Introduction to LDAP

Tommi Virtanen <tv@debian.org>


Table of Contents

Foreword
1. LDAP Presents a Distributed Tree of Information
2. Objectclasses and Schemas
3. Object-oriented look at LDAP entries
4. Writing Things Down: LDIF
5. Searches and Search Filters
6. Phases of an LDAP Protocol Chat
Index

List of Figures

1.1. Tree-like, distributed nature of data stored in LDAP
5.1. Visualizing an LDAP search filter
6.1. Beginning of an LDAP protocol chat
6.2. A sample LDAP search operation
6.3. Multiple search operations pipelined
6.4. End of an LDAP protocol chat

List of Examples

2.1. An example attributeType definition
2.2. An example objectClass definition
4.1. A simple LDAP file with two entries.
4.2. A file containing an entry with a folded attribute value, from RFC2849.

Foreword

This text is intended as a quick introduction to the interesting bits of the LDAP protocol, and should be useful whether you are managing an LDAP server, programming something using an LDAP library, or writing an LDAP library yourself. I welcome any feedback you might have.

Chapter 1. LDAP Presents a Distributed Tree of Information

Probably the nicest way to get a mental model of LDAP information is to think of a tree with elements both in leaf and non-leaf nodes. Parts of the tree may reside at different LDAP servers.

Figure 1.1. Tree-like, distributed nature of data stored in LDAP

Tree-like, distributed nature of data stored in LDAP

An organization normally uses their DNS domain name as the root entry for their local LDAP tree. For example, example.com is free to use dc=example,dc=com. The dc stands for domainComponent. An alternative is to identify the organization via geographical location, as in o=Example Inc., c=US, but this is cumbersome as it requires registration to avoid name conflicts. The o stands for organization, c for country. You will also encounter ou, short for organizational unit.

Each node of the tree is called an "LDAP entry", and can contain multiple attributes in the form of attributeType=value pairs, for example surname=Wiesel. One attributeType may appear multiple times, in effect having multiple values.

One or more of the attributes are chosen as a Relative Distinguished Name, and will be used to identify the node based on its parent. This means the RDN must be unique among the children of its parent. Listing all the RDNs, separated by commas, from the node to the root, gives us the Distinguished Name of the entry.

The RDN of the entry for Jack E. Wiesel is cn=Jack E. Wiesel. The DN is cn=Jack E. Wiesel,ou=Sales,ou=People,dc=example,dc=com. The cn is short for common name.

The RDN of the entry for John Doe consist of two attributes, gn=John and sn=Doe, joined with a plus sign to form gn=John+sn=Doe. gn is short for given name (first name), sn for surname (last name).

Chapter 2. Objectclasses and Schemas

A special attributeType of objectClass lists all the objectclasses the LDAP entry manifests. An object class basically lists what attribute types an entry must have, and what optional attribute types it may have. For example, telephone directory entries must have a name and a telephone number, and may have a fax number and street address. objectClass can have multiple values, allowing the same entry to describe e.g. information about a person both for a telephone directory and for UNIX shell login.

An LDAP schema is a part of the configuration of the LDAP server, containing two things: definitions of attribute types and definitions of objectclasses. It is normally stored as ASCII text, but can e.g. be requested from the server over an LDAP connection.

An attribute type definition commonly contains a global identifier for the attribute type (a list of period-separated integers), a list of names for the attribute type, a free-form description and a reference to another attribute type this definition inherits from. It may also contain information about what sort of data the attribute values may contain, how to compare and sort them, how to find substrings in the value, whether the attribute type can have multiple values, etc.

Example 2.1. An example attributeType definition

attributetype ( 2.5.4.4 NAME ( 'sn' 'surname' )
	DESC 'RFC2256: last (family) name(s) for which the entity is known by'
	SUP name )
      

An object class definition also commonly contains a global identifier, name, description and inheritance information. It also commonly lists the attribute types entries having this object class must have, and additional attribute types they may have. An entry cannot have attribute types that are not listed as a MUST or MAY by one of the entrys object classes or their parents.

Example 2.2. An example objectClass definition

