RFC 2251

Lightweight Directory Access Protocol (v3)

๐Ÿ“… published December 1997, from ietf

RFC 2251 ๐Ÿ“œ Title Block

Okay bestie, here's the vibe check on the paper itself ๐Ÿ’…

  • Network Working Group ๐ŸŒธ
  • RFC 2251: "Lightweight Directory Access Protocol (v3)" ๐Ÿฆ‹
  • Authors: M. Wahl (Critical Angle Inc.), T. Howes (Netscape Communications Corp.), S. Kille (Isode Limited) ๐Ÿ‘‘
  • Category: Standards Track โญ
  • Date: December 1997 ๐ŸŽ€
  • Obsoletes / Updates: the title block doesn't list anything under either one ๐Ÿ™ˆ

1. Status of this Memo โœจ

This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited. ๐Ÿ’–

Copyright (C) The Internet Society (1997). All Rights Reserved. ๐ŸŒˆ

IESG Note ๐Ÿซถ

This document describes a directory access protocol that provides both read and update access. Update access requires secure authentication, but this document does not mandate implementation of any satisfactory authentication mechanisms. ๐Ÿ”ฅ

In accordance with RFC 2026, section 4.4.1, this specification is being approved by IESG as a Proposed Standard despite this limitation, for the following reasons:

  • a. to encourage implementation and interoperability testing of these protocols (with or without update access) before they are deployed, and
  • b. to encourage deployment and use of these protocols in read-only applications. (e.g. applications where LDAPv3 is used as a query language for directories which are updated by some secure mechanism other than LDAP), and
  • c. to avoid delaying the advancement and deployment of other Internet standards-track protocols which require the ability to query, but not update, LDAPv3 directory servers.

Readers are hereby warned that until mandatory authentication mechanisms are standardized, clients and servers written according to this specification which make use of update functionality are "UNLIKELY TO INTEROPERATE, or MAY INTEROPERATE ONLY IF AUTHENTICATION IS REDUCED TO AN UNACCEPTABLY WEAK LEVEL." ๐Ÿ˜ญ

Implementors are hereby discouraged from deploying LDAPv3 clients or servers which implement the update functionality, until a Proposed Standard for mandatory authentication in LDAPv3 has been approved and published as an RFC. ๐Ÿ™ˆ

Table of Contents ๐Ÿ—‚๏ธ

   1.  Status of this Memo ....................................  1
       Copyright Notice .......................................  1
       IESG Note ..............................................  1
   2.  Abstract ...............................................  3
   3.  Models .................................................  4
   3.1. Protocol Model ........................................  4
   3.2. Data Model ............................................  5
   3.2.1. Attributes of Entries ...............................  5
   3.2.2. Subschema Entries and Subentries ....................  7
   3.3. Relationship to X.500 .................................  8
   3.4. Server-specific Data Requirements .....................  8
   4.  Elements of Protocol ...................................  9
   4.1. Common Elements .......................................  9
   4.1.1. Message Envelope ....................................  9
   4.1.1.1. Message ID ........................................ 11
   4.1.2. String Types ........................................ 11
   4.1.3. Distinguished Name and Relative Distinguished Name .. 11
   4.1.4. Attribute Type ...................................... 12
   4.1.5. Attribute Description ............................... 13
   4.1.5.1. Binary Option ..................................... 14
   4.1.6. Attribute Value ..................................... 14
   4.1.7. Attribute Value Assertion ........................... 15
   4.1.8. Attribute ........................................... 15
   4.1.9. Matching Rule Identifier ............................ 15
   4.1.10. Result Message ..................................... 16
   4.1.11. Referral ........................................... 18
   4.1.12. Controls ........................................... 19
   4.2. Bind Operation ........................................ 20
   4.2.1. Sequencing of the Bind Request ...................... 21
   4.2.2. Authentication and Other Security Services .......... 22
   4.2.3. Bind Response ....................................... 23
   4.3. Unbind Operation ...................................... 24
   4.4. Unsolicited Notification .............................. 24
   4.4.1. Notice of Disconnection ............................. 24
   4.5. Search Operation ...................................... 25
   4.5.1. Search Request ...................................... 25
   4.5.2. Search Result ....................................... 29
   4.5.3. Continuation References in the Search Result ........ 31
   4.5.3.1. Example ........................................... 31
   4.6. Modify Operation ...................................... 32
   4.7. Add Operation ......................................... 34
   4.8. Delete Operation ...................................... 35
   4.9. Modify DN Operation ................................... 36
   4.10. Compare Operation .................................... 37
   4.11. Abandon Operation .................................... 38
   4.12. Extended Operation ................................... 38
   5.  Protocol Element Encodings and Transfer ................ 39
   5.1. Mapping Onto BER-based Transport Services ............. 39
   5.2. Transfer Protocols .................................... 40
   5.2.1. Transmission Control Protocol (TCP) ................. 40
   6.  Implementation Guidelines .............................. 40
   6.1. Server Implementations ................................ 40
   6.2. Client Implementations ................................ 40
   7.  Security Considerations ................................ 41
   8.  Acknowledgements ....................................... 41
   9.  Bibliography ........................................... 41
   10. Authors' Addresses ..................................... 42
   Appendix A - Complete ASN.1 Definition ..................... 44
   Full Copyright Statement ................................... 50

2. Abstract ๐ŸŒŸ

The protocol described in this document is designed to provide access to directories supporting the X.500 models, while not incurring the resource requirements of the X.500 Directory Access Protocol (DAP). This protocol is specifically targeted at management applications and browser applications that provide read/write interactive access to directories. When used with a directory supporting the X.500 protocols, it is intended to be a complement to the X.500 DAP. ๐Ÿ’…

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", and "MAY" in this document are to be interpreted as described in RFC 2119 [10]. ๐ŸŽ€

Key aspects of this version of LDAP are: โœจ

  • All protocol elements of LDAPv2 (RFC 1777) are supported. The protocol is carried directly over TCP or other transport, bypassing much of the session/presentation overhead of X.500 DAP.
  • Most protocol data elements can be encoded as ordinary strings (e.g., Distinguished Names).
  • Referrals to other servers may be returned.
  • SASL mechanisms may be used with LDAP to provide association security services.
  • Attribute values and Distinguished Names have been internationalized through the use of the ISO 10646 character set.
  • The protocol can be extended to support new operations, and controls may be used to extend existing operations.
  • Schema is published in the directory for use by clients.

3. Models ๐Ÿงš

Interest in X.500 [1] directory technologies in the Internet has led to efforts to reduce the high cost of entry associated with use of these technologies. This document continues the efforts to define directory protocol alternatives, updating the LDAP [2] protocol specification. ๐Ÿฆ‹

3.1. Protocol Model

The general model adopted by this protocol is one of clients performing protocol operations against servers. In this model, a client transmits a protocol request describing the operation to be performed to a server. The server is then responsible for performing the necessary operation(s) in the directory. Upon completion of the operation(s), the server returns a response containing any results or errors to the requesting client. ๐Ÿ’œ

In keeping with the goal of easing the costs associated with use of the directory, it is an objective of this protocol to minimize the complexity of clients so as to facilitate widespread deployment of applications capable of using the directory. ๐ŸŒธ

Note that although servers are required to return responses whenever such responses are defined in the protocol, there is no requirement for synchronous behavior on the part of either clients or servers. Requests and responses for multiple operations may be exchanged between a client and server in any order, provided the client eventually receives a response for every request that requires one. ๐Ÿ“

In LDAP versions 1 and 2, no provision was made for protocol servers returning referrals to clients. However, for improved performance and distribution this version of the protocol permits servers to return to clients referrals to other servers. This allows servers to offload the work of contacting other servers to progress operations. ๐Ÿ”ฅ

Note that the core protocol operations defined in this document can be mapped to a strict subset of the X.500(1997) directory abstract service, so it can be cleanly provided by the DAP. However there is not a one-to-one mapping between LDAP protocol operations and DAP operations: server implementations acting as a gateway to X.500 directories may need to make multiple DAP requests. ๐Ÿซถ

3.2. Data Model

This section provides a brief introduction to the X.500 data model, as used by LDAP. ๐Ÿ“š

The LDAP protocol assumes there are one or more servers which jointly provide access to a Directory Information Tree (DIT). The tree is made up of entries. Entries have names: one or more attribute values from the entry form its relative distinguished name (RDN), which "MUST" be unique among all its siblings. The concatenation of the relative distinguished names of the sequence of entries from a particular entry to an immediate subordinate of the root of the tree forms that entry's Distinguished Name (DN), which is unique in the tree. An example of a Distinguished Name is: ๐ŸŒณ

CN=Steve Kille, O=Isode Limited, C=GB

Some servers may hold cache or shadow copies of entries, which can be used to answer search and comparison queries, but will return referrals or contact other servers if modification operations are requested. ๐Ÿ’…

Servers which perform caching or shadowing "MUST" ensure that they do not violate any access control constraints placed on the data by the originating server. ๐Ÿšจ

The largest collection of entries, starting at an entry that is mastered by a particular server, and including all its subordinates and their subordinates, down to the entries which are mastered by different servers, is termed a naming context. The root of the DIT is a DSA-specific Entry (DSE) and not part of any naming context: each server has different attribute values in the root DSE. (DSA is an X.500 term for the directory server.) ๐Ÿ‘‘


That's part 1 of 11 done bestie ๐Ÿฆ‹ more parts coming, so stay tuned ๐Ÿ’–

3.2.1. Attributes of Entries โœจ

Okay so entries are basically a bunch of attributes ๐Ÿ’– An attribute is a type with one or more values attached to it. The attribute type gets a short descriptive name AND an OID (object identifier) ๐ŸŽ€ The type decides whether an entry can hold more than one value of that attribute, what syntax those values have to follow, what kinds of matching you can do on them, and some other stuff too ๐Ÿฆ‹

Here's an example: "mail" ๐Ÿ“ง It can have one or more values, they must be IA5 (ASCII) strings, and it's case insensitive. So foo@bar.com will match FOO@BAR.COM. Iconic ๐Ÿ’…

