RFC 2255

The LDAP URL Format

πŸ“… published December 1997, from ietf

The LDAP URL Format πŸŽ€

Okay bestie, let's get into RFC 2255 ✨ It's called The LDAP URL Format and it's by T. Howes and M. Smith from Netscape Communications Corp., published in the Network Working Group in December 1997. It's a Standards Track doc, so it's an actual Internet standards protocol πŸ’… It also replaces RFC 1959 and updates the LDAP URL format for version 3 of LDAP. Let's go πŸ¦‹

1. Status of this Memo ✨

Okay so this doc specifies an Internet standards track protocol for the Internet community, and it's literally asking for discussion and suggestions for improvements 🫢 If you want to know where it stands in standardization, check the current edition of the "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited, so share away πŸ’–

Copyright (C) The Internet Society (1997). All Rights Reserved. 🌸

IESG NOTE πŸ™ˆ

Real talk, this one's a little serious. This document describes a directory access protocol that gives both read and update access. Update access needs secure authentication, but this document doesn't require anyone to implement any satisfactory authentication mechanisms 😭

So the IESG approved it as a Proposed Standard anyway, under RFC 2026, section 4.4.1, for three 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.

Now the warning, bestie 🚨 Until mandatory authentication mechanisms are standardized, clients and servers written to this spec that use the 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 that implement the update functionality until a Proposed Standard for mandatory authentication in LDAPv3 has been approved and published as an RFC. πŸ’€

2. Abstract 🧚

So LDAP is the Lightweight Directory Access Protocol, defined in [1], [2] and [3] πŸ“ This document describes a format for an LDAP Uniform Resource Locator. The format describes an LDAP search operation to perform to retrieve information from an LDAP directory. This document replaces RFC 1959. It updates the LDAP URL format for version 3 of LDAP and clarifies how LDAP URLs are resolved. It also defines an extension mechanism for LDAP URLs, so future documents can extend their functionality, for example to provide access to new LDAPv3 extensions as they get defined. Iconic behavior, honestly ✨

The key words "MUST", "MAY", and "SHOULD" used in this document are to be interpreted as described in [6]. πŸ”₯

3. URL Definition πŸŽ€

An LDAP URL begins with the protocol prefix "ldap" and is defined by the following grammar. Here it is, in all its glory πŸ‘‘

       ldapurl    = scheme "://" [hostport] ["/"
                    [dn ["?" [attributes] ["?" [scope]
                    ["?" [filter] ["?" extensions]]]]]]
       scheme     = "ldap"
       attributes = attrdesc *("," attrdesc)
       scope      = "base" / "one" / "sub"
       dn         = distinguishedName from Section 3 of [1]
       hostport   = hostport from Section 5 of RFC 1738 [5]
       attrdesc   = AttributeDescription from Section 4.1.5 of [2]
       filter     = filter from Section 4 of [4]
       extensions = extension *("," extension)
       extension  = ["!"] extype ["=" exvalue]
       extype     = token / xtoken
       exvalue    = LDAPString from section 4.1.2 of [2]
       token      = oid from section 4.1 of [3]
       xtoken     = ("X-" / "x-") token

The "ldap" prefix points to an entry or entries living in the LDAP server running on the given hostname at the given portnumber. The default LDAP port is TCP port 389. If no hostport is given, the client must have some apriori knowledge of an appropriate LDAP server to contact. 🧠

The dn is an LDAP Distinguished Name using the string format described in [1]. It identifies the base object of the LDAP search. πŸ’–

Same grammar again, because the original repeats it, so here it is once more πŸ™ƒ

   ldapurl    = scheme "://" [hostport] ["/"
                    [dn ["?" [attributes] ["?" [scope]
                    ["?" [filter] ["?" extensions]]]]]]
       scheme     = "ldap"
       attributes = attrdesc *("," attrdesc)
       scope      = "base" / "one" / "sub"
       dn         = distinguishedName from Section 3 of [1]
       hostport   = hostport from Section 5 of RFC 1738 [5]
       attrdesc   = AttributeDescription from Section 4.1.5 of [2]
       filter     = filter from Section 4 of [4]
       extensions = extension *("," extension)
       extension  = ["!"] extype ["=" exvalue]
       extype     = token / xtoken
       exvalue    = LDAPString from section 4.1.2 of [2]
       token      = oid from section 4.1 of [3]
       xtoken     = ("X-" / "x-") token

The "ldap" prefix points to an entry or entries living in the LDAP server running on the given hostname at the given portnumber. The default LDAP port is TCP port 389. If no hostport is given, the client must have some apriori knowledge of an appropriate LDAP server to contact. ✨

The dn is an LDAP Distinguished Name using the string format described in [1]. It identifies the base object of the LDAP search. 🌈

