Differences between LDAP 2 and 3 Protocols
Articles and Tips: article
Senior Technical Writer
Developer Information
01 Aug 1998
Defines the differences in the server/client interactions between the two versions of LDAP. Also explains how those interactions are handled in the protocol to help you anticipate the responses from the server to your client's requests. Provides a summary of the protocol differences, including information on the LDAPMessage and LDAPResult structures.
- Introduction
- LDAPMessage and LDAPResult
- Bind Operation
- Search operation
- The Modify, Add, Delete, Compare, and Abandon Operations
- Required Elements for LDAP 2 and 3
- Conclusion
Introduction
Last month, I said that this article would be about configuring LDAP services for NDS. However, I have received requests for some reference material showing the changes between the LDAP 2 and 3 protocols. So, I decided to extend this series of articles. This article will define the differences in the protocols between the two LDAP versions.
The LDAP protocol uses a lightweight Basic Encoding Rules (BER) and Abstract Syntax Notation 1 (ASN.1) syntax. So, the protocols defined in this article will also be encoded in BER and use ASN.1 syntax. The ISO 8825 standard describes BER. The ISO 8824 standard describes ASN.1. These Web pages provide a basic description of BER and ASN.1:
http://www.itu.ch/itudoc/itu-t/rec/x/x200-499/x209_24177.html
http://www.salford.ac.uk/iti/books/osi/chap8.html
http://ganges.cs.tcd.ie/4ba2/presentation/syntaxandrep.html
This article provides a summary of the protocol differences. For more detailed information about the protocol structures and the operations for LDAP 3, see RFCs 2251 - 2256. (Of course, as soon as last month's article was published with a table of URLs for the LDAP protocols, those Web pages became outdated. Currently, I am finding the RFCs at this URL: http://www.faqs.org/rfcs.)
LDAPMessage and LDAPResult
The most obvious differences between the two LDAP versions are in the LDAPMessage and LDAPResult structures. These are probably the most obvious because LDAPMessage encapsulates all protocol operations in a common envelope. LDAPResult is the construct the server returns to the client. LDAPResult contains the final status of a protocol operation request.
LDAPMessage
LDAPMessage provides an envelope containing common fields required in all protocol exchanges.
This is the LDAPMessage structure for LDAP 2.
LDAPMessage ::= SEQUENCE { messageID MessageID, protocolOpCHOICE { bindRequest BindRequest, bindResponse BindResponse, unbindRequest UnbindRequest, searchRequest SearchRequest, searchResponse SearchResponse, /*Not in version 3*/ modifyRequest ModifyRequest, modifyResponse ModifyResponse, addRequest AddRequest, addResponse AddResponse, delRequest DelRequest, delResponse DelResponse, modifyRDNRequest ModifyRDNRequest, modifyRDNResponse ModifyRDNResponse, compareDNRequest CompareRequest, compareDNResponse CompareResponse, abandonRequest AbandonRequest } } MessageID ::= INTEGER (0 .. maxInt)
This is the LDAPMessage structure for LDAP 3.
LDAPMessage ::= SEQUENCE { messageID MessageID, protocolOp CHOICE { bindRequest BindRequest, bindResponse BindResponse, unbindRequest UnbindRequest, searchRequest SearchRequest, searchResEntry SearchResultEntry, /*new*/ searchResDone SearchResultDone, /*new*/ searchResRef SearchResultReference, /*new*/ modifyRequest ModifyRequest, modifyResponse ModifyResponse, addRequest AddRequest, addResponse AddResponse, delRequest DelRequest, delResponse DelResponse, modDNRequest ModifyDNRequest, modDNResponse ModifyDNResponse, compareRequest CompareRequest, compareResponse CompareResponse, abandonRequest AbandonRequest, extendedReq ExtendedRequest, /*new*/ extendedResp ExtendedResponse /*new*/ }, controls [0] Controls OPTIONAL /*new*/ } MessageID ::= INTEGER (0 .. maxInt)
Note that LDAP 3 has replaced the SearchResponse field with these new fields.
searchResEntry SearchResultEntry, searchResDone SearchResultDone, searchResRef SearchResultReference,
Figure 1 defines these fields' new data types.
Figure 1: New data types for LDAPMessage search fields.
The LDAP 3 Search operation uses these new fields. The server returns the results of the search in Search Responses. The Search Response is an LDAP message that contains either the searchResEntry, searchResdone, searchResRef, or extendedResp fields.
The Search operation uses the extendedResp field if the original LDAPMessage used the extendReq field. These fields are new fields at the end of LDAPMessage:
extendedReq ExtendedRequest, extendedResp ExtendedResponse
Figure 2 defines these fields' new data types.
Figure 2: New data types for LDAPMessage extension fields.
"LDAPOID" is a notation that indicates this string's permitted value is an Object Identifier represented in UTF-8 encoded, dotted-decimal. The value 1.3.6.1.4.1.1466.1.2.3 is an example of an acceptable value for this string type. Object Identifiers are unique and registered by IANA. Novell manages their own Object Identifiers.
The extendedRequest and extendedResponse data types enable clients to make requests and receive responses with predefined syntaxes and semantics. Each request must have a unique Object Identifier assigned to it. The rootDSE supportedExtension field holds a list of the extensions the server supports. So, before the client requests an extension, it should look at the server's rootDSE supportedExtension field to see if the extension is supported.
Whenever a server sees an extendedReq field in the LDAPMessage, it will respond with an LDAPMessage that contains an extendedResp field.
If the server does not recognize the request name, it will return only the response fields in LDAPResult that contain the protocolError result code.
In LDAP 2 the only common field was the Message ID. Version 3 adds a common Controls field so that the LDAP protocol can be extended. The control field looks like this:
controls [0] Controls OPTIONAL
Controls sent in the LDAPMessage apply only to the current request and are not saved. Figure 3 defines the control field.
Figure 3: The LDAPMessage control field. Because the controls field is an array, multiple controls can be stacked in a single LDAPMessage.
These field definitions are:
controlType A LDAPOID string that uniquely identifies the control so that control names don't conflict. The rootDSE supportedControl field contains a list for controls the server supports. The client should first look at the server's rootDSE supportedControl field before it requests a control.
criticality Either TRUE or FALSE. It's default value is FALSE. A control can be always noncritical, always critical, or critical at the client's option.
controlValue Contains any information associated with the control. Servers must be prepared in order to handle arbitrary contents of the controlValue octet string, including zero bytes. This field is absent if no value information is associated with this control.
The server uses this structure's controlType and criticality fields like this:
If the server recognizes the control type and it's appropriate for the requested operation, the server will use the control while performing the operation.
If the server does not recognize the control type and the criticality field is TRUE, the server will not perform the operation. Instead, it will return the "unsupportedCriticalExtension" resultCode.
If the control is not appropriate for the requested operation and the criticality field is TRUE, the server will not perform the operation. Instead, it must return the "unsupportedCriticalExtension" resultCode.
If the server does not recognize the control, or the control is inappropriate for the operation, and the criticality field is FALSE, the server will ignore the field.
Servers list the controls they recognize in the supportedControl attribute in the root DSE.
LDAPResult
LDAPResult is the construct that contains the success or failure messages from the server to the client. LDAPResult also indicates the final status of a protocol operation request.
This is the LDAPResult structure for LDAP 2.
LDAPResult ::= SEQUENCE { resultCode ENUMERATED { success (0), operationsError (1), protocolError (2), timeLimitExceeded (3), sizeLimitExceeded (4), compareFalse (5), compareTrue (6), authMethodNotSupported (7), strongAuthRequired (8), noSuchAttribute (16), undefinedAttributeType (17), inappropriateMatching (18), constraintViolation (19), attributeOrValueExists (20), invalidAttributeSyntax (21), noSuchObject (32), aliasProblem (33), invalidDNSyntax (34), isLeaf (35), aliasDereferencingProblem (36), inappropriateAuthentication (48), invalidCredentials (49), insufficientAccessRights (50), busy (51), unavailable (52), unwillingToPerform (53), loopDetect (54), namingViolation (64), objectClassViolation (65), notAllowedOnNonLeaf (66), notAllowedOnRDN (67), entryAlreadyExists (68), objectClassModsProhibited (69), other (80) }, matchedDN LDAPDN, errorMessage LDAPString }
This is the LDAPResult structure for LDAP 3.
LDAPResult ::= SEQUENCE { resultCode ENUMERATED { success (0), operationsError (1), protocolError (2), timeLimitExceeded (3), sizeLimitExceeded (4), compareFalse (5), compareTrue (6), authMethodNotSupported (7), strongAuthRequired (8), -- 9 reserved -- referral (10), /*new*/ adminLimitExceeded (11), /*new*/ unavailableCriticalExtension (12), /*new*/ confidentialityRequired (13), /*new*/ saslBindInProgress (14), /*new*/ noSuchAttribute (16), undefinedAttributeType (17), inappropriateMatching (18), constraintViolation (19), attributeOrValueExists (20), invalidAttributeSyntax (21), -- 22-31 unused -- noSuchObject (32), aliasProblem (33), invalidDNSyntax (34), -- 35 reserved for undefined isLeaf -- aliasDereferencingProblem (36), -- 37-47 unused -- inappropriateAuthentication (48), invalidCredentials (49), insufficientAccessRights (50), busy (51), unavailable (52), unwillingToPerform (53), loopDetect (54), -- 55-63 unused -- namingViolation (64), objectClassViolation (65), notAllowedOnNonLeaf (66), notAllowedOnRDN (67), entryAlreadyExists (68), objectClassModsProhibited (69), -- 70 reserved for CLDAP -- affectsMultipleDSAs (71), /*new*/ -- 72-79 unused -- other (80) }, -- 81-90 reserved for APIs -- matchedDN LDAPDN, errorMessage LDAPString, referral [3] Referral OPTIONAL }
Note that LDAP 3 contains the following new fields:
referral (10), adminLimitExceeded (11), unavailableCriticalExtension (12), confidentialityRequired (13), saslBindInProgress (14), affectsMultipleDSAs (71), referral [3] Referral OPTIONAL
LDAPResult's new referral field allows the server to return a referral to a client. The referral error indicates that the contacted server does not have the requested information (or entry). LDAPResult.referral is present if the value in LDAPResult.resultCode is referral and does not have any other result codes. Then, LDAPResult.referral contains a reference to another server (or directory service) the client cannot access. A referral must contain at least one URL. A server can return a referral in response to any operation except Unbind and Abandon.
The referral field is defined by:
Referral ::= SEQUENCE OF LDAPURL (one or more URLs) LDAPURL ::= LDAPString /*The string is limited to characters permitted in URLs*/
If the client wants to continue an operation, it must follow the referral by contacting any one of the servers listed in the referral field. All the URLs returned in the field must be equally able to continue the operation.
If the search spans multiple naming contexts and the client must contact several different servers to complete the operation, the server does not return a referral, but returns continuation references.
LDAP 3 adds the following rules:
Treat all the result codes with the exception of success, compareFalse and compareTrue as meaning that the operation could not be completed.
Most of the result codes are based on problem indications from X.511 error data types.
Result codes from 16-21 indicate an attribute problem.
Codes 32, 33, 34, and 36 indicate a NameProblem.
Codes 48, 49, and 50 indicate a SecurityProblem.
Codes 51 to 54 indicate a ServiceProblem
Codes 64 to 69 and 71 indicate an Update problem.
The client must treat any result code not listed above as an unknown error condition.
The server can use the errorMessage field to return a string containing a textual, human-readable error diagnostic. However, because these error diagnostics are not standardized, implementations cannot rely on the returned values. If the field does not contain a textual diagnostic, it must contain a zero length string.
Bind Operation
The Bind operation allows the client to authenticate to the server. The Bind operation is the first request the server receives from a client.
Bind Request
The LDAP 2 Bind Request is defined as:
[APPLICATION 0] SEQUENCE { version INTEGER (1 .. 127), name LDAPDN, authentication CHOICE { simple [0] OCTET STRING, krbv42LDAP [1] OCTET STRING, krbv42DSA [2] OCTET STRING } }
The LDAP 3 Bind request is defined as:
BindRequest ::= [APPLICATION 0] SEQUENCE { version INTEGER (1 ... 127), name LDAPDN authentication AuthenticationChoice }
This structure introduces a new data type, AuthenticationChoice. Figure 4 defines the data type.
Figure 4: AuthenticationChoice data type.
Because LDAP 3 allows SASL connections, some of the parameters are used a little differently than they were in LDAP 2. Parameters of the Bind Request are:
version The client and server do not negotiate version numbers. The client just sets this parameter to the LDAP version it is using. If the client requests protocol version 2, a server that supports the version 2 protocol will not return any protocol fields that are specific to version 3.
name The name of the Directory object that the client wishes to bind as. This field may take on a null value (a zero length string) for the purposes of anonymous binds.
authentication If the Bind Request contains a name, this field has the information used to authenticate that name. LDAP 3 adds the SASL possibilities to this field.
Perhaps the most notable change in the Bind Request sequencing is that in LDAP 2 the client must send a Bind Request in the first packet of the connection. In LDAP 3, the client may request any operation in the first packet, and the server must then open an unauthenticated connection.
Bind Response
The Bind Response has also changed for LDAP 3. This is the Bind Response for LDAP 2:
BindResponse = [APPLICATION 1] LDAPResult
This is the Bind Response for LDAP 3:
BindResponse ::= [APPLICATION 1] sequence { COMPONENTS OF LDAPResult, ServerSASLCreds [7] OCTET STRING OPTIONAL }
In LDAP 3, the Bind Response has changed to allow for the SASL connection. The serverSASLCreds field is part of the SASL-defined bind mechanism. If the bound client does not require the server to return information to the client, this field is not included in the result.
Also, LDAP 3 allows some result codes in the Bind Response that accommodate referrals and SASL connections. These are the result codes:
operationsError The server encountered an internal error.
protocolError The request had an unrecognized version number or incorrect packet structure.
authMethodNotSupported The request contained an unrecognized SASL mechanism name.
strongAuthRequired The server requires a SASL connection.
referral The client should send the request to another server.
saslBindInProgress The client must send a new Bind request, using the same SASL mechanism, to continue the authentication process.
inappropriateAuthentication The client must send credentials.
invalidCredentials The server could not process the credentials.
unavailable The server is shutting down.
Search operation
LDAP 3 had a few changes to the Search operation's SearchRequest and Search response structures.
The SearchRequest structure
Except for an additional field and a new data type, most of the changes to the Search Request structure are minor.
This is the LDAP 2 structure.
SearchRequest ::= [APPLICATION 3] SEQUENCE { baseObject LDAPDN, scope ENUMERATED { baseObject (0), singleLevel (1), wholeSubtree (2) }, derefAliases ENUMERATED { neverDerefAliases (0), derefInSearching (1), derefFindingBaseObj (2), derefAlways (3) }, sizeLimit INTEGER (0 .. maxInt), timeLimit INTEGER (0 .. maxInt), attrsOnly BOOLEAN, filter Filter, attributes SEQUENCE OF AttributeType } Filter ::= CHOICE { and [0] SET OF Filter, or [1] SET OF Filter, not [2] Filter, equalityMatch [3] AttributeValueAssertion, substrings [4] SubstringFilter, greaterOrEqual [5] AttributeValueAssertion, lessOrEqual [6] AttributeValueAssertion, present [7] AttributeType, approxMatch [8] AttributeValueAssertion } SubstringFilter SEQUENCE { type AttributeType, SEQUENCE OF CHOICE { initial [0] LDAPString, any [1] LDAPString, final [2] LDAPString } }
This the Search structure for LDAP 3.
SearchRequest ::= [APPLICATION 3] SEQUENCE { baseObject LDAPDN, scope ENUMERATED { baseObject (0), singleLevel (1), wholeSubtree (2) }, derefAliases ENUMERATED { neverDerefAliases (0), derefInSearching (1), derefFindingBaseObj (2), derefAlways (3) }, sizeLimit INTEGER (0 .. maxInt), timeLimit INTEGER (0 .. maxInt), typesOnly BOOLEAN, filter Filter, attributes AttributeDescriptionList } Filter ::= CHOICE { and [0] SET OF Filter, or [1] SET OF Filter, not [2] Filter, equalityMatch [3] AttributeValueAssertion, substrings [4] SubstringFilter, greaterOrEqual [5] AttributeValueAssertion, lessOrEqual [6] AttributeValueAssertion, present [7] AttributeDescription, approxMatch [8] AttributeValueAssertion, extensibleMatch [9] MatchingRuleAssertion /*new*/ } SubstringFilter ::= SEQUENCE { type AttributeDescription, /*at least one must be present*/ substrings SEQUENCE OF CHOICE { initial [0] LDAPString, any [1] LDAPString, final [2] LDAPString } } MatchingRuleAssertion ::= SEQUENCE { /*new*/ matchingRule [1] MatchingRuleId OPTIONAL, type [2] AttributeDescription OPTIONAL, matchValue [3] AssertionValue, dnAttributes [4] BOOLEAN DEFAULT FALSE }
These lines in the LDAP 2 Search structure, "attrsOnly BOOLEAN,", "attributes SEQUENCE OF AttributeType", and "type AttributeType," are changed to "typesOnly BOOLEAN,", "attributes AttributeDescriptionList", and "type Attribute Description," in the LDAP 3 Search structure. Although the structures are renamed, their definitions remain the same. None of these changes affect the Search operation.
The LDAP 3 Search adds the field "extensibleMatch [9] MatchingRuleAssertion". The new structure MatchingRuleAssertion defines the type of the new extensibleMatch field. The MatchingRuleAssertion structure is defined as:
MatchingRuleAssertion ::= SEQUENCE { matchingRule [1] MatchingRuleId OPTIONAL, type [2] AttributeDescription OPTIONAL, matchValue [3] AssertionValue, dnAttributes [4] BOOLEAN DEFAULT FALSE }
The presence, absence and values of this structure's fields determine the type of match the Search operation will perform.
Note: If the matchingRule field is absent, the type field must be present. The dnAttributes field is present so that multiple versions of generic matching rule are not needed. The following table defines the effect of the structure's possible field condition.
Effects of matchingRuleAssertion Structure Fields on Search Operation
Field Name
|
Field Condition
|
Effects on Search Operation
|
matchingRule |
Present |
Equality match is performed for the type defined in the type field. |
type |
Absent |
|
dnAttributes |
Not applicable |
Field Name
|
Field Condition
|
Effect on Search Operation
|
matchingRule |
Present |
The matchValue field value is compared against all attributes in an entry that supports the matchingRule field value, and the matchingRule field value determines the syntax for the assertion value. |
type |
Absent |
|
dnAttributes |
Not applicable |
Field Name
|
Field Condition
|
Effect on Search Operation
|
matchingRule |
Present |
The matchingRule must be one permitted for use with the value in the type field. If it is not, the Filter item evaluates to undefined. |
type |
Present |
|
dnAttributes |
Not applicable |
Field Name
|
Field Condition
|
Effect on Search Operation
|
matchingRule |
Not applicable |
The match is applied against all the attributes in an entry's distinguished name as well, and also evaluates to TRUE if the distinguished name has at least one attribute for which the filter evaluates to TRUE. |
type |
Not applicable |
|
dnAttributes |
TRUE |
The Search Response and Search Result structures
In LDAP 2, when the server has finished the search, it returns the results in Search Responses. LDAP 2 defined the Search Response as:
Search Response ::= CHOICE { entry [APPLICATION 4] SEQUENCE { objectName LDAPDN, attributes SEQUENCE OF SEQUENCE { AttributeType, SET OF AttributeValue } }, resultCode [APPLICATION 5] LDAPResult }
In LDAP 3, the Search Response is returned in LDAP messages containing either SearchResultEntry, SearchResultReference, ExtendedResponse or SearchResultDone data types.
For more information about these fields, see the "LDAPMessage" section.
The server can send the following search responses to a client:
Zero or more responses containing SearchResultEntry, one for each entry found during the search.
Also, zero or more responses containing SearchResultReference, one for each area not explored by this server during the search.
The SearchResultEntry and SearchResultReference packets can come in any order.
Each entry returned in a SearchResultEntry will contain all attributes, complete with associated values if necessary, as specified in the attributes field of the Search Request.
After all the SearchResultReference responses and all SearchResultEntry responses, the server returns a response containing the SearchResultDone, which contains an indication of success, or detailing any errors that have occurred.
One or more SearchResultReference responses with a reference to another set of servers for continuing the operation.
The Modify RDN and Modify DN Operations
LDAP 2 has a Modify RDN operation that allows clients to change the last component of an entry's name in the directory.
The ModifyRDN operation is defined as:
ModifyRDNRequest ::= [APPLICATION 12] SEQUENCE { entry LDAPDN, newrdn RelativeLDAPDN, deleteoldrdn BOOLEAN }
This structure's parameters are defined as:
entry The name of the entry to be changed.
newrdn The RDN that will form the last component of the new name.
deleteoldrdn A boolean parameter that controls whether the old RDN attribute values should be retained as attributes of the entry or deleted from the entry.
When the server gets the Modify RDN request, it will attempt to make the name change. The server then returns the result of the name change in a Modify RDN Response, defined as:
ModifyRDNResponse ::= [APPLICATION 13] LDAPResult
The attributes that make up the old RDN are deleted from the entry, or kept, depending on the setting of the deleteoldrdn parameter.
LDAP 3 replaced the Modify RDN operation with the Modify DN operation. This operation allows a client to change the leftmost (or least significant) component of an entry's name. It also allows a client to move a subtree of entries to a new location in the directory. The Modify DN Request is defined as:
ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { entry LDAPDN, newrdn RelativeLDAPDN, deleteoldrdn BOOLEAN, newSuperior [0] LDAPDN OPTIONAL }
Parameters of the Modify DN Request are:
entry The Distinguished Name of the entry to be changed. This entry may or may not have subordinate entries.
newrdn The RDN that will form the least significant component of the entry's new name.
deleteoldrdn A boolean parameter that controls whether the old RDN attribute values are to be retained as attributes of the entry, or deleted from the entry.
newSuperior If this field is present, it contains the Distinguished Name of the entry which will become the immediate superior of the existing entry.
When the server receives a Modify DN Request, it tries to change the name and returns the result in the Modify DN Response, defined as:
ModifyDNResponse = [APPLICATION 13] LDAPResult
The Modify, Add, Delete, Compare, and Abandon Operations
These operations are the same for both LDAP 2 and 3.
Required Elements for LDAP 2 and 3
Many of the new protocol elements are required for LDAP applications, some are in the "should" (or recommended) category. According to RFC 2119, when an element is labeled should, it means "that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course." The next table lists which protocol elements are required and which are labeled as should.
Required Protocol Elements
Protocol elements
|
RFC
|
LDAP2
|
LDAP3
|
Industry
|
|||||
Must |
Should |
May |
Must |
Should |
May |
Standard |
Compliant |
||
Auxiliary classes assigned to entries |
2252 section 4.4, 6.1 |
X |
|||||||
Bind authentication Cleartext |
1777 section 4.1, 6 |
X |
X |
||||||
Bind authentication Kerberos |
1777 section 4.1, 6 |
X |
Reserved |
||||||
Bind authentication SASL |
2251 section 4.2, 7 |
X |
|||||||
Binary encoded attribute generation and parsing |
2252 section 4.3.1 |
X |
|||||||
Referrals not returned to clients |
1777 section 2 |
X |
|||||||
Referrals returned to clients |
2251 section 4.1.11 |
X |
|||||||
Root DSE and subschema entries maintained and accessible to clients |
2251 section 3.2.2, 3.4 |
X |
|||||||
Attribute types recognized by servers |
2252 section 5 |
X |
|||||||
Standard operational attributes maintained |
2252 section 5.1 |
X |
|||||||
LDAPMessage Controls |
2251 section 4.1.12 |
X |
|||||||
LDAPMessage Control field recognized and parsed for criticality |
2251 section 4.1.12 |
X |
|||||||
LDAPMessage ExtendedRequest recognition |
2251 section 4.12 |
X |
|||||||
LDAPMessage ModifyDNRequest support |
2251 section 4.9 |
X |
Conclusion
This article went deeper into the LDAP internals than I had originally intended this series to go. But, understanding the differences in the server/client interactions between the two LDAP versions and how those interactions are handled in the protocol should help you anticipate the responses from the server to your client's requests.
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.