Schema is the whole collection of attribute type definitions, object class definitions, and other info a server uses to figure out how to match a filter or an attribute value assertion (in a compare operation) against an entry's attributes. It also helps the server decide whether to allow add and modify operations ๐Ÿงš The schema for LDAP is defined in [5] and [6], and other documents can add more schema elements too ๐ŸŒˆ

Each entry MUST have an objectClass attribute ๐Ÿ‘‘ The objectClass attribute lists the object classes of an entry. Together with the system and user schema, those decide which attributes the entry is allowed to have. Clients can change the values of this attribute, but the objectClass attribute itself can't be removed ๐Ÿ˜ญ Servers may restrict changes to this attribute so the entry's basic structural class can't be swapped out (so no turning a person into a country, bestie ๐Ÿ’€). When you create an entry or add an objectClass value, all the superclasses of the named classes get added automatically if they aren't already there. The client has to supply values for any mandatory attributes of those new superclasses ๐Ÿซถ

Some attributes are called operational attributes, and servers use them to run the directory system itself ๐ŸŒธ They don't come back in search results unless you ask for them by name. Non-operational attributes, like "mail", still get their schema and syntax rules enforced by servers, but servers generally don't do anything with their values ๐Ÿ“

Servers MUST NOT permit clients to add attributes to an entry unless those attributes are allowed by the object class definitions, by the schema controlling that entry (listed in the subschema, see below), or are operational attributes the server knows about and uses for administration. Also, there's a special objectClass called extensibleObject defined in [5] that lets all user attributes be present in an entry, so it's giving wide open ๐Ÿ”ฅ

Entries MAY contain, among others, the following operational attributes, defined in [5]. The server maintains these automatically, and clients can't modify them ๐Ÿ™ˆ

  • creatorsName: the Distinguished Name of the user who added this entry to the directory.
  • createTimestamp: the time this entry was added to the directory.
  • modifiersName: the Distinguished Name of the user who last modified this entry.
  • modifyTimestamp: the time this entry was last modified.
  • subschemaSubentry: the Distinguished Name of the subschema entry (or subentry) that controls the schema for this entry.

3.2.2. Subschema Entries and Subentries ๐Ÿฆ‹

Subschema entries are where info about the directory schema lives, especially the object classes and attribute types that directory servers support ๐Ÿ’œ One subschema entry holds all the schema definitions used by entries in a particular part of the directory tree.

Servers that follow the X.500(93) models SHOULD implement subschema using the X.500 subschema mechanisms, which means these subschemas aren't ordinary entries ๐ŸŽ€ LDAP clients SHOULD NOT assume that servers implement any other parts of X.500 subschema ๐Ÿ™… A server that masters entries and lets clients modify them MUST implement and provide access to these subschema entries, so its clients can find out which attributes and object classes are allowed to be present. It is strongly recommended that all other servers implement this as well ๐Ÿซถ

The following four attributes MUST be present in all subschema entries โœจ

  • cn: this attribute MUST be used to form the RDN of the subschema entry.
  • objectClass: the attribute MUST have at least the values top and subschema.
  • objectClasses: each value of this attribute specifies an object class known to the server.
  • attributeTypes: each value of this attribute specifies an attribute type known to the server.

These are defined in [5]. Other attributes MAY be present in subschema entries to show extra supported capabilities ๐ŸŒˆ Those include matchingRules, matchingRuleUse, dITStructureRules, dITContentRules, nameForms and ldapSyntaxes.

Servers SHOULD provide the attributes createTimestamp and modifyTimestamp in subschema entries, so clients can keep their schema caches up to date ๐Ÿ“

Clients MUST only retrieve attributes from a subschema entry by doing a base object search of the entry, where the search filter is (objectClass=subschema). (This lets LDAPv3 servers that gateway to X.500(93) notice that subentry info is being requested. Smart, right? ๐Ÿงš)

3.3. Relationship to X.500 ๐Ÿ’–

This document defines LDAP in terms of X.500, as an X.500 access mechanism ๐ŸŽ€ An LDAP server MUST act in accordance with the X.500(1993) series of ITU recommendations when it provides the service. BUT it's not required for an LDAP server to use any X.500 protocols to do that ๐Ÿฆ‹ LDAP can be mapped onto any other directory system, as long as the X.500 data and service model used in LDAP isn't violated in the LDAP interface ๐Ÿซถ

3.4. Server-specific Data Requirements ๐ŸŒธ

An LDAP server MUST provide info about itself and other info that's specific to each server ๐Ÿชž This is stored as a group of attributes in the root DSE (DSA-Specific Entry), which is named with the zero-length LDAPDN. Clients can read these attributes with a base object search of the root using the filter (objectClass=*), but access control restrictions still apply ๐Ÿ”’ The root DSE MUST NOT be included if the client does a subtree search starting from the root.

Servers may allow clients to modify these attributes ๐Ÿ’…

The following root DSE attributes are defined in section 5 of [5]. Other documents may define more attributes too โœจ

  • namingContexts: naming contexts held in the server. Naming contexts are defined in section 17 of X.501 [6].
  • subschemaSubentry: subschema entries (or subentries) known by this server.
  • altServer: alternative servers in case this one becomes unavailable later.
  • supportedExtension: list of supported extended operations.
  • supportedControl: list of supported controls.
  • supportedSASLMechanisms: list of supported SASL security features.
  • supportedLDAPVersion: LDAP versions implemented by the server.

If the server doesn't master entries and doesn't know where the schema info is, the subschemaSubentry attribute won't be present in the root DSE ๐Ÿ™ˆ If the server masters directory entries under one or more schema rules, there may be any number of values of the subschemaSubentry attribute in the root DSE ๐ŸŒˆ

4. Elements of Protocol โœจ

The LDAP protocol is described using Abstract Syntax Notation 1 (ASN.1) [3], and it's usually transferred using a subset of ASN.1 Basic Encoding Rules [11] ๐Ÿง  To support future extensions to this protocol, clients and servers MUST ignore elements of SEQUENCE encodings whose tags they don't recognize. Bestie, that's how the protocol stays flexible ๐Ÿ’œ

Note that, unlike X.500, each change to the LDAP protocol other than through the extension mechanisms gets a different version number ๐Ÿ”ข A client indicates the version it supports as part of the bind request, which is described in section 4.2. If a client hasn't sent a bind, the server MUST assume that version 3 is supported by the client (since version 2 required the client to bind first) ๐ŸŽ€

Clients can work out which protocol version a server supports by reading the supportedLDAPVersion attribute from the root DSE ๐Ÿ‘‘ Servers which implement version 3 or later versions MUST provide this attribute. Servers which only implement version 2 may not provide this attribute ๐Ÿฆ‹

4.1. Common Elements ๐ŸŒธ

This section describes the LDAPMessage envelope PDU (Protocol Data Unit) format, plus the data type definitions used in the protocol operations ๐Ÿ’–

4.1.1. Message Envelope ๐Ÿ’…

For protocol exchanges, all protocol operations are wrapped in a common envelope called the LDAPMessage, which is defined like this ๐Ÿ‘€

     LDAPMessage ::= SEQUENCE {

             messageID       MessageID,
             protocolOp      CHOICE {
                     bindRequest     BindRequest,
                     bindResponse    BindResponse,
                     unbindRequest   UnbindRequest,
                     searchRequest   SearchRequest,
                     searchResEntry  SearchResultEntry,
                     searchResDone   SearchResultDone,
                     searchResRef    SearchResultReference,
                     modifyRequest   ModifyRequest,
                     modifyResponse  ModifyResponse,
                     addRequest      AddRequest,
                     addResponse     AddResponse,
                     delRequest      DelRequest,
                     delResponse     DelResponse,
                     modDNRequest    ModifyDNRequest,
                     modDNResponse   ModifyDNResponse,
                     compareRequest  CompareRequest,
                     compareResponse CompareResponse,
                     abandonRequest  AbandonRequest,
                     extendedReq     ExtendedRequest,
                     extendedResp    ExtendedResponse },
              controls       [0] Controls OPTIONAL }

     MessageID ::= INTEGER (0 .. maxInt)

     maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --

The job of the LDAPMessage is to be an envelope with the common fields every protocol exchange needs ๐Ÿ“จ Right now, the only common fields are the message ID and the controls ๐Ÿซถ

If the server gets a PDU from the client where the LDAPMessage SEQUENCE tag can't be recognized, the messageID can't be parsed, the tag of the protocolOp isn't recognized as a request, or the encoding structures or lengths of data fields are found to be incorrect, then the server MUST return the notice of disconnection described in section 4.4.1, with a resultCode of protocolError, and immediately close the connection ๐Ÿ˜ฑ In other cases where the server can't parse the request it received from the client, the server MUST return an appropriate response to the request, with the resultCode set to protocolError ๐Ÿ™…

If the client gets a PDU from the server that can't be parsed, the client may discard the PDU, or it may abruptly close the connection ๐Ÿ’€

The ASN.1 type Controls is defined in section 4.1.12 โœจ

4.1.1.1. Message ID โœจ

okay so every LDAPMessage envelope that carries a response has the messageID of the request it's answering ๐Ÿ’Œ that's how everyone knows which question a reply belongs to, bestie.

The message ID of a request MUST have a value different from the values of any other requests outstanding in the LDAP session of which this message is a part. ๐Ÿ’… no two open requests can share an ID, period.

A client MUST NOT send a second request with the same message ID as an earlier request on the same connection if the client has not received the final response from the earlier request. Otherwise the behavior is undefined. ๐Ÿ’€ undefined is not the vibe, so don't. Typical clients increment a counter for each request ๐Ÿ”ข

A client MUST NOT reuse the message id of an abandonRequest or of the abandoned operation until it has received a response from the server for another request invoked subsequent to the abandonRequest, as the abandonRequest itself does not have a response. ๐Ÿ™ˆ the abandonRequest never gets a reply of its own, so you wait for a response to some later request first.

4.1.2. String Types ๐Ÿงต

okay so the LDAPString is basically a notational shortcut ๐Ÿง it means that even though these strings encode as OCTET STRING, the character set is ISO 10646 [13] (a superset of Unicode), encoded with the UTF-8 algorithm [14]. ngl the cute part is that characters matching ASCII (0x0000 through 0x007F) are stored as that same ASCII character in a single byte. The other byte values are used to build a variable-length encoding for any character at all ๐ŸŒˆ