The attributes construct tells you which attributes should be returned from the entry or entries. Individual attrdesc names are as defined for AttributeDescription in [2]. If the attributes part is left out, all user attributes of the entry or entries should be requested (e.g., by setting the attributes field AttributeDescriptionList in the LDAP search request to a NULL list, or (in LDAPv3) by requesting the special attribute name "*"). πŸ¦‹

The scope construct sets the scope of the search in the given LDAP server. The allowable scopes are "base" for a base object search, "one" for a one-level search, or "sub" for a subtree search. If scope is omitted, a scope of "base" is assumed. πŸ“

The filter is the search filter applied to entries within the specified scope during the search. It has the format specified in [4]. If filter is omitted, a filter of "(objectClass=*)" is assumed. πŸ’…

The extensions construct gives the LDAP URL an extensibility mechanism, so the URL's capabilities can be extended in the future. Extensions are a simple comma-separated list of type=value pairs, where the =value portion MAY be omitted for options that don't need it. Each type=value pair is a separate extension. These LDAP URL extensions aren't necessarily related to any of the LDAPv3 extension mechanisms. The client resolving the URL may or may not support any given extension. An extension prefixed with a '!' character (ASCII 33) is critical. An extension not prefixed with a '!' character is non-critical. πŸ”₯

If an extension is supported by the client, the client MUST obey the extension if the extension is critical. The client SHOULD obey supported extensions that are non-critical. πŸ’–

If an extension is unsupported by the client, the client MUST NOT process the URL if the extension is critical. If an unsupported extension is non-critical, the client MUST ignore the extension. πŸ™…β€β™€οΈ

If a critical extension can't be processed successfully by the client, the client MUST NOT process the URL. If a non-critical extension can't be processed successfully by the client, the client SHOULD ignore the extension. 🫢

Extension types prefixed by "X-" or "x-" are reserved for bilateral agreements between communicating parties. Other extension types MUST be defined in this document, or in other standards-track documents. πŸ‘‘

One LDAP URL extension is defined in this document, in the next section. Other documents or a future version of this document MAY define other extensions. ✨

Note that any URL-illegal characters (e.g., spaces), URL special characters (as defined in section 2.2 of RFC 1738), and the reserved character '?' (ASCII 63) that show up inside a dn, filter, or other element of an LDAP URL MUST be escaped using the % method described in RFC 1738 [5]. If a comma character ',' shows up inside an extension value, that character MUST also be escaped using the % method. πŸŽ€

4. The Bindname Extension 🧚

This section defines an LDAP URL extension for representing the distinguished name a client uses when authenticating to an LDAP directory during resolution of an LDAP URL. Clients MAY implement this extension. πŸ’œ

The extension type is "bindname". The extension value is the distinguished name of the directory entry to authenticate as, in the same form as described for dn in the grammar above. The dn may be the NULL string to specify unauthenticated access. The extension may be either critical (prefixed with a '!' character) or non-critical (not prefixed with a '!' character). πŸ¦‹

If the bindname extension is critical, the client resolving the URL MUST authenticate to the directory using the given distinguished name and an appropriate authentication method. Note that for a NULL distinguished name, no bind MAY be required to get anonymous access to the directory. If the extension is non-critical, the client MAY bind to the directory using the given distinguished name. πŸ”₯

5. URL Processing πŸ’…

This section describes how an LDAP URL SHOULD be resolved by a client. Let's walk through the steps 🌸

First, the client gets a connection to the LDAP server referenced in the URL, or to an LDAP server of the client's choice if no LDAP server is explicitly referenced. This connection MAY be opened specifically to resolve the URL, or the client MAY reuse an already open connection. The connection MAY provide confidentiality, integrity, or other services, e.g., using TLS. Use of security services is at the client's discretion if not specified in the URL. πŸ”

Next, the client authenticates itself to the LDAP server. This step is optional, unless the URL contains a critical bindname extension with a non-NULL value. If a bindname extension is given, the client proceeds according to the section above. 🫢

If a bindname extension is not specified, the client MAY bind to the directory using a appropriate dn and authentication method of its own choosing (including NULL authentication). ✨

Next, the client performs the LDAP search operation specified in the URL. Additional fields in the LDAP protocol search request, such as sizelimit, timelimit, deref, and anything else not specified or defaulted in the URL specification, MAY be set at the client's discretion. πŸ“

Once the search has completed, the client MAY close the connection to the LDAP server, or the client MAY keep the connection open for future use. Main character energy, honestly πŸ‘‘ πŸ¦‹

6. Examples ✨

okay bestie, examples time 🫢 these show the LDAP URL format from earlier in action, and once you see them it's giving total clarity. The first one points at the University of Michigan entry on whichever LDAP server the client picks:

ldap:///o=University%20of%20Michigan,c=US

The next one names a specific server, so the University of Michigan entry lives on that exact host:

ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US

Both of these mean the same thing: a base object search of the "o=University of Michigan, c=US" entry with the filter "(objectclass=*)", asking for all attributes πŸ’…