objectclass ( 2.5.6.6 NAME 'person'
	DESC 'RFC2256: a person'
	SUP top STRUCTURAL
	MUST ( sn $ cn )
	MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
      

There are a lot of pre-existing schemas, standardized in various RFCs. Also, anyone can create their own schemas. The only things you need are access to the LDAP server configuration, and a number reserved for you, which can be achieved by filling a web form.

Chapter 3. Object-oriented look at LDAP entries

If you look at LDAP entries from the viewpoint of a programmer accustomed with object oriented programming, you will see a lot of similarities, but also some striking differences:

  • An LDAP entry corresponds with an object.

  • Whereas object are usually instances of a single class, LDAP entries can "implement" multiple objectClasses.

  • objectClasses can inherit zero, one or many objectClasses, just like programming classes.

  • objectClasses have a root class, known as top; many object oriented programming languages have a root class, e.g. named Object.

  • objectClasses are either STRUCTURAL or AUXILIARY; entries can only implement one STRUCTURAL objectClass.

  • The objectClasses of an entry can be changed at will; you only need to take care that the entry has all the MUST attribute types, and no attribute types outside of the ones that are MUST or MAY.

    Note that e.g. OpenLDAP doesn't implement this.

  • Attributes of an entry closely match attributes of objects in programming languages; however, LDAP attributes may have multiple values.

Chapter 4. Writing Things Down: LDIF

There is a standardized way of writing down, in plain text, the contents of LDAP directories, individual entries and even add, delete and modify operations. This format is known as LDIF (LDAP Data Interchange Format), and it is defined in RFC2849.

The rough format of LDIF is this: there is a paragraph per entry, where paragraphs are separated by blank lines. Each paragraph contains lines in the format keyword: value. Entries start by listing the keyword dn, and their DN, and then list all the attributes and values the entry has. Lines starting with space are appended to the previous line. The whole file starts with the keyword version and value 1. [1]

Example 4.1. A simple LDAP file with two entries.

version: 1
dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
cn: Barbara Jensen
cn: Barbara J Jensen
cn: Babs Jensen
sn: Jensen
uid: bjensen
telephonenumber: +1 408 555 1212
description: A big sailing fan.

dn: cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
cn: Bjorn Jensen
sn: Jensen
telephonenumber: +1 408 555 1212
      

Example 4.2. A file containing an entry with a folded attribute value, from RFC2849.

version: 1
dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
objectclass:top
objectclass:person
objectclass:organizationalPerson
cn:Barbara Jensen
cn:Barbara J Jensen
cn:Babs Jensen
sn:Jensen
uid:bjensen
telephonenumber:+1 408 555 1212
description:Babs is a big sailing fan, and travels extensively in sea
 rch of perfect sailing conditions.
title:Product Manager, Rod and Reel Division
      



[1] The actual format is more complex, but this tutorial should allow you to read and write normal LDIF files fluently.

Chapter 5. Searches and Search Filters

The most common LDAP operation is a search, and LDAP is purposefully designed for environments where searches are many times more common than modify operations. In general, LDAP servers index the entries and can effectively search for matches against a reasonably complex criteria among thousands of entries.

An LDAP search takes the following information as input: [2]

  • The base DN for the search

  • A search filter, specifying criteria an entry must fulfill to match.

  • Scope of the search, either look at the base DN only, only look one level below it, or look at the whole subtree rooted at the base DN.

  • Size limit of at most how many matching entries to return.

  • Attributes to return, or none for all attributes the matching entries happen to have.

Of these, the search filter is clearly the most interesting one. As with LDIF, search filters have a standardized plain text representation, even though they are not transmitted as plain text in the actual protocol.

A search filter is basically a combination of tests an entry must fulfill in order to match the filter. They are always written inside parentheses. A simple example would be

(cn=John Smith)

but the filters can also match against presence, prefix, suffix, substring, rough equality, etc. Multiple matches can be combined freely with and, or and not operators, which are represented by &, | and !, respectively. For example, to match only objects that have objectClass person, where the full name contains the letters a and b in either order, and who don't have a telephone number listed, we could use the filter [3]

(&(objectClass=person)(!(telephoneNumber=*))(|(cn=*a*b*)(cn=*b*a*)))

Figure 5.1. Visualizing an LDAP search filter

Visualizing an LDAP search filter



[2] Once again, we are skipping some details for understandability.

[3] Yes, once again we are skipping details for understandability. See RFC2254 for more.

Chapter 6. Phases of an LDAP Protocol Chat

An average LDAP protocol chat consists of three stages:

  1. Opening the connection

  2. Doing one or more searches

  3. Closing the connection

At the first stage, opening a connection, an LDAP client opens a TCP connection to the LDAP server, either as plain text, encrypted by TLS or starting with plaintext and switching to use TLS with STARTTLS.

The client authenticates itself and/or the user, providing any necessary authentication information. This is called binding. Normally, the connection is not really authenticated, but left as anonymous; the bind message is sent with no user or password information.

Figure 6.1. Beginning of an LDAP protocol chat

Beginning of an LDAP protocol chat

Next, the client sends a search request, containing the base DN for the search, the filter that entries must fulfill to match, and some extra settings discussed above.

The server replies by sending search result entries back, one message per matching entry. If no entry matched or there was an error before the search could even start, the server might not send any entries. Finally, the server sends a message indicating the search is done, and includes information on whether the search was completely successfully, or the error encountered.

Figure 6.2. A sample LDAP search operation

A sample LDAP search operation

Note that the client could have sent another search request without waiting for the first search to complete. The order of results from the different search, or when they are completed, is in no way guaranteed.

Figure 6.3. Multiple search operations pipelined

Multiple search operations pipelined

One important detail we have skimmed over so far is how the LDAP client knows what message the server is replying to. Earlier we avoided this topic just by doing only one thing at a time, but now we have two searches getting their result entries interleaved. Clearly, there must be a mechanism to separate which entries belong to which search request. And exactly such a mechanism exists; each message sent by the client contains a number identifying the request, and the server replies by including the same number in the reply. Now, all the client needs to do is remember which numbers are still in use, and not reuse those. It can internally maintain search state based on these numbers, and process result entries based on them. The client can reuse a number when it is known that no more server replies will be sent using that number; for example, the search done message gives this guarantee.

Finally, when the client longer wants to talk to the server, it sends a message effectively saying "good bye". This message is known as unbind. This only means that the state of connection is the same as when connected, before the first bind; that is, it unauthenticates the current user. If the client really wants to close the connection, it will then close the TCP socket.

Figure 6.4. End of an LDAP protocol chat

End of an LDAP protocol chat

Please understand that these were just examples, and in reality protocol chats are often more complicated. For example, one could connect some other protocol servers, say a web servers, authentication mechanism to actually act as an LDAP client, that tries to bind as the user authenticating himself to the web server, with the password given by the user. If this service had no other interest in the contents of LDAP, it would probably immediately after the bind close the connection. But opening and closing TCP connections repeatedly is slow; it is quite likely the authentication mechanism would be changed to keep a single TCP connection alive, and just do repeated binds over the same connection.

Index

L

LDIF
LDAP Data Interchange Format, Writing Things Down: LDIF

R

Relative Distinguished Name
RDN, LDAP Presents a Distributed Tree of Information