LDAPString ::= OCTET STRING

The LDAPOID is also a notational shortcut ๐Ÿฆ‹ it means the permitted value is a (UTF-8 encoded) dotted-decimal representation of an OBJECT IDENTIFIER.

LDAPOID ::= OCTET STRING

For example,

1.3.6.1.4.1.1466.1.2.3

4.1.3. Distinguished Name and Relative Distinguished Name ๐ŸŒธ

LDAPDN and RelativeLDAPDN are the representations of a Distinguished Name and a Relative Distinguished Name after encoding them according to the spec in [4] ๐ŸŽ€ so that:

<distinguished-name> ::= <name>

<relative-distinguished-name> ::= <name-component>

where <name> and <name-component> are as defined in [4].

LDAPDN ::= LDAPString

RelativeLDAPDN ::= LDAPString

Only Attribute Types can be present in a relative distinguished name component ๐Ÿ™…โ€โ™€๏ธ the options of Attribute Descriptions (next section) MUST NOT be used in specifying distinguished names. no options in DNs, main character energy only.

4.1.4. Attribute Type ๐Ÿฆ‹

An AttributeType takes on as its value the textual string associated with that AttributeType in its specification.

AttributeType ::= LDAPString

Each attribute type has a unique OBJECT IDENTIFIER assigned to it ๐Ÿ†” this identifier may be written as decimal digits with components separated by periods, e.g. "2.5.4.10".

A specification may also assign one or more textual names for an attribute type. These names MUST begin with a letter, and only contain ASCII letters, digit characters and hyphens. They are case insensitive. (These ASCII characters are identical to ISO 10646 characters whose UTF-8 encoding is a single byte between 0x00 and 0x7F.) ๐Ÿ”ค

If the server has a textual name for an attribute type, it MUST use a textual name for attributes returned in search results. The dotted-decimal OBJECT IDENTIFIER is only used if there is no textual name for an attribute type. ๐Ÿงพ names win when they exist, iykyk.

Attribute type textual names are non-unique, as two different specifications (neither in standards track RFCs) may choose the same name. ๐Ÿ˜ญ yes, names can collide, it's giving chaos.

A server which masters or shadows entries SHOULD list all the attribute types it supports in the subschema entries, using the attributeTypes attribute. Servers which support an open-ended set of attributes SHOULD include at least the attributeTypes value for the 'objectClass' attribute. Clients MAY retrieve the attributeTypes value from subschema entries in order to obtain the OBJECT IDENTIFIER and other information associated with attribute types. ๐Ÿ“š

Some attribute type names which are used in this version of LDAP are described in [5]. Servers may implement additional attribute types. โœจ

4.1.5. Attribute Description ๐ŸŽ€

An AttributeDescription is a superset of the definition of the AttributeType. It has the same ASN.1 definition, but allows additional options to be specified. They are also case insensitive. ๐Ÿ’–

AttributeDescription ::= LDAPString

A value of AttributeDescription is based on the following BNF:

<AttributeDescription> ::= <AttributeType> [ ";" <options> ]

<options>  ::= <option> | <option> ";" <options>

<option>   ::= <opt-char> <opt-char>*

<opt-char> ::=  ASCII-equivalent letters, numbers and hyphen

Examples of valid AttributeDescription:

cn
userCertificate;binary

One option, "binary", is defined in this document. Additional options may be defined in IETF standards-track and experimental RFCs. Options beginning with "x-" are reserved for private experiments. Any option could be associated with any AttributeType, although not all combinations may be supported by a server. ๐Ÿงช

An AttributeDescription with one or more options is treated as a subtype of the attribute type without any options. Options present in an AttributeDescription are never mutually exclusive. Implementations MUST generate the <options> list sorted in ascending order, and servers MUST treat any two AttributeDescription with the same AttributeType and options as equivalent. A server will treat an AttributeDescription with any options it does not implement as an unrecognized attribute type. ๐Ÿ‘‘ sorted order is a must, and the same type plus options means the same thing.

The data type "AttributeDescriptionList" describes a list of 0 or more attribute types. (A list of zero elements has special significance in the Search request.) ๐Ÿงš

AttributeDescriptionList ::= SEQUENCE OF
        AttributeDescription

4.1.5.1. Binary Option ๐Ÿซถ

If the "binary" option is present in an AttributeDescription, it overrides any string-based encoding representation defined for that attribute in [5]. Instead the attribute is to be transferred as a binary value encoded using the Basic Encoding Rules [11]. The syntax of the binary value is an ASN.1 data type definition which is referenced by the "SYNTAX" part of the attribute type definition.

The presence or absence of the "binary" option only affects the transfer of attribute values in protocol; servers store any particular attribute in a single format. If a client requests that a server return an attribute in the binary format, but the server cannot generate that format, the server MUST treat this attribute type as an unrecognized attribute type. Similarly, clients MUST NOT expect servers to return an attribute in binary format if the client requested that attribute by name without the binary option. ๐Ÿšซ no sneaky binary surprises.

This option is intended to be used with attributes whose syntax is a complex ASN.1 data type, and the structure of values of that type is needed by clients. Examples of this kind of syntax are "Certificate" and "CertificateList". ๐Ÿ”

4.1.6. Attribute Value ๐Ÿ“

A field of type AttributeValue takes on as its value either a string encoding of a AttributeValue data type, or an OCTET STRING containing an encoded binary value, depending on whether the "binary" option is present in the companion AttributeDescription to this AttributeValue.

The definition of string encodings for different syntaxes and types may be found in other documents, and in particular [5].

AttributeValue ::= OCTET STRING

Note that there is no defined limit on the size of this encoding; thus protocol values may include multi-megabyte attributes (e.g. photographs). ๐Ÿ“ธ big files are allowed, bestie.

Attributes may be defined which have arbitrary and non-printable syntax. Implementations MUST NEITHER simply display nor attempt to decode as ASN.1 a value if its syntax is not known. The implementation may attempt to discover the subschema of the source entry, and retrieve the values of attributeTypes from it. ๐Ÿ™ˆ don't just print it or try to decode it blindly.

Clients MUST NOT send attribute values in a request which are not valid according to the syntax defined for the attributes. โŒ no junk values in requests, ever.

4.1.7. Attribute Value Assertion ๐Ÿง

The AttributeValueAssertion type definition is similar to the one in the X.500 directory standards. It contains an attribute description and a matching rule assertion value suitable for that type.

AttributeValueAssertion ::= SEQUENCE {
        attributeDesc   AttributeDescription,
        assertionValue  AssertionValue }

AssertionValue ::= OCTET STRING

If the "binary" option is present in attributeDesc, this signals to the server that the assertionValue is a binary encoding of the assertion value. ๐Ÿ”

For all the string-valued user attributes described in [5], the assertion value syntax is the same as the value syntax. Clients may use attribute values as assertion values in compare requests and search filters. ๐Ÿ’•

Note however that the assertion syntax may be different from the value syntax for other attributes or for non-equality matching rules. These may have an assertion syntax which contains only part of the value. See section 20.2.1.8 of X.501 [6] for examples. ๐Ÿ‘€ plot twist, sometimes it's only part of the value.

4.1.8. Attribute ๐ŸŒท

An attribute consists of a type and one or more values of that type. (Though attributes MUST have at least one value when stored, due to access control restrictions the set may be empty when transferred in protocol. This is described in section 4.5.2, concerning the PartialAttributeList type.) ๐Ÿ” stored attributes always have a value, but the wire can be empty because of access control.

Attribute ::= SEQUENCE {
        type    AttributeDescription,
        vals    SET OF AttributeValue }

Each attribute value is distinct in the set (no duplicates). The order of attribute values within the vals set is undefined and implementation-dependent, and MUST NOT be relied upon. ๐Ÿซ  don't count on the order, it's not promised.

4.1.9. Matching Rule Identifier ๐Ÿ”Ž

A matching rule is a means of expressing how a server should compare an AssertionValue received in a search filter with an abstract data value. The matching rule defines the syntax of the assertion value and the process to be performed in the server. ๐Ÿง 

An X.501(1993) Matching Rule is identified in the LDAP protocol by the printable representation of its OBJECT IDENTIFIER, either as one of the strings given in [5], or as decimal digits with components separated by periods, e.g. "caseIgnoreIA5Match" or "1.3.6.1.4.1.453.33.33". ๐Ÿ†”

MatchingRuleId ::= LDAPString

Servers which support matching rules for use in the extensibleMatch search filter MUST list the matching rules they implement in subschema entries, using the matchingRules attributes. The server SHOULD also list there, using the matchingRuleUse attribute, the attribute types with which each matching rule can be used. More information is given in section 4.4 of [5]. ๐ŸŽ‰ the matching rules go in the subschema, with the server listing which attribute types each one works with.

4.1.10. Result Message โœจ

okay so the LDAPResult is the construct this protocol uses to tell clients whether things went ๐ŸŽ‰ or ๐Ÿ’€. servers send back responses with LDAPResult fields so you can see the final status of whatever operation you asked for. main character energy for status codes ๐Ÿ’…

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 }

so basically every result code EXCEPT success, compareFalse and compareTrue means the operation did not fully finish ๐Ÿ™ˆ those three are the only ones that count as a clean vibe check โœจ

most of these codes are based on problem types from X.511 ๐ŸŒธ codes 16 to 21 are AttributeProblem, 32, 33, 34 and 36 are NameProblem, 48, 49 and 50 are SecurityProblem, 51 to 54 are ServiceProblem, and 64 to 69 plus 71 are UpdateProblem ๐Ÿงš

if a client gets a result code that isn't on this list, it has to treat it as an unknown error condition ๐Ÿ’€ no guessing allowed ๐Ÿ˜ญ

the errorMessage field can hold a textual, human-readable error diagnostic if the server wants to send one ๐Ÿ“ (terminal control and page formatting characters should be avoided). this diagnostic isn't standardized, so implementations MUST NOT rely on the values returned ๐Ÿ™…โ€โ™€๏ธ if the server doesn't send a text diagnostic, the errorMessage field of the LDAPResult type MUST contain a zero length string.

