OpenLDAP includes two daemons: SLAPD and SLURPD. SLAPD is the main server, and we will examine its operation throughout this book. SLURPD is a special-purpose daemon used for replicating directories. While it is still in use, it is now deprecated in favor of a more robust replication mechanism. We will cover it only briefly in this book.
The first, SLAPD, is the stand-alone LDAP daemon. It is the LDAP server. It listens for client requests and, when it receives a request, performs the requested operation and returns any necessary data. In the most common case a client will send a query message to the server. The SLAPD server will then look up the information and return the results. Let’s consider an example (in conversational English):
Client: Log in as user Bob with the password Password
Server: Bob is now logged in
Client: Bob wants all of the usernames of users whose email addresses start with ‘m’
Server: There are four users with email addresses that start with ‘m’. The user IDs are: mattb, markd, melaniek, melindaq
Client: Log Bob off
This example is very simplistic (and omits lots of the details of an LDAP transaction), but it should give you the main idea of what SLAPD does.
The SLAPD program is called, appropriately enough,
slapd. It is located at
/usr/sbin (if you compiled from source, it is in
/usr/local/libexec). In the previous chapter we configured SLAPD using the
/etc/ldap/slapd.conf configuration file.
The SLAPD server handles all client interactions, including authentication, processing ACLs, performing searches, and handling changes, additions, and deletions of the data. It also manages the databases that store LDAP content. All of the clients that we look at in this chapter interact directly with SLAPD. The utilities provide maintenance services for SLAPD, though they rarely directly interact with the SLAPD server (they tend to operate on files that the directory uses).
Let’s take a slightly more technical look at the simple LDAP exchange that we outlined here. We can break the exchange into two major parts: the authentication process (called binding in LDAP parlance) and the search process.
The Binding Operation
The first thing that must happen is the client must authenticate to the server. Keep in mind that in order to interact with an LDAP server the client must provide two pieces of information: a DN and a password.
Typically, there are two different ways by which a client can authenticate to a server: through a Simple Bind, and through an SASL Bind. It is possible to write custom methods of binding, too, but that’s a significant undertaking. Let’s look at the way clients connect to LDAP using the Simple Bind method.
Typically, to authenticate a user, SLAPD looks up the DN (and the DN’s
userPassword attribute) in the directory and verifies the following:
- The supplied DN exists in the directory.
- The DN is allowed to connect under the present conditions (such as from the originating IP address, or with the currently-implemented security features).
- The password supplied matches the value of the DN’s
In our example scenario the user Bob wants to bind to the directory. For Bob to bind according to the outlined steps, the client would have to provide Bob’s full DN, which might be something like
cn=Bob,dc=example,dc=net. But, not all clients know the full DN of the user. Most applications require only a username and password, not a full DN. To solve this problem, LDAP servers support the idea of the Anonymous user.
When the LDAP server receives a bind request with an empty DN and an empty password field, the server treats the user as Anonymous. The Anonymous user can be granted or denied access to information in the directory based on the ACLs specified for SLAPD. Generally, the task of the Anonymous user is to get Bob’s DN out of the directory and request that Bob be authenticated.
How does this happen? The client first connects to the server as Anonymous, then searches the directory for Bob’s entry with a filter of something like this: entries whose CN is “Bob” and who have the objectclass “organizationalPerson”.
The actual LDAP filter for this request would look like this:
Assuming that the filter is specific enough, and the directory actually has an entry for Bob, then the server would then send the client one DN:
cn=Bob,dc=example,dc=net. The client would then re-bind, this time as
cn=Bob,dc=example,dc=net (and with Bob’s password), rather than as Anonymous.
In order for anonymous authentication to work, the ACLs will need to allow the Anonymous user to bind and attempt to perform authentication. The ACLs we added to
slapd.conf in the previous chapter allowed the Anonymous user to request authentication services with the
In this tutorial, we will use Simple Binding, though we will specify a full DN, rather than bind as Anonymous and search, and then rebind. Simple Bind sends the password from the client to the server. Without additional security (like SSL or TLS encryption), this makes the authentication process vulnerable to attacks. SASL (Simple Authentication and Security Layer) Binding provides another method of authenticating that relies on external security measures for added security. In Chapter 4, we will look at the authentication process in more detail, with particular emphasis on security.
The Search Operation
In our example scenario, after Bob authenticates to the server he searches for all the email addresses that begin with the letter m. Let’s examine that process in a little more detail.
In order to search the directory we need to know the following things:
Base DN: Where in the directory to start from
Scope: How deep in the tree to look
Attributes: What information we want retrieved
Filter: What to look for
Let’s look at what Bob wants to get out of the directory. Bob wants to get a list of all of the people in his organization, Example.Com, who have email addresses that begin with the letter m. From this information, we can construct a search.
First, Bob wants to know about everyone in the Example.Com organization. In the directory, this is everything under the Example.Com entry:
dc=example,dc=com. Also, since we know that Bob wants all of the email addresses that begin with m, not just one layer down; we know that Bob wants to search the entire subtree under
dc=example,dc=com. So we have:
Scope: Entire subtree
Next, we want to know what attributes Bob wants the server to return. The DN will be automatically returned. Other than that, Bob is concerned only with the attribute that stores the email address. Email addresses are stored in the
cn) and telephone number (
telephoneNumber). So we have:
The attribute referred to by
rfc822Mailbox. These two names are called attribute descriptions because they both describe a common attribute. Each attribute has at least one attribute description, but it is legal to have multiple descriptions (such as
domainComponent). When you have an attribute with more than one description it doesn’t matter which description you use. All should return the same results.
Finally, we need to create a filter from Bob’s criteria. Bob wants all of the entries where the email address starts with the letter m.
Here is the search filter:
First, the filter is enclosed in parentheses. Parentheses are used for grouping elements within the filter. For any filter, the entire filter should always be enclosed in parentheses.
Second, the filter begins with an attribute description:
Third is the matching rule. There are four matching rules: equality (
=), approximate match (
~=), greater than or equal to (
>=), and less than or equal to (
<=). How these are used (and whether they can be used) is determined to a large degree by the directory schema, which we will discuss at length in Chapter 6. In this case the filter performs string matching.
Finally, we have the assertion value—the string or pattern that we want results to match. In this case it is composed of the character
mand the wildcard character (
*). This indicates that the string must start with
m, and can then have zero or more characters following it.
This type of search is called a substring search, because the filter provides only part of the string, and requests that the server respond with any entries that match the substring (according to the pattern supplied).
What if Bob also needed all of the users with email addresses that started with
n? We could run two separate searches, or we could create a more elaborate filter:
This filter is composed of two subfilters:
(mail=n*). The first matches only mail addresses that start with m, while the second matches only addresses that start with n. These two subfilters are disjoined using the pipe (
|) symbol. That means that an OR operation will be performed, and the filter will match a record if the record matches either
The syntax may seem a little unusual at first, as the operator (the OR) comes before the two filters are listed.
There are three logical operators that can be used in filters: AND (
&), OR (
|), and NOT (
Just to make things more interesting, let’s say that Bob wants to restrict the list to only people whose offices have room numbers of 300 or above. We can simply add one more sub-filter to our list, and we will have the results that Bob is looking for:
To visualize this a little better let’s add some line breaks and spaces:
(& (| (mail = m*) (mail = n*) ) (roomNumber >= 300) )
Now it should be a little easier to see how this filter is interpreted. In the innermost level, mail addresses are considered matches if they start with m OR n. Now, these matches are only returned if they also have a room number greater than or equal to 300. They must match either
(mail=n*), AND, in addition, must also have
(roomNumber >= 300).
Once Bob performs the search, with the base DN, scope, attributes, and filter, he will receive a response from the server that will contain a list of records that look something like this:
dn:cn=Matt B,dc=example,dc=com mail: firstname.lastname@example.org cn: Matt B cn: Matthew B telephoneNumber: +1 555 555 55555 dn: cn=Melanie K,dc=example,dc=com mail: email@example.com cn: Melanie K elephoneNumber: +1 555 555 4444
The search returns everything in appearing in the subtree below the DN
dc=example,dc=com that matches our filter. The returned records only have the DN and the attributes that we specified:
In our most complex filter, we used the
roomNumber attribute. Why isn’t it present in the records above? Even though it was used in the filter the attribute value would not be returned in the response unless we requested it.
Before going on, there is one last thing to mention about searching. During a search the entire request is checked against the list of access controls.
If an ACL specifies that Bob does not have access to the
telephoneNumber attribute, then the search will return the same DNs but without the
telephoneNumber attribute. Similarly, if an ACL denied Bob access to the records of certain people in the directory, then the server would send back the results for only those that Bob does have permission to see.
The server will not give Bob any indication that some information has been withheld because of an ACL.
More Operations: Additions, Modifications, and Deletions
In our illustration of Bob’s search for email addresses we covered only binding and searching. Of course, LDAP supports adding, modifying, and deleting, as well. All three of these also require that the user first bind. And all three of these are also subject to ACL restrictions.
The Addition Operation
In an addition operation a new record is added to the server. In this case the client will have to provide a new (and unique) DN, and set of attribute/value pairs. The attribute/value pairs must include a list of object classes to which the entry belongs. For example, if the entry is going to be a new user with a user ID and an email account, then the modification would have to include at least three object class attribute/value pairs.
An entire record for a user to be added might look something like this:
dn: uid=bjensen,dc=exaple,dc=com cn: Barbara Jensen mail: firstname.lastname@example.org uid: bjensen objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson
The Modification Operation
Modification acts on a particular record, specified by DN. Any number of changes can be done on a single record in one modification request.
For a particular record, a modification operation can add, replace, or remove attributes. And it can combine operations in the same request. That is, it can remove one attribute and replace another attribute in one request. Let’s see these attributes:
- An add request takes an attribute name and one or more values. It will add those values to the existing set of values for that attribute. For example, consider a record like this:
dn: cn=Matt,dc=example,dc=com cn: Matt telephoneNumber: 1 555 555 1234 telephoneNumber: 1 555 555 4321 objectClass: person
If we want to modify this record by adding
cn: Matthew, the result will look like this:
dn: cn=Matt,dc=example,dc=com cn: Matt cn: Matthew telephoneNumber: 1 555 555 1234 telephoneNumber: 1 555 555 4321 objectClass: person
If we want to modify this record by adding
cn: Matthew, the result will look like this:
- A replace request also takes an attribute and one or more values. But the list of values replaces the existing values. For example, if Matt relocated and his telephone number changed, then replacing with the new attribute
1 555 555 6543would result in a record that looked like this:
dn: cn=Matt,dc=example,dc=com cn: Matt cn: Matthew telephoneNumber: 1 555 555 6543 objectClass: person
The new number is added and the old numbers are removed.
dn: cn=Matt,dc=example,dc=com cn: Matt telephoneNumber: 1 555 555 6543 objectClass: person
Only the matching CN was removed. If, however, a delete request only specifies the attribute (with no values), then all instances of that attribute will be removed.
The Delete Operation
Finally, an entire LDAP record can be deleted. Like modifications, deletion operates on a particular record, the record’s DN. During a delete operation, the entire record is removed from the directory—the DN and all attributes.
Only records that do not have children can be deleted from the directory. If an entry has children, the children must be removed from the directory (or relocated to another part of the tree) before the parent entry can be removed.
There are a few operations that clients can call, but that tend to be used less than binding, searching, adding, modifying, and deleting. Three that we will look at just briefly are ModifyDN, Compare, and Extended Operation.
The ModifyDN Operation
ModifyDN is used in cases where the DN for a record must be changed. Generally, DNs should not be changed frequently as they are intended to be used as unique and stable locators within a directory tree. However, it is not difficult to envision cases where a DN needs to be changed. The following figure displays a (full) DN:
A (full) DN is composed of two parts:
Second, there is the part that refers to the parent record of the DN. It is specific to this record. The
dc=example,dc=compart in the same example points to the parent of this record.
Given the DN, we know how far down the directory tree this record is. It is one layer below the root of the tree—the base DN (
The ModifyDN operation provides a way to change just the RDN or the entire DN. Changing the latter equates to moving the record to another part of the directory tree.
The Compare Operation
A Compare operation takes a DN and an attribute value assertion (attribute = value), and checks to see if that attribute assertion is true or false. For example, if the client supplies the DN
cn=Matt,dc=example,dc=com and the attribute value assertion
cn=Matthew, then the server will return true if the record has an attribute
cn with the value
Matthew, or false otherwise. This operation can be faster (and also more secure) than fetching a record and doing the comparison on the client side.
In OpenLDAP ACLs, the
auth permission setting (as well as the
=x permission setting that we will look at in the next chapter) allows the Compare operation to be used, but does not allow the attribute value to be returned in a search. The
read permission (
=xw) allows both the Compare operation and the return of the attribute value in search results.
The Extended Operation
Finally, OpenLDAP implements the LDAP v.3 Extended Operation, which makes it possible for a server to implement custom operations.
The exact syntax of an Extended Operation will depend on the implementation of the extension. The supported Extended Operations are listed in the root DSE under the
supportedExtension attribute. Take a look at the root DSE at the end of Chapter 2. In that record there are two extended operations:
184.108.40.206.4.1.4220.127.116.11: This Modify Password extension is defined in RFC 3062 (http://www.rfc-editor.org/rfc/rfc3062.txt). This extension provides an operation for updating a password in the directory.
18.104.22.168.4.1.422.214.171.124: This Who Am I? extension is defined in RFC 4532 (http://www.rfc-editor.org/rfc/rfc4532.txt). This extension makes it possible for the currently active DN to find out about itself from the server.
Later in this chapter we will look at tools that use the Modify Password and the Who Am I? extensions.
In this section we have looked at some of the operations that the SLAPD server makes available to the clients. We’ve looked at the most common operations (binding, searching, modifying, adding, and deleting). We’ve also looked at a few of the less-known operations like modifyDN, Compare, and Extended Operations as well.
By now you should have a good idea of what services the SLAPD server provides to clients. Clients can bind (or authenticate) to a SLAPD server and perform powerful searches of the directory. And through SLAPD the information in the directory tree can be maintained.
These concepts will be central to the rest of this chapter, and the rest of this book.
Next, we’ll look at the SLURPD daemon, though we will not go into much detail.
SLAPD and SLURPD are the two daemons included in the OpenLDAP suite. Above, we looked at the SLAPD server. Now we will turn to the second daemon.
SLURPD, the Stand-alone LDAP Update Replication Daemon, is used less frequently than SLAPD, and is on its way to obsolescence. SLURPD provides one way of keeping multiple copies of an LDAP directory synchronized (see the discussion in Chapter 1). Basically it works by tracking the changes (additions, deletions, modifications) to a master SLAPD directory server. When a change is made to the master directory, SLURPD sends updates to all of the subordinate slave servers.
The SLURPD program,
slurpd, is located at
/usr/local/libexec, if you compiled from source). In configurations where SLURPD is used,
slurpd is typically started immediately after
slapd. SLURPD does not have its own configuration file. It searches the
slapd.conf file for configuration information.