Now we get more specific. This one only asks for the postalAddress attribute of that same entry 🏠

ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,
       c=US?postalAddress

The search operation is identical to the last example, except now only postalAddress gets requested. Small change, big vibe πŸ¦‹

Next up is a subtree search on port 6666 of the University of Michigan, looking for any entry with a common name of "Babs Jensen" and returning all attributes. Main character energy πŸ‘‘

ldap://host.com:6666/o=University%20of%20Michigan,
       c=US??sub?(cn=Babs%20Jensen)

This one is a one-level search of all the children under the c=GB entry, asking for the objectClass attribute back. The filter is left out, so the default "(objectclass=*)" kicks in 🌈

ldap://ldap.itd.umich.edu/c=GB?objectClass?one

Here's one where the escaping is the star 🌟 It retrieves the mail attribute for the entry named "o=Question?,c=US". The reserved character '?' gets escaped, so the question mark inside the name doesn't get mistaken for a delimiter. Iconic, honestly 😭

ldap://ldap.question.com/o=Question%3f,c=US?mail

Then we get the interaction between LDAP quoting and URL quoting, which is a lot but we're handling it πŸ’ͺ The filter here uses LDAP's own escaping with \ to encode three zero bytes (null bytes) in the value:

ldap://ldap.netscape.com/o=Babsco,c=US??(int=%5c00%5c00%5c00%5c04)

In LDAP the filter would be written as (int=\00\00\00\04). The thing is, \ has to be escaped inside a URL too, so each \ becomes %5c in the URL encoding. Two layers of escaping, one URL, zero chill πŸ™ˆ

Last one, and it's a fun one. It shows the bindname extension, which tells the client which dn to use for authentication when it resolves the URL πŸŽ€

ldap:///??sub??bindname=cn=Manager%2co=Foo
ldap:///??sub??!bindname=cn=Manager%2co=Foo

These two are the same, except the second one marks the bindname extension as critical (that's what the ! does). Also notice the comma in the distinguished name is encoded with % as %2c, because a raw comma would mess with the value πŸ’œ


7. Security Considerations πŸ”

okay this section is serious but also dramatic, so let's gooo. The general URL security stuff from [5] applies to LDAP URLs too, so that's the baseline πŸ’–

Using security mechanisms while processing LDAP URLs needs real care, ngl. Clients can run into tons of different servers through URLs, and URLs usually get processed automatically with nobody watching 😬 So a client SHOULD have a user-configurable policy about which servers it connects to and which security mechanisms it uses, and it SHOULD NOT make connections that go against that policy. No freelancing, bestie 🚫

Sending authentication info, no matter what mechanism, can violate a user's privacy requirements. So unless a policy specifically says it's okay to send authentication info to a server, a client should use an anonymous connection πŸ•ΆοΈ (And to be clear, clients following the older LDAP URL specs, where every connection is anonymous and unprotected, still fit this spec. They just have the default security policy πŸ“)

Some authentication methods, especially reusable passwords sent to the server, can expose info that's easy to abuse, either to the remote server or to someone eavesdropping along the way. They should not be used in URL processing unless a policy explicitly allows it 😭 Having the human user confirm before authentication info gets used is a good idea in lots of situations. Strong authentication methods that don't reveal sensitive info are way more preferred ✨

The LDAP URL format lets you specify any LDAP search to run when the URL gets evaluated. That means following one can cause surprises, like pulling back huge amounts of data or kicking off a long-running search πŸŒͺ️ Resolving an LDAP URL has the same security implications as resolving an LDAP search query, so treat it that way πŸ’…


8. Acknowledgements 🌸

The LDAP URL format was first defined at the University of Michigan πŸŽ“ This work was based on research supported by the National Science Foundation under Grant No. NCR-9416667. Huge thanks to both the University of Michigan and the National Science Foundation 🫢

A bunch of people left valuable comments on this document, and RL "Bob" Morgan and Mark Wahl deserve extra love for their contributions πŸ’œ


9. References πŸ“š

  • [1] Wahl, M., Kille, S., and T. Howes, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names", RFC 2253, December 1997.
  • [2] Wahl, M., Howes, T., and S. Kille, "Lightweight Directory Access Protocol (v3)", RFC 2251, December 1997.
  • [3] Wahl, M., Coulbeck, A., Howes, T. and S. Kille, "Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions", RFC 2252, December 1997.
  • [4] Howes, T., "A String Representation of LDAP Search Filters", RFC 2254, December 1997.
  • [5] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource Locators (URL)," RFC 1738, December 1994.
  • [6] Bradner, S., "Key Words for use in RFCs to Indicate Requirement Levels," RFC 2119, March 1997.

Authors' Addresses πŸ¦‹

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

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

Mark Smith Netscape Communications Corp. 501 E. Middlefield Rd. Mountain View, CA 94043 USA

Phone: +1 415 937-3477 EMail: mcs@netscape.com


Copyright (C) The Internet Society (1997). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

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