for the result codes noSuchObject, aliasProblem, invalidDNSyntax and aliasDereferencingProblem, the matchedDN field is set to the name of the lowest entry (object or alias) that got matched in the directory ๐Ÿ‘€ if no aliases were dereferenced while looking for the entry, it's a truncated form of the name you sent, or if aliases were dereferenced, it's a truncated form of the resulting name, as defined in section 12.5 of X.511 [8]. for all other result codes, the matchedDN field is set to a zero length string.

4.1.11. Referral ๐Ÿฆ‹

this is the referral error, and it basically says "wrong server bestie, this one doesn't hold the target entry" ๐Ÿงญ the referral field shows up in an LDAPResult only when resultCode is referral, and it's absent for every other result code. it contains a reference to another server (or a set of servers) that you can reach over LDAP or other protocols. referrals can come back for any operation request (except unbind and abandon, which don't have responses). at least one URL MUST be present in the Referral โœจ

the referral is NOT returned for a singleLevel or wholeSubtree search where the search scope spans multiple naming contexts and you'd need to contact several different servers to finish ๐Ÿ˜ตโ€๐Ÿ’ซ instead, you get continuation references, which are described in section 4.5.3 ๐ŸŽ€

Referral ::= SEQUENCE OF LDAPURL  -- one or more

LDAPURL ::= LDAPString -- limited to characters permitted in URLs

if the client wants to keep the operation going, it MUST follow the referral by contacting any one of the servers ๐Ÿƒโ€โ™€๏ธ all the URLs MUST be equally capable of being used to progress the operation ๐Ÿ’– (how multiple servers pull this off is outside the scope of this document, so that's a different story ๐Ÿ“–)

URLs for servers that implement the LDAP protocol are written according to [9]. if an alias was dereferenced, the <dn> part of the URL MUST be present, with the new target object name ๐ŸŒˆ if the <dn> part is there, the client MUST use that name in its next request to progress the operation. if it's not there, the client uses the same name as in the original request. some servers (for example, ones taking part in distributed indexing) might give you a different filter in a referral for a search operation ๐Ÿงš if the filter part of the URL is in an LDAPURL, the client MUST use that filter in its next request to progress the search, and if it's not there, the client MUST use the same filter it used for that search. the other parts of the new request can be the same or different from the request that made the referral ๐Ÿซถ

heads up ๐Ÿšจ UTF-8 characters in a DN or search filter might not be legal in URLs (spaces, for example), so they MUST be escaped using the % method in RFC 1738 [7] ๐Ÿ’…

other kinds of URLs can be returned too, as long as the operation could be performed using that protocol โœจ

4.1.12. Controls ๐Ÿ’œ

a control is a way to pass extension information ๐ŸŽ€ controls sent as part of a request only apply to that request and are NOT saved ๐Ÿ™ˆ

Controls ::= SEQUENCE OF Control

Control ::= SEQUENCE {
        controlType             LDAPOID,
        criticality             BOOLEAN DEFAULT FALSE,
        controlValue            OCTET STRING OPTIONAL }

the controlType field MUST be a UTF-8 encoded dotted-decimal representation of an OBJECT IDENTIFIER that uniquely identifies the control ๐Ÿ”ฅ this stops control names from clashing ๐Ÿ™Œ

the criticality field is either TRUE or FALSE ๐Ÿ“

if the server recognizes the control type and it fits the operation, the server will use the control when it performs the operation ๐ŸŒธ

if the server doesn't recognize the control type and criticality is TRUE, the server MUST NOT perform the operation, and MUST instead return the resultCode unsupportedCriticalExtension ๐Ÿ›‘

if the control doesn't fit the operation and criticality is TRUE, the server MUST NOT perform the operation, and MUST instead return the resultCode unsupportedCriticalExtension ๐Ÿ›‘

if the control is unrecognized or doesn't fit but criticality is FALSE, the server MUST ignore the control ๐Ÿซ 

the controlValue contains any info tied to the control, and its format is defined for that control ๐Ÿงš the server MUST be prepared to handle arbitrary contents of the controlValue octet string, including zero bytes ๐Ÿ’ช it's only absent if there's no value information associated with a control of its type โœจ

this document doesn't define any controls ๐Ÿ™…โ€โ™€๏ธ controls can be defined in other documents. a control definition consists of:

  • the OBJECT IDENTIFIER assigned to the control,
  • whether the control is always noncritical, always critical, or critical at the client's option,
  • the format of the controlValue contents of the control.

servers list the controls they recognize in the supportedControl attribute in the root DSE ๐ŸŒˆ

4.2. Bind Operation โœจ

okay so the Bind Operation is basically how the client and server swap authentication info ๐Ÿ” it's giving handshake energy, and it's lowkey the main character of the whole session ๐Ÿ’…

The Bind Request is defined as follows:

BindRequest ::= [APPLICATION 0] SEQUENCE {
        version                 INTEGER (1 .. 127),
        name                    LDAPDN,
        authentication          AuthenticationChoice }

AuthenticationChoice ::= CHOICE {
        simple                  [0] OCTET STRING,
                                 -- 1 and 2 reserved
        sasl                    [3] SaslCredentials }

SaslCredentials ::= SEQUENCE {
        mechanism               LDAPString,
        credentials             OCTET STRING OPTIONAL }

Okay, so there are three parameters in the Bind Request ๐ŸŽ€

  • version: this is the protocol version the session is going to use. This document is about version 3 of LDAP โœจ There's no version negotiation, so the client just sets this to whatever version it wants. If the client asks for protocol version 2, a server that supports the version 2 protocol described in [2] won't return any v3-specific protocol fields ๐Ÿ™ˆ (Fair warning, not every LDAP server does version 2, because they might not be able to generate the attribute syntaxes that go with it.)
  • name: this is the directory object the client wants to bind as ๐Ÿ“ It can be a null value (a zero length string) for anonymous binds, when authentication already happened at a lower layer, or when you're using SASL credentials with a mechanism that puts the LDAPDN inside the credentials.
  • authentication: this is the info used to authenticate the name, if there's any in the Bind Request ๐Ÿ”‘

So when a Bind Request comes in, the protocol server authenticates the requesting client, if that's needed. Then it sends back a Bind Response that tells the client how the authentication went ๐Ÿซถ

Authorization is using that authentication info while doing operations. Authorization MAY be affected by stuff outside the LDAP Bind request, like lower layer security services ๐Ÿ‘‘


4.2.1. Sequencing of the Bind Request โœจ

ngl this part is so important for not getting stuck in a loop ๐ŸŒ€ Some SASL mechanisms need the client to send the BindRequest more than once. If the client wants to quit the bind process at any point, it MAY unbind and then drop the underlying connection ๐Ÿฆ‹ Also, clients MUST NOT invoke operations between two Bind requests made as part of a multi-stage bind. No sneaking operations in the middle, bestie ๐Ÿ™…โ€โ™€๏ธ

A client can abort a SASL bind negotiation by sending a BindRequest with a different value in the mechanism field of SaslCredentials, or an AuthenticationChoice other than sasl ๐Ÿ’…

If the client sends a BindRequest with the sasl mechanism field as an empty string, the server MUST return a BindResponse with authMethodNotSupported as the resultCode. This lets clients bail out of a negotiation if they want to try again with the same SASL mechanism ๐ŸŒธ

Unlike LDAP v2, the client doesn't have to send a Bind Request in the first PDU of the connection ๐Ÿงš The client can ask for any operations, and the server MUST treat them as unauthenticated. If the server wants the client to bind before it browses or changes the directory, the server MAY reject any request other than binding, unbinding, or an extended request with the "operationsError" result ๐Ÿ™ˆ

If the client didn't bind before sending a request and gets an operationsError, it can then send a Bind Request. If that also fails, or the client decides not to bind on the existing connection, it closes the connection, reopens it, and starts over by sending a PDU with a Bind Request first ๐Ÿ” This helps it play nice with servers running other versions of LDAP ๐Ÿค

Clients MAY send multiple bind requests on a connection to change their credentials โœจ A later bind process abandons every operation still outstanding on the connection. (This makes the server side simpler, which is iconic ๐Ÿ‘‘) Authentication from earlier binds gets ignored, so if the bind fails, the connection gets treated as anonymous. If a SASL transfer encryption or integrity mechanism has been negotiated, and that mechanism can't switch credentials from one identity to another, then the client MUST establish a new connection instead ๐Ÿšจ


4.2.2. Authentication and Other Security Services ๐Ÿ”

The simple authentication option is the most basic one. The authentication field only holds a cleartext password ๐Ÿ˜ฌ Using cleartext passwords over open networks is not recommended when no lower layer is doing authentication or encryption. Check out the "Security Considerations" section for the full story ๐Ÿ’€

If there's no authentication to do, the simple authentication option MUST be chosen, and the password has to be zero length. (LDAPv2 clients do this a lot.) The DN is usually zero length too ๐Ÿƒ

The sasl choice works with any mechanism defined for use with SASL [12] โœจ The mechanism field holds the mechanism's name. The credentials field holds the arbitrary data used for authentication, wrapped inside an OCTET STRING. LDAP isn't text-based, unlike some other internet protocols that use SASL, so no base64 transformations get done on the credentials ๐Ÿ™…โ€โ™€๏ธ

If any SASL-based integrity or confidentiality services are turned on, they kick in after the server sends the final BindResponse with resultCode success and the client receives it ๐Ÿ›ก๏ธ

The client can ask the server to use authentication info from a lower layer protocol by using the SASL EXTERNAL mechanism ๐Ÿฆ‹


4.2.3. Bind Response ๐ŸŽ€

The Bind Response is defined as follows:

BindResponse ::= [APPLICATION 1] SEQUENCE {
     COMPONENTS OF LDAPResult,
     serverSaslCreds    [7] OCTET STRING OPTIONAL }

The Bind Response is basically the server telling the client how its authentication request went ๐Ÿ“ฌ

If the bind worked, the resultCode is success. Otherwise, it's one of these:

  • operationsError: the server ran into an internal error, ๐Ÿ’ฅ
  • protocolError: the version number isn't recognized, or the PDU structure is wrong, ๐Ÿ™ƒ
  • authMethodNotSupported: the SASL mechanism name isn't recognized, ๐Ÿคทโ€โ™€๏ธ
  • strongAuthRequired: the server needs authentication to happen with a SASL mechanism, ๐Ÿ”’
  • referral: this server can't accept this bind, so the client should try another one, ๐Ÿ‘‰
  • saslBindInProgress: the server needs the client to send a new bind request, using the same sasl mechanism, to keep the authentication going ๐Ÿ”
  • inappropriateAuthentication: the client tried to bind anonymously or without credentials, and the server needs it to supply some kind of credentials ๐Ÿ™‹โ€โ™€๏ธ
  • invalidCredentials: the password was wrong, or the SASL credentials couldn't be processed ๐Ÿ˜ญ
  • unavailable: the server is shutting down ๐ŸŒ™

If the server doesn't support the client's requested protocol version, it MUST set the resultCode to protocolError ๐Ÿšซ

If the client gets a BindResponse where the resultCode was protocolError, it MUST close the connection, because the server won't accept more operations after that ๐Ÿ”Œ (This is for compatibility with older LDAP versions, where the bind was always the very first operation and there was no negotiation. Very throwback ๐Ÿ•ฐ๏ธ)

The serverSaslCreds are used as part of a SASL-defined bind mechanism. They let the client authenticate the server it's talking to, or do "challenge-response" authentication ๐Ÿค If the client bound with the password choice, or the SASL mechanism doesn't need the server to send info back to the client, then this field isn't included in the result โœจ


4.3. Unbind Operation ๐Ÿ‘‹

The Unbind Operation is how you end a protocol session ๐Ÿงน It's defined as follows:

UnbindRequest ::= [APPLICATION 2] NULL

There's no response defined for the Unbind Operation. Once a protocol client sends an UnbindRequest, it can assume the session is over ๐Ÿซถ When a protocol server gets an UnbindRequest, it can assume the client is done, throw away any outstanding requests, and close the connection ๐Ÿ’…


4.4. Unsolicited Notification ๐Ÿ“ฃ

An unsolicited notification is an LDAPMessage the server sends to the client without the client asking for it ๐Ÿ‘€ The server uses it to signal something extraordinary going on in the server or on the connection between it and the client ๐Ÿšจ It's advisory, so the server doesn't expect the client to reply ๐Ÿ’–

The unsolicited notification is structured as an LDAPMessage with a messageID of 0 and a protocolOp in the extendedResp form. The responseName field of the ExtendedResponse is present. The LDAPOID value MUST be unique to this notification, and it can't be used in any other situation ๐Ÿ†”

Only one unsolicited notification is defined in this document ๐ŸŒธ


4.4.1. Notice of Disconnection ๐Ÿšช

The server can use this notification to tell the client it's about to close the connection because of an error condition ๐Ÿ˜ต Note that this notification is NOT a response to an unbind the client asked for. The server MUST follow the procedures of section 4.3 instead. This notification is there to help clients tell an error condition apart from a temporary network failure ๐Ÿง Like with a connection closed by a network failure, the client MUST NOT assume that any outstanding requests which changed the directory succeeded or failed ๐Ÿค”

The responseName is 1.3.6.1.4.1.1466.20036, the response field is absent, and the resultCode tells you why the connection is dropping ๐Ÿ“

These resultCode values are used in this notification:

  • protocolError: the server got data from the client that couldn't be parsed as an LDAPMessage structure. ๐Ÿ™ƒ
  • strongAuthRequired: the server noticed that the security association protecting the communication between client and server has unexpectedly failed or been compromised. ๐Ÿšจ๐Ÿ”’
  • unavailable: this server is going to stop accepting new connections and operations on all existing connections, and it'll be unavailable for a while. The client can use an alternative server instead. ๐ŸŒ™

After sending this notice, the server MUST close the connection ๐Ÿ”Œ After receiving it, the client MUST NOT transmit anything else on the connection, and it may close the connection abruptly ๐Ÿ’ฅ


4.5. Search Operation ๐Ÿ”

The Search Operation lets a client ask a server to run a search for it ๐Ÿ•ต๏ธโ€โ™€๏ธ It can be used to read attributes from a single entry, from the entries immediately below a particular entry, or from a whole subtree of entries ๐ŸŒณ literally so useful ๐Ÿ’œ

4.5.1. Search Request โœจ

Okay bestie, here's how the Search Request is laid out ๐ŸŽ€:

        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 }

        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 {
                matchingRule    [1] MatchingRuleId OPTIONAL,
                type            [2] AttributeDescription OPTIONAL,
                matchValue      [3] AssertionValue,
                dnAttributes    [4] BOOLEAN DEFAULT FALSE }

Now the parameters of the Search Request, the fun part ๐Ÿ’…:

  • baseObject: an LDAPDN ๐ŸŒธ that names the base object entry the search is performed relative to.
  • scope: this tells the server how wide the search is ๐Ÿฆ‹. The values mean exactly the same thing as the scope field in the X.511 Search Operation.
  • derefAliases: this decides how alias objects (as defined in X.501) get handled when searching ๐Ÿ”. The possible values are:
    • neverDerefAliases: aliases are not dereferenced, either while searching or while locating the base object of the search.
    • derefInSearching: aliases are dereferenced in subordinates of the base object while searching, but not while locating the base object of the search.
    • derefFindingBaseObj: aliases are dereferenced while locating the base object of the search, but not when searching subordinates of the base object.
    • derefAlways: aliases are dereferenced both while searching and while locating the base object of the search.
  • sizelimit: a limit on the maximum number of entries returned by the search ๐Ÿง. A value of 0 means no client-requested sizelimit restrictions are in effect for the search. Servers may enforce a maximum number of entries to return.
  • timelimit: a limit on the maximum time, in seconds, allowed for a search โฐ. A value of 0 means no client-requested timelimit restrictions are in effect for the search.
  • typesOnly: this one decides whether results include both attribute types and values, or just the types ๐Ÿ™ˆ. Setting it to TRUE means only attribute types come back (no values). Setting it to FALSE means both attribute types and values come back.
  • filter: this is the set of conditions an entry has to fulfill for the search to match it ๐Ÿ’œ.

The and, or and not choices can be used to combine filters into combos ๐Ÿงฉ. At least one filter element MUST be present in an and or or choice. The others match against individual attribute values of entries in the scope of the search. (Implementor's note: the not filter is an example of a tagged choice in an implicitly-tagged module. In BER this is treated as if the tag was explicit.)

A server MUST evaluate filters according to the three-valued logic of X.511(93) section 7.8.1 ๐Ÿ”ฅ. Basically, a filter comes out as TRUE, FALSE or Undefined. If the filter comes out TRUE for a particular entry, that entry's attributes are returned as part of the search result (subject to any applicable access control restrictions) โœจ. If it comes out FALSE or Undefined, the entry gets ignored for the search ๐Ÿ™…โ€โ™€๏ธ.

An and filter is TRUE if all the filters in the SET OF evaluate to TRUE, FALSE if at least one of them is FALSE, and otherwise Undefined. An or filter is FALSE if all of the filters in the SET OF evaluate to FALSE, TRUE if at least one of them is TRUE, and Undefined otherwise. A not filter is TRUE if the filter being negated is FALSE, FALSE if it is TRUE, and Undefined if the negated filter is Undefined ๐ŸŒ€.

The present match evaluates to TRUE where an entry has an attribute, or a subtype of the specified attribute description, present. Otherwise it's FALSE ๐ŸŒธ. That includes a presence test using an attribute description the server doesn't recognize.

The extensibleMatch is brand new in this version of LDAP ๐ŸŽ‰. If the matchingRule field is absent, the type field MUST be present, and the equality match is performed for that type. If the type field is absent and matchingRule is present, the matchValue gets compared against all attributes in an entry that support that matchingRule, and the matchingRule decides the syntax for the assertion value. The filter item comes out TRUE if it matches at least one attribute in the entry, FALSE if it doesn't match any attribute in the entry, and Undefined if the matchingRule isn't recognized or the assertion value can't be parsed. If the type field is present and matchingRule is present, the matchingRule MUST be one permitted for use with that type, otherwise the filter item is undefined. If the dnAttributes field is set to TRUE, the match is also applied against all the attributes in an entry's distinguished name, and it evaluates to TRUE if at least one of those attributes gives TRUE for the filter item. (Editors note: The dnAttributes field is present so that there does not need to be multiple versions of generic matching rules such as for word matching, one to apply to entries and another to apply to entries and dn attributes as well).

A filter item evaluates to Undefined when the server wouldn't be able to figure out whether the assertion value matches an entry ๐Ÿค”. That happens if an attribute description in an equalityMatch, substrings, greaterOrEqual, lessOrEqual, approxMatch or extensibleMatch filter isn't recognized by the server, if a matching rule id in the extensibleMatch isn't recognized, if the assertion value can't be parsed, or if the type of filtering requested isn't implemented. For example, if a server didn't recognize the attribute type shoeSize, then (shoeSize=*) would evaluate to FALSE, while (shoeSize=12), (shoeSize>=12) and (shoeSize<=12) would all evaluate to Undefined ๐Ÿ‘Ÿ.

Servers MUST NOT return errors if attribute descriptions or matching rule ids aren't recognized, or if assertion values can't be parsed ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’–. More details of filter processing are given in section 7.8 of X.511 [8].

  • attributes: a list of the attributes to return from each entry that matches the search filter ๐Ÿ“‹. There are two special values you can use: an empty list with no attributes, and the attribute description string *. Both of these mean all user attributes get returned. (The * lets the client ask for all user attributes on top of specific operational attributes ๐Ÿฆ„.)

Attributes MUST be named at most once in the list, and they get returned at most once in an entry. If the list has attribute descriptions that aren't recognized, the server just ignores them ๐Ÿซถ.

If the client doesn't want any attributes back, it can give a list with only the attribute with OID 1.1 ๐Ÿ™ƒ. That OID was picked arbitrarily and doesn't match any attribute in use.

Client implementors, listen up ๐Ÿ‘‘: even if you request all user attributes, some attributes of the entry might still be left out of the search results because of access control or other restrictions. Also, servers won't return operational attributes, like objectClasses or attributeTypes, unless you list them by name, since some operational attributes can have an extremely large number of values ๐Ÿ˜ญ. (A list of operational attributes for use in LDAP is given in [5].)

Note that an X.500 "list"-like operation can be faked by the client sending a one-level LDAP search with a filter that checks for the existence of the objectClass attribute ๐Ÿงš. Similarly, an X.500 "read"-like operation can be faked with a base object LDAP search using that same filter ๐Ÿ“. A server that provides a gateway to X.500 isn't required to use the Read or List operations, although it may choose to do so. If it does, it must provide the same semantics as the X.500 search operation ๐ŸŒˆ.

4.5.2. Search Result โœจ

okay so the results of a search go back to the client inside Search Responses ๐Ÿ’Œ These are LDAP messages, and each one carries either a SearchResultEntry, a SearchResultReference, an ExtendedResponse, or a SearchResultDone. that's the whole cast ๐ŸŽ€

SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
        objectName      LDAPDN,
        attributes      PartialAttributeList }

PartialAttributeList ::= SEQUENCE OF SEQUENCE {
        type    AttributeDescription,
        vals    SET OF AttributeValue }
-- implementors should note that the PartialAttributeList may
-- have zero elements (if none of the attributes of that entry
-- were requested, or could be returned), and that the vals set
-- may also have zero elements (if types only was requested, or
-- all values were excluded from the result.)

SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
-- at least one LDAPURL element must be present

SearchResultDone ::= [APPLICATION 5] LDAPResult

the moment a server gets a Search Request, it goes off and does the search of the DIT ๐Ÿ”

if the LDAP session is running over a connection-oriented transport like TCP, the server sends back a bunch of responses, each in its own LDAP message ๐Ÿ“ฌ there can be zero or more SearchResultEntry responses, one for each entry it finds. there can also be zero or more SearchResultReference responses, one for each area the server didn't explore during the search ๐Ÿ—บ๏ธ the SearchResultEntry and SearchResultReference PDUs can show up in any order, so don't get thrown if they're jumbled ๐Ÿ™ˆ once every SearchResultReference and every SearchResultEntry is sent, the server wraps it up with a SearchResultDone response. that one says whether things went well, or spells out any errors that happened ๐Ÿ’…

each entry in a SearchResultEntry has all the attributes you asked for in the attributes field of the Search Request, with their values included when needed ๐Ÿงš but getting attributes back is subject to access control and other administrative policy, so it's not automatically a free-for-all ๐Ÿ” some attributes can come back in binary format, and you'll spot that because the AttributeDescription in the response has the binary option present ๐ŸŒธ

some attributes are constructed by the server and show up in a SearchResultEntry attribute list even though they aren't stored attributes of the entry โœจ so, important bit: Clients MUST NOT assume that all attributes can be modified, even if permitted by access control. ๐Ÿšซ seeing an attribute doesn't mean you get to change it, bestie ๐Ÿ’œ

LDAPMessage responses in the ExtendedResponse form are reserved for sending back information tied to a control the client asked for ๐ŸŽ€ these might get defined in future versions of this document ๐Ÿ”ฎ

4.5.3. Continuation References in the Search Result

ok this part is about when the server finds the entry called the baseObject but can't search everything in the scope at and under it ๐Ÿ™ƒ in that case the server may send back one or more SearchResultReference responses. each one points to another set of servers that can continue the operation ๐Ÿฆ‹ A server MUST NOT return any SearchResultReference if it has not located the baseObject and thus has not searched any entries; in that situation it returns a SearchResultDone with a referral resultCode instead ๐Ÿ’€

if the server doesn't have indexing info from the servers that hold the subordinate naming contexts, then SearchResultReference responses aren't filtered by the search filters. they're always returned when they're in scope ๐ŸŒˆ

the SearchResultReference is the same data type as the Referral. URLs for servers implementing the LDAP protocol are written according to [9]. The <dn> part MUST be present in the URL, with the new target object name. The client MUST use this name in its next request. ๐ŸŽฏ some servers (like part of a distributed index exchange system) might give a different filter in the URLs of the SearchResultReference ๐Ÿงฉ if the filter part is in the LDAP URL, then the client MUST use the new filter in its next request to progress the search. if the filter part is absent, the client just uses the same filter again ๐Ÿ” other parts of the new search request can be the same or different from the search that made the continuation references ๐Ÿ’ซ

other kinds of URLs can come back too, as long as the operation could be done using that protocol ๐ŸŒธ

the name of an unexplored subtree in a SearchResultReference doesn't have to be subordinate to the base object ๐Ÿคทโ€โ™€๏ธ

to finish the search, the client MUST issue a new search operation for each SearchResultReference that is returned. ๐Ÿ“จ also, the abandon operation in section 4.11 only applies to one particular operation sent on a connection between a client and server. so if you've got multiple outstanding search operations going to different servers, it MUST abandon each operation individually. ๐Ÿ™…โ€โ™€๏ธ very main character energy of you to keep track of all of them ๐Ÿ‘‘

4.5.3.1. Example

okay let's walk through this with some hosts ๐Ÿงš say the contacted server (hosta) holds the entry "O=MNN,C=WW" and the entry "CN=Manager,O=MNN,C=WW". it knows that either LDAP-capable servers (hostb) or (hostc) hold "OU=People,O=MNN,C=WW" (one is the master and the other server a shadow). and LDAP-capable server (hostd) holds the subtree "OU=Roles,O=MNN,C=WW". if a subtree search of "O=MNN,C=WW" is requested to the contacted server, it may return the following:

     SearchResultEntry for O=MNN,C=WW
     SearchResultEntry for CN=Manager,O=MNN,C=WW
     SearchResultReference {
       ldap://hostb/OU=People,O=MNN,C=WW
       ldap://hostc/OU=People,O=MNN,C=WW
     }
     SearchResultReference {
       ldap://hostd/OU=Roles,O=MNN,C=WW
     }
     SearchResultDone (success)

client implementors, pay attention here ๐Ÿ‘€ when you follow a SearchResultReference, you might get additional SearchResultReference responses generated too ๐ŸŒ€ continuing the example, if the client contacted the server (hostb) and issued the search for the subtree "OU=People,O=MNN,C=WW", the server might respond like this:

     SearchResultEntry for OU=People,O=MNN,C=WW
     SearchResultReference {
      ldap://hoste/OU=Managers,OU=People,O=MNN,C=WW
     }
     SearchResultReference {
      ldap://hostf/OU=Consultants,OU=People,O=MNN,C=WW
     }
     SearchResultDone (success)

and if the contacted server doesn't hold the base object for the search, it sends back a referral to the client ๐ŸŽ for example, if the client requests a subtree search of "O=XYZ,C=US" to hosta, the server may return only a SearchResultDone containing a referral:

     SearchResultDone (referral) {
       ldap://hostg/
     }

4.6. Modify Operation

the Modify Operation lets a client ask a server to modify an entry for it ๐Ÿ’– the Modify Request is defined like this:

ModifyRequest ::= [APPLICATION 6] SEQUENCE {
        object          LDAPDN,
        modification    SEQUENCE OF SEQUENCE {

                operation       ENUMERATED {
                                        add     (0),
                                        delete  (1),
                                        replace (2) },
                modification    AttributeTypeAndValues } }

AttributeTypeAndValues ::= SEQUENCE {
        type    AttributeDescription,
        vals    SET OF AttributeValue }

Parameters of the Modify Request are:

  • object: The object to be modified. The value of this field contains the DN of the entry to be modified. The server will not perform any alias dereferencing in determining the object to be modified. ๐ŸŽฏ
  • modification: A list of modifications to be performed on the entry. The entire list of entry modifications MUST be performed in the order they are listed, as a single atomic operation. While individual modifications may violate the directory schema, the resulting entry after the entire list of modifications is performed MUST conform to the requirements of the directory schema. ๐Ÿ“‹ the values that the 'operation' field can take in each modification construct have these semantics, respectively:
    • add: add values listed to the given attribute, creating the attribute if necessary; โž•
    • delete: delete values listed from the given attribute, removing the entire attribute if no values are listed, or if all current values of the attribute are listed for deletion; ๐Ÿ—‘๏ธ
    • replace: replace all existing values of the given attribute with the new values listed, creating the attribute if it did not already exist. A replace with no value will delete the entire attribute if it exists, and is ignored if the attribute does not exist. ๐Ÿ”„

the server sends back the result of the modify it attempted in a Modify Response, defined like so ๐Ÿ’Œ

ModifyResponse ::= [APPLICATION 7] LDAPResult

once the server gets a Modify Request, it does the necessary modifications to the DIT โœจ the server returns a single Modify Response that says either the DIT modification finished successfully, or why it failed ๐Ÿ’ซ because the list of modifications in the Modify Request has to be atomic, the client can expect that no modifications were performed if the Modify Response shows any sort of error. and if the Modify Response says the Modify Operation completed successfully, then all the requested modifications were performed ๐Ÿซถ but if the connection fails, it's indeterminate whether the modification happened or not ๐Ÿ˜ญ

the Modify Operation cannot be used to remove any of an entry's distinguished values, the ones that form the entry's relative distinguished name ๐Ÿšซ trying to do that gets you the error notAllowedOnRDN. if you want to rename an entry, use the Modify DN Operation described in section 4.9 instead ๐Ÿฆ‹

if an equality match filter hasn't been defined for an attribute type, clients MUST NOT attempt to delete individual values of that attribute from an entry using the "delete" form of a modification, and MUST instead use the "replace" form. ๐Ÿ™ˆ it's giving "replace or nothing" for that situation ๐Ÿ’…

last thing, and it matters: because LDAP is simplified, there isn't a direct mapping from the modifications in an LDAP ModifyRequest onto the EntryModifications of a DAP ModifyEntry operation. different LDAP-DAP gateway implementations may represent the change in different ways ๐ŸŒ‰ but if successful, the final effect of the operations on the entry MUST be identical. ๐Ÿ’œ the vibe can differ, but the result has to match, periodt ๐Ÿ‘‘

4.7. Add Operation โœจ

Okay so the Add Operation is how a client asks the server to add a brand new entry to the directory ๐ŸŒธ The Add Request looks like this:

AddRequest ::= [APPLICATION 8] SEQUENCE {
        entry           LDAPDN,
        attributes      AttributeList }

AttributeList ::= SEQUENCE OF SEQUENCE {
        type    AttributeDescription,
        vals    SET OF AttributeValue }

The parameters of the Add Request are:

  • entry: the Distinguished Name of the entry to be added. Ngl, the server won't dereference any aliases while it's hunting for the entry being added ๐Ÿ”
  • attributes: the list of attributes that make up the content of the entry being added. Clients MUST include distinguished values (the ones forming the entry's own RDN) in this list, the objectClass attribute, and values of any mandatory attributes of the listed object classes. Clients MUST NOT supply the createTimestamp or creatorsName attributes, since the server generates those automatically ๐Ÿค–

The entry named in the entry field of the AddRequest MUST NOT exist for the AddRequest to succeed. The parent of the entry to be added MUST exist. Picture this: a client tries to add "CN=JS,O=Foo,C=US", but "O=Foo,C=US" doesn't exist, while "C=US" does. The server would return the error noSuchObject with the matchedDN field set to "C=US" ๐Ÿ’€ If the parent entry exists but lives outside any naming context the server holds, the server SHOULD return a referral to the server that holds the parent entry ๐Ÿฆ‹

Servers implementations SHOULD NOT restrict where entries can be located in the directory. Some servers MAY allow the administrator to restrict which classes of entries can be added to the directory ๐Ÿ’…

When an Add Request arrives, the server will try to do the add it asked for. The result comes back to the client in the Add Response:

AddResponse ::= [APPLICATION 9] LDAPResult

A success response means the new entry is now present in the directory. Iconic ๐Ÿ‘‘


4.8. Delete Operation

The Delete Operation lets a client ask for an entry to be removed from the directory ๐Ÿ—‘๏ธ The Delete Request is defined like this:

DelRequest ::= [APPLICATION 10] LDAPDN

The Delete Request is just the Distinguished Name of the entry to be deleted. The server won't dereference aliases while it resolves the name of the target entry, and only leaf entries (the ones with no subordinate entries) can be deleted with this operation. So no deleting the whole family tree in one go ๐ŸŒณ๐Ÿšซ

The server reports the result of the delete attempt in the Delete Response:

DelResponse ::= [APPLICATION 11] LDAPResult

When a Delete Request comes in, the server will try to remove the entry. The result of that attempt goes back to the client in the Delete Response ๐Ÿซถ


4.9. Modify DN Operation

The Modify DN Operation lets a client change the leftmost (least significant) component of an entry's name, or move a whole subtree of entries to a new spot in the directory ๐Ÿฆ‹ Here's the Modify DN Request:

ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
        entry           LDAPDN,
        newrdn          RelativeLDAPDN,
        deleteoldrdn    BOOLEAN,
        newSuperior     [0] LDAPDN OPTIONAL }

The 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 leftmost component of the entry's new name.
  • deleteoldrdn: a boolean parameter that controls whether the old RDN attribute values are kept as attributes of the entry, or deleted from it ๐Ÿงน
  • newSuperior: if it's present, this is the Distinguished Name of the entry that becomes the immediate superior of the existing entry ๐Ÿ 

The server reports the result of the name change in the Modify DN Response:

ModifyDNResponse ::= [APPLICATION 13] LDAPResult

When a ModifyDNRequest arrives, the server will try to perform the name change. The result of that attempt is returned to the client in the Modify DN Response โœจ

Here's an example. Say the entry named in the "entry" parameter is "cn=John Smith,c=US", the newrdn parameter is "cn=John Cougar Smith", and newSuperior is absent. Then this operation tries to rename the entry to "cn=John Cougar Smith,c=US". If an entry with that name already exists, the operation fails with the error code entryAlreadyExists ๐Ÿ™ˆ

If deleteoldrdn is TRUE, the values forming the old RDN get deleted from the entry. If it's FALSE, those values stick around as non-distinguished attribute values of the entry. The server may skip the operation and return an error code if the deleteoldrdn setting would cause a schema inconsistency in the entry ๐Ÿค“

Heads up, bestie: X.500 only lets the ModifyDN operation touch entries that live inside a single server. If the LDAP server is mapped onto DAP, that restriction applies, and the resultCode affectsMultipleDSAs comes back if this error happens. In general, clients MUST NOT expect to be able to move entries and subtrees between servers whenever they feel like it ๐Ÿšซ

4.10. Compare Operation

The Compare Operation lets a client check an assertion against an entry in the directory ๐Ÿ”Ž The Compare Request is defined as follows:

CompareRequest ::= [APPLICATION 14] SEQUENCE {
        entry           LDAPDN,
        ava             AttributeValueAssertion }

The parameters of the Compare Request are:

  • entry: the name of the entry to be compared with.
  • ava: the assertion that an attribute in the entry is to be compared against.

The server reports the result of the compare in the Compare Response:

CompareResponse ::= [APPLICATION 15] LDAPResult

When a Compare Request arrives, the server will try to do the requested comparison. The result comes back to the client in the Compare Response. Note that errors and the comparison result are all returned in the same construct, so keep your eyes peeled ๐Ÿ‘€

Some directory systems may set up access controls that let certain attributes (like userPassword) be compared but not read ๐Ÿ” In a search result, an attribute of that type might come back with an empty set of values. Sneaky, right? ๐Ÿ™ƒ


4.11. Abandon Operation

The Abandon Operation lets a client ask the server to abandon an operation that's still outstanding ๐Ÿ›‘ The Abandon Request is defined as follows:

AbandonRequest ::= [APPLICATION 16] MessageID

The MessageID MUST be that of a an operation which was requested earlier in this connection.

(The abandon request has its own message id too. That's different from the id of the earlier operation being abandoned, so don't mix them up ๐Ÿง )

There's no response defined for the Abandon Operation. Once a client sends an Abandon Operation, it can expect that the operation identified by the Message ID in the Abandon Request has been abandoned ๐Ÿซ  If a server gets an Abandon Request for a Search Operation while it's in the middle of sending search responses, that server MUST cease transmitting entry responses to the abandoned request immediately, and MUST NOT send the SearchResponseDone. Of course, the server MUST ensure that only properly encoded LDAPMessage PDUs are transmitted ๐Ÿ”’

Clients MUST NOT send abandon requests for the same operation multiple times. They MUST also be prepared to receive results from operations they've abandoned, since those may have been in transit when the abandon was requested ๐Ÿ“ฌ

Servers MUST discard abandon requests for message IDs they don't recognize, for operations that can't be abandoned, and for operations that have already been abandoned ๐Ÿ—‘๏ธ


4.12. Extended Operation

An extension mechanism was added in this version of LDAP so that additional operations can be defined for services that aren't available anywhere else in the protocol, like digitally signed operations and results โœ๏ธ๐Ÿ”ฅ

The extended operation lets clients make requests and receive responses with predefined syntaxes and semantics. These may be defined in RFCs or be private to particular implementations. Each request MUST have a unique OBJECT IDENTIFIER assigned to it ๐Ÿ†”

ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
        requestName      [0] LDAPOID,
        requestValue     [1] OCTET STRING OPTIONAL }

The requestName is a dotted-decimal representation of the OBJECT IDENTIFIER that corresponds to the request. The requestValue is information in a form defined by that request, wrapped up inside an OCTET STRING ๐ŸŽ

The server responds to this with an LDAPMessage containing the ExtendedResponse:

ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
        COMPONENTS OF LDAPResult,
        responseName     [10] LDAPOID OPTIONAL,
        response         [11] OCTET STRING OPTIONAL }

If the server doesn't recognize the request name, it MUST return only the response fields from LDAPResult, containing the protocolError result code ๐Ÿ˜ฌ


5. Protocol Element Encodings and Transfer โœจ

Only one underlying service is defined here. Clients and servers SHOULD implement the mapping of LDAP over TCP described in 5.2.1 ๐Ÿงฆ

5.1. Mapping Onto BER-based Transport Services

The protocol elements of LDAP are encoded for exchange using the Basic Encoding Rules (BER) [11] of ASN.1 [3]. But BER has a lot of overhead for certain elements, so there are extra restrictions on BER-encodings of LDAP protocol elements ๐Ÿ’… They are:

  1. Only the definite form of length encoding will be used.
  2. OCTET STRING values will be encoded in the primitive form only.
  3. If the value of a BOOLEAN type is true, the encoding MUST have its contents octets set to hex "FF".
  4. If a value of a type is its default value, it MUST be absent. Only some BOOLEAN and INTEGER types have default values in this protocol definition.

These restrictions don't apply to ASN.1 types wrapped inside OCTET STRING values, such as attribute values, unless it's noted otherwise ๐ŸŒˆ

5.2. Transfer Protocols

This protocol is designed to run over connection-oriented, reliable transports, with all 8 bits in an octet being significant in the data stream ๐Ÿงƒ

5.2.1. Transmission Control Protocol (TCP)

The LDAPMessage PDUs get mapped directly onto the TCP bytestream ๐ŸŒŠ It is recommended that server implementations running over TCP MAY provide a protocol listener on the assigned port, 389. Servers may instead provide a listener on a different port number. Clients MUST support contacting servers on any valid TCP port ๐Ÿ’–

6. Implementation Guidelines โœจ

This document describes an Internet protocol ๐ŸŒ

6.1. Server Implementations ๐ŸŽ€

okay so the server MUST be capable of recognizing all the mandatory attribute type names and implementing the syntaxes specified in [5]. Servers MAY also recognize additional attribute type names ๐Ÿงš

6.2. Client Implementations ๐Ÿ’…

bestie, clients that request referrals MUST make sure they don't loop between servers. They MUST NOT repeatedly contact the same server for the same request with the same target entry name, scope and filter. Some clients might be using a counter that goes up each time referral handling happens for an operation, and these kinds of clients MUST be able to handle a DIT with at least ten layers of naming contexts between the root and a leaf entry ๐Ÿ˜ญ

Unless you've already agreed on things with a server, clients SHOULD NOT assume that servers support any particular schemas beyond the ones referenced in section 6.1. Different schemas can have different attribute types with the same names, so it's giving confusion if you don't check ๐Ÿ™ˆ The client can retrieve the subschema entries referenced by the subschemaSubentry attribute in the server's root DSE or in entries held by the server โœจ

7. Security Considerations ๐Ÿ”ฅ

okay this section is SERIOUS, so pay attention ๐Ÿ’€

When used with a connection-oriented transport, this version of the protocol provides facilities for the LDAP v2 authentication mechanism, simple authentication using a cleartext password, as well as any SASL mechanism [12]. SASL allows for integrity and privacy services to be negotiated ๐Ÿ”

It is also permitted that the server can return its credentials to the client, if it chooses to do so.

Cleartext passwords are strongly discouraged where the underlying transport service cannot guarantee confidentiality, because they may result in disclosure of the password to unauthorized parties. Not the vibe ๐Ÿ’€

When used with SASL, it should be noted that the name field of the BindRequest is not protected against modification. Thus, if the distinguished name of the client (an LDAPDN) is agreed through the negotiation of the credentials, it takes precedence over any value in the unprotected name field ๐Ÿซถ

Implementations which cache attributes and entries obtained via LDAP MUST ensure that access controls are maintained if that information is to be provided to multiple clients, since servers may have access control policies which prevent the return of entries or attributes in search results except to particular authenticated clients. For example, caches could serve result information only to the client whose request caused it to be cache ๐Ÿ‘‘

8. Acknowledgements ๐ŸŒธ

This document is an update to RFC 1777, by Wengyik Yeong, Tim Howes, and Steve Kille. Design ideas included in this document are based on those discussed in ASID and other IETF Working Groups. The contributions of individuals in these working groups is gratefully acknowledged ๐Ÿ’œ

9. Bibliography ๐Ÿ“š

[1] ITU-T Rec. X.500, "The Directory: Overview of Concepts, Models and Service", 1993.

[2] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access Protocol", RFC 1777, March 1995.

[3] ITU-T Rec. X.680, "Abstract Syntax Notation One (ASN.1) - Specification of Basic Notation", 1994.

[4] Kille, S., Wahl, M., and T. Howes, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names", RFC 2253, December 1997.

[5] Wahl, M., Coulbeck, A., Howes, T., and S. Kille, "Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions", RFC 2252, December 1997.

[6] ITU-T Rec. X.501, "The Directory: Models", 1993.

[7] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform Resource Locators (URL)", RFC 1738, December 1994.

[8] ITU-T Rec. X.511, "The Directory: Abstract Service Definition", 1993.

[9] Howes, T., and M. Smith, "The LDAP URL Format", RFC 2255, December 1997.

[10] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, March 1997.

[11] ITU-T Rec. X.690, "Specification of ASN.1 encoding rules: Basic, Canonical, and Distinguished Encoding Rules", 1994.

[12] Meyers, J., "Simple Authentication and Security Layer", RFC 2222, October 1997.

[13] Universal Multiple-Octet Coded Character Set (UCS) - Architecture and Basic Multilingual Plane, ISO/IEC 10646-1 : 1993.

[14] Yergeau, F., "UTF-8, a transformation format of Unicode and ISO 10646", RFC 2044, October 1996.

10. Authors' Addresses ๐Ÿ’–

Mark Wahl

Mark Wahl
Critical Angle Inc.
4815 W Braker Lane #502-385
Austin, TX 78759
USA

Phone:  +1 512 372-3160
EMail:  M.Wahl@critical-angle.com

Tim Howes

Tim Howes
Netscape Communications Corp.
501 E. Middlefield Rd., MS MV068
Mountain View, CA 94043
USA

Phone:  +1 650 937-3419
EMail:   howes@netscape.com

Steve Kille

Steve Kille
Isode Limited
The Dome, The Square
Richmond
TW9 1DT
UK

Phone:  +44-181-332-9091
EMail:  S.Kille@isode.com

Appendix A - Complete ASN.1 Definition โœจ

okay bestie, this is the full ASN.1 definition all in one place ๐Ÿงš every type is here exactly as written, so you can copy it straight from the page ๐Ÿ’…

        Lightweight-Directory-Access-Protocol-V3 DEFINITIONS
        IMPLICIT TAGS ::=

        BEGIN

        LDAPMessage ::= SEQUENCE {
                messageID       MessageID,
                protocolOp      CHOICE {
                        bindRequest     BindRequest,
                        bindResponse    BindResponse,
                        unbindRequest   UnbindRequest,
                        searchRequest   SearchRequest,
                        searchResEntry  SearchResultEntry,
                        searchResDone   SearchResultDone,
                        searchResRef    SearchResultReference,
                        modifyRequest   ModifyRequest,
                        modifyResponse  ModifyResponse,
                        addRequest      AddRequest,
                        addResponse     AddResponse,
                        delRequest      DelRequest,
                        delResponse     DelResponse,
                        modDNRequest    ModifyDNRequest,
                        modDNResponse   ModifyDNResponse,
                        compareRequest  CompareRequest,
                        compareResponse CompareResponse,
                        abandonRequest  AbandonRequest,
                        extendedReq     ExtendedRequest,
                        extendedResp    ExtendedResponse },
                 controls       [0] Controls OPTIONAL }

        MessageID ::= INTEGER (0 .. maxInt)

        maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --

        LDAPString ::= OCTET STRING

        LDAPOID ::= OCTET STRING

        LDAPDN ::= LDAPString

        RelativeLDAPDN ::= LDAPString

        AttributeType ::= LDAPString

        AttributeDescription ::= LDAPString
        AttributeDescriptionList ::= SEQUENCE OF
                AttributeDescription

        AttributeValue ::= OCTET STRING

        AttributeValueAssertion ::= SEQUENCE {
                attributeDesc   AttributeDescription,
                assertionValue  AssertionValue }

        AssertionValue ::= OCTET STRING

        Attribute ::= SEQUENCE {
                type    AttributeDescription,
                vals    SET OF AttributeValue }

        MatchingRuleId ::= LDAPString

        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 }

        Referral ::= SEQUENCE OF LDAPURL

        LDAPURL ::= LDAPString -- limited to characters permitted in URLs

        Controls ::= SEQUENCE OF Control

        Control ::= SEQUENCE {
                controlType             LDAPOID,
                criticality             BOOLEAN DEFAULT FALSE,
                controlValue            OCTET STRING OPTIONAL }

        BindRequest ::= [APPLICATION 0] SEQUENCE {
                version                 INTEGER (1 .. 127),
                name                    LDAPDN,
                authentication          AuthenticationChoice }

        AuthenticationChoice ::= CHOICE {
                simple                  [0] OCTET STRING,
                                         -- 1 and 2 reserved
                sasl                    [3] SaslCredentials }

        SaslCredentials ::= SEQUENCE {
                mechanism               LDAPString,
                credentials             OCTET STRING OPTIONAL }

        BindResponse ::= [APPLICATION 1] SEQUENCE {

             COMPONENTS OF LDAPResult,
             serverSaslCreds    [7] OCTET STRING OPTIONAL }

        UnbindRequest ::= [APPLICATION 2] NULL

        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 }

        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 {
                matchingRule    [1] MatchingRuleId OPTIONAL,
                type            [2] AttributeDescription OPTIONAL,
                matchValue      [3] AssertionValue,
                dnAttributes    [4] BOOLEAN DEFAULT FALSE }

        SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
                objectName      LDAPDN,
                attributes      PartialAttributeList }

        PartialAttributeList ::= SEQUENCE OF SEQUENCE {
                type    AttributeDescription,
                vals    SET OF AttributeValue }

        SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL

        SearchResultDone ::= [APPLICATION 5] LDAPResult

        ModifyRequest ::= [APPLICATION 6] SEQUENCE {
                object          LDAPDN,
                modification    SEQUENCE OF SEQUENCE {
                        operation       ENUMERATED {
                                                add     (0),
                                                delete  (1),
                                                replace (2) },
                        modification    AttributeTypeAndValues } }

        AttributeTypeAndValues ::= SEQUENCE {
                type    AttributeDescription,
                vals    SET OF AttributeValue }

        ModifyResponse ::= [APPLICATION 7] LDAPResult

        AddRequest ::= [APPLICATION 8] SEQUENCE {
                entry           LDAPDN,
                attributes      AttributeList }

        AttributeList ::= SEQUENCE OF SEQUENCE {
                type    AttributeDescription,
                vals    SET OF AttributeValue }

        AddResponse ::= [APPLICATION 9] LDAPResult

        DelRequest ::= [APPLICATION 10] LDAPDN

        DelResponse ::= [APPLICATION 11] LDAPResult

        ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
                entry           LDAPDN,
                newrdn          RelativeLDAPDN,
                deleteoldrdn    BOOLEAN,
                newSuperior     [0] LDAPDN OPTIONAL }

        ModifyDNResponse ::= [APPLICATION 13] LDAPResult
        CompareRequest ::= [APPLICATION 14] SEQUENCE {
                entry           LDAPDN,
                ava             AttributeValueAssertion }

        CompareResponse ::= [APPLICATION 15] LDAPResult

        AbandonRequest ::= [APPLICATION 16] MessageID

        ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
                requestName      [0] LDAPOID,
                requestValue     [1] OCTET STRING OPTIONAL }

        ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
                COMPONENTS OF LDAPResult,
                responseName     [10] LDAPOID OPTIONAL,
                response         [11] OCTET STRING OPTIONAL }

        END

Copyright (C) The Internet Society (1997). All Rights Reserved. ๐ŸŒˆ

okay so the Internet Society owns the copyright on this one, and every right is reserved ๐Ÿ”’ but they're being super generous about sharing it, bestie ๐Ÿซถ You can copy it and hand it out to people, and you can make derivative works that comment on or explain it or help people actually implement it. You can prepare those, copy them, publish them, and distribute them, either the whole thing or just bits, with no restrictions of any kind ๐Ÿฆ‹ The one catch is that the copyright notice and this paragraph have to stay on every copy and every derivative work ๐Ÿ’œ

Now the important bit ๐Ÿ‘€ The document itself may not be modified in any way. That means you can't remove the copyright notice, and you can't remove the references to the Internet Society or other Internet organizations. There are two exceptions. The first is if you need to do it to develop Internet standards, and then the copyright procedures in the Internet Standards process must be followed ๐Ÿ“ The second is if you need to translate it into a language other than English. Nobody's allowed to freestyle edits on the original, periodt ๐Ÿ’…

The limited permissions above are perpetual ๐Ÿ’– They will not be revoked by the Internet Society or its successors or assigns, so they're not going anywhere โœจ

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ๐Ÿ’€
๐Ÿ“ฆ where this page comes from