LDAP defines four basic models that fully describe how it operates, what data can be stored in LDAP directories, and what can be done with that data. The LDAP Information ModelThe LDAP information model defines the types of data and basic units of information you can store in your directory. In other words, the LDAP information model describes the building blocks you can use to create your directory. Entries, Attributes, and ValuesThe basic unit of information in the directory is the entry , a collection of information about an object. Often the information in an entry describes a real-world object such as a person, but the model does not require this. In a typical directory you'll find thousands of entries that correspond to people, departments, servers, printers, and other real-world objects in the organization served by the directory. Figure 2.7 shows a portion of a typical directory, with objects corresponding to some of the real-world objects in the organization. Figure 2.7. Part of a Typical Directory
Each directory entry has a distinguished name (DN); for example, the organization shown in Figure 2.7 has the DN dc=example,dc=com . We will discuss DNs in detail later in this chapter when we dive into the LDAP naming model. An entry is composed of a set of attributes , each of which describes one particular trait of the object. Each attribute has a type and one or more values . The type describes the kind of information contained in the attribute, and the value contains the actual data. For example, Figure 2.8 zooms in on an entry describing a person, with attributes for the person's full name, surname (last name), telephone number, and e-mail address. Figure 2.8. A Directory Entry Showing Attribute Types and Values
Note Throughout this book you'll see directory entries shown in the LDIF (LDAP Data Interchange Fromat) text format. This is a standard way of representing directory data in a textual format, and it is used when data is being exported from and imported into a directory server. We'll describe LDIF in detail later in this chapter. Attribute types also have an associated syntax and a set of matching rules . The syntax of an attribute specifies the form of the data that may be present in an attribute of that type. For example, the INTEGER syntax allows only digits to be present in a value. Matching rules specify the following things:
All standards-compliant LDAP server software supports a set of well-known required syntaxes and matching rules; see RFC 2252 (http://www.ietf.org/rfc/rfc2252.txt) for a list. Some packages, such as Netscape Directory Server, provide a plug-in interface or another mechanism that allows additional syntaxes or matching rules to be added. Attributes are also classified broadly into two categories: user and operational. User attributes , the "normal" attributes of an entry, may be modified by the users of the directory (with appropriate permissions). Operational attributes are special attributes that either modify the operation of the directory server or reflect the operational status of the directory. An example of an operational attribute is the modifyTimeStamp attribute, which reflects the time that the entry was last modified and is automatically maintained by the directory. When an entry is sent to a client, operational attributes are not included unless the client requests them by name. Attribute values can also have additional constraints placed on them. Some server software allows the administrator to declare whether a given attribute type may hold multiple values or whether only a single attribute value may be stored. For example, the givenName attribute is typically multivalued so that a person can include more than one given name (for example, Jim and James ). On the other hand, an attribute holding an employee ID number is likely to be single-valued. Some server software allows the administrator to set the maximum length of an attribute's values. This feature can be used to prevent directory users from using unreasonable amounts of storage. Maintaining Order: Directory SchemasAny entry in the directory has a set of required attribute types and a set of allowed attribute types. For example, an entry describing a person is required to have a cn (common name) attribute and an sn (surname) attribute. Other attributes are allowed, but not required, for person entries. Any attribute type not explicitly required or allowed is prohibited . The collections of all information about required and allowed attributes are called the directory schemas . It's important to understand that directory schemas do not have any bearing on the arrangement of entries into the LDAP directory tree. This may seem odd if you are familiar with relational database technology, where schema is a more inclusive term describing the layout of database tables and their relationship to one another. The LDAP schema is a simpler concept, and therefore it determines only what types of data appear in an individual entry. Directory schemas, which are discussed in detail in Chapter 8, Schema Design, allow you to retain control and maintain order over the types of information stored in your directory. In summary, the LDAP information model describes entries , which are the basic building blocks of your directory. Entries are composed of attributes, which are composed of an attribute type and one or more values. Attributes may have constraints that limit the type and length of data placed in attribute values. The directory schemas place restrictions on the attribute types that must be or are allowed to be contained in an entry. The LDAP Naming ModelThe LDAP naming model defines how you organize and refer to your data. In other words, it describes the types of structures you can build out of your individual building blocks, which are the directory entries. After you've arranged your entries into a logical structure, the naming model also tells you how to refer to any particular directory entry within that structure. The flexibility afforded by the LDAP naming model allows you to place your data in the directory in a way that is easy for you to manage. For example, you might choose to create one container to hold all the entries describing people in your organization, and another container to hold all your groups. Alternatively, you might choose to arrange your directory in a way that reflects the geographical placement of your organization's offices. Chapter 9, Namespace Design, guides you in making good choices when you design your directory hierarchy or namespace. The LDAP naming model specifies that entries should be arranged in an inverted tree structure, as shown in Figure 2.9. Readers familiar with the hierarchical file system used by Unix systems will note its similarities to this directory structure. Such a file system consists of a set of directories and files; each directory may have zero or more files or directories beneath it. Figure 2.10 shows part of a typical Unix file system. Figure 2.9. A Directory Tree
Figure 2.10. Part of a Typical Unix File System
There are three significant differences between the Unix file system hierarchy and the LDAP directory hierarchy, however. The first major difference between the two models is that there isn't really a root entry in the LDAP model. A file system, of course, has a root directory, which is the common ancestor of all files or directories in the file system hierarchy. In an LDAP directory hierarchy, on the other hand, the root entry is a special entry that contains configuration information about the directory server. It is not normally used to store information. The second major difference is that in an LDAP directory, every node contains data, and any node can be a container. This means that any LDAP entry may have child nodes underneath it. In contrast, in a file system a given node is either a file or a directory, but not both. In the file system, only directories may have children, and only files may contain data. Another way of thinking of this is that an entry in a directory may be both a file and a directory simultaneously . The directory tree shown in Figure 2.11 illustrates this concept. Notice how the entries dc=example , dc=com , ou=People , and ou=Devices all contain data (attributes) but are also containers with child nodes beneath them. Figure 2.11. Part of a Typical LDAP Directory
The third and final difference between the file system hierarchy and the LDAP hierarchy is how individual nodes in the tree are named. LDAP names are backward relative to file system names. As illustration, consider the names of the shaded nodes in Figures 2.10 and 2.11. In Figure 2.10, the shaded node is a file with a complete filename of /usr/bin/grep . Notice that if you read the filename from left to right, you move from the top of the tree ( / ) down to the specific file being named. Contrast this name with the name of the shaded directory entry in Figure 2.11: uid=bjensen,ou=people,dc=example,dc=com . Notice that, if you read from left to right, you move from the specific entry being named back up toward the top of the tree. We'll discuss directory entry names in detail in Chapter 9, Namespace Design. Although LDAP supports a hierarchical arrangement of directory entries, it does not mandate any particular type of hierarchy. Just as you're free to arrange your file system in a way that makes sense to you and is easy for you to manage, you're free to construct any type of directory hierarchy you want. Of course, some directory structures are better than others, depending on your particular situation; we'll cover the topic of designing your directory namespace in Chapter 9. The one exception to this freedom is if your LDAP directory service is actually a front end to an X.500 service. The X.500 naming model is much more restrictive than the LDAP naming model. In the X.500 1993 standard, directory structure rules limit the types of hierarchies you can create. The standard accomplishes this restriction by specifying what types of "object classes" may be direct children of an entry. In the X.500 model, for example, only entries representing countries , localities, or organizations may be placed at the root of the directory tree. The LDAP naming model, on the other hand, does not limit the tree structure in any way; any type of entry may be placed anywhere in the tree. In addition to specifying how to arrange directory entries into hierarchical structures, the LDAP naming model describes how to refer to individual entries in the directory. We mentioned this briefly when we were discussing the similarities and differences between file system hierarchy and LDAP directory hierarchy. Now let's go into more detail about naming. Why Is Naming Important?A naming model is needed so that you can give a unique name to any entry in the directory, allowing you to refer to any entry unambiguously. In LDAP, distinguished names (DNs) are how you refer to entries. Like file system pathnames, we form the name of an LDAP entry by connecting in a series all the individual names of the parent entries back to the root. For example, look back at the directory tree shown in Figure 2.11. The shaded entry's name is uid=bjensen,ou=people,dc=example,dc=com . Reading this name from left to right, you can trace the path from the entry itself back to the root of the directory tree. The individual components of the name are separated by commas. Spaces after the commas are optional, so the following two distinguished names are equivalent: uid=bjensen, ou=people, dc=example, dc=com uid=bjensen,ou=people,dc=example,dc=com In any entry's DN, the leftmost component is called the relative distinguished name ( RDN ). Among a set of peer entries (those that share a common immediate parent), each RDN must be unique. This rule, when applied recursively to the entire directory tree, ensures that no two entries have the same DN. If you attempt to add two entries with the same name, the directory server will reject the attempt to add the second entry; this is similar to a Unix or Microsoft Windows file system, which will reject an attempt to create a file that has the same name as an existing file within a directory. RDNs have to be unique only if they share a common immediate parent. Look at the tree in Figure 2.12. Even though two entries have the RDN cn=John Smith , they are in different subtrees, so the tree is completely legal. Whether this is a good way to construct your directory is another matter, one addressed in Chapter 9, Namespace Design. Figure 2.12. Entries with the Same RDNs Are Permitted If They Are in Different Parts of the Tree
Multivalued RDNs, and Why You Should Avoid Using ThemYou've probably noticed that each RDN we've shown is composed of two parts: an attribute name and a value, separated by an equal sign ( = ). An RDN may also contain more than one such name “value pair. Such a construction, called a multivalued RDN , looks like this: cn=John Smith + mail=jsmith@example.com The RDN for this entry consists of two attribute=value pairs: cn=John Smith and mail=jsmith@example.com . Multivalued RDNs can be used to distinguish RDNs that would otherwise be the same. For example, if there were more than one John Smith entry in the same container, a multivalued RDN would allow you to assign unique RDNs to each entry. However, you should generally avoid using multivalued RDNs, for two reasons: First, they tend to clutter your namespace, and there are better ways to arrive at unique names for your entries. (Approaches for uniquely naming your entries are discussed in Chapter 9, Namespace Design.) Second, according to X.500 specifications, from which LDAP is derived, the values in a multivalued RDN are a set, which means that the ordering is not significant. Therefore, the following two DNs refer to the same entry: cn=John Smith + mail=jsmith@example.com, dc=example, dc=com mail=jsmith@example.com + cn=John Smith, dc=example, dc=com Client applications that need to compare DNs must be sophisticated enough to understand that these two DNs are equivalent. Realistically, few applications handle this correctly. Also, many off-the-shelf directory applications do not allow you to create entries with multivalued RDNs, nor do they properly handle any such entries that may exist in your directory. Our advice is to avoid using multivalued RDNs in your directory. EscapingCertain characters must be escaped when they appear within a component of a DN. For example, what if you have the entry o=United Widgets,Ltd. in your directory? The comma is part of the organization's name, not a separator between DN components. To resolve the ambiguity, you must escape all literal commas (those within an RDN) with a backslash ( \ ). In our example, then, the DN would be Table 2.1. Characters That Must Be Escaped If Contained in Distinguished Names
o=United Widgets\, Ltd., c=GB Table 2.1 shows all the characters that must be escaped, according to the LDAPv3 specification. AliasesAlias entries in the LDAP directory allow one entry to point to another one, which means that you can devise structures that are not strictly hierarchical. Alias entries perform a function like symbolic links in the Unix file system or shortcuts in the Windows 95/NT file system. In Figure 2.13, the dotted entry is an alias entry pointing to the real entry. Figure 2.13. An Alias Entry Points to Another Directory Entry
To create an alias entry in the directory, you must first create an entry with the object class alias and an attribute named aliasedObjectName . The value of the aliasedObjectName attribute must be the DN of the entry you want this alias to point to. In general, we recommend that you avoid the use of aliases. Because aliases can point to any directory entry, even one that is on a different server, aliases may exact a severe performance penalty. Consider the directory trees shown in Figure 2.13. Alias entries in one of the trees point to entries in the other tree, which is housed in another server. To support searching across the entire dc=example,dc=com tree, Server A must contact Server B each time an alias entry is encountered while the search operation is being serviced. This requirement can significantly slow down searches. In addition, when an entry is deleted on one server, it might still be referred to by an alias on another server. The result can be a dangling reference, which must be cleaned up somehow. Instead of using aliases, use referrals or LDAP URLs in entries to point to the information you need to reference. More information on using referrals can be found in Chapter 10, Topology Design. The LDAP Functional ModelNow that you understand the LDAP information and naming models, you need some way to access the data stored in the directory tree. The LDAP functional model describes the operations that you can perform on the directory using the LDAP protocol. The LDAP functional model consists of a set of operations divided into three groups. The interrogation operations allow you to search the directory and retrieve directory data. The update operations allow you to add, delete, rename, and change directory entries. The authentication and control operations allow clients to identify themselves to the directory and control certain aspects of a session. In addition to these three main groups of operations, version 3 of the LDAP protocol defines a framework for adding new operations to the protocol via LDAP extended operations . Extended operations allow the protocol to be extended in an orderly fashion to meet new marketplace needs as they emerge. Extended operations were described earlier, in the section titled LDAP Extensibility. The LDAP Interrogation OperationsThe two LDAP interrogation operations allow LDAP clients to search the directory and retrieve directory data. The search operation allows a client to find entries in the directory, and the compare operation allows a client to test whether an entry contains a particular attribute value. The LDAP Search OperationThe LDAP search operation is used to search the directory for entries and retrieve individual directory entries. There is no LDAP read operation. When you want to read a particular entry, you must use a form of the search operation in which you restrict your search to just the entry you want to retrieve. Later in the chapter we'll discuss how to search the directory and retrieve specific entries, as well as how to list all the entries at a particular location in the tree. The LDAP search operation requires eight parameters:
Base ObjectThe first parameter is the base entry for the search (the terms entry and object are used interchangeably). This parameter, expressed as a DN, indicates the top of the tree you want to search. Search ScopeThe second parameter is the scope. There are three types of scope. A scope of sub (subtree) indicates that you want to search the entire subtree from the base object all the way down to the leaves of the tree. A scope of onelevel indicates that you want to search only the immediate children of the entry at the top of the search base. A scope of base indicates that you want to limit your search to just the base object; this scope is used to retrieve one particular entry from the directory. Figure 2.14 depicts the three search scope types. The base object and the search scope together define the area of the directory tree you want to search. Figure 2.14. The Three Types of Search Scope
Alias Dereferencing OptionsThe third search parameter, derefAliases , tells the server whether aliases should be dereferenced when it is performing the search. This parameter has four possible values:
Size LimitThe fourth search parameter is the size limit. This parameter tells the server that the client is interested in receiving only a certain number of entries. For example, if the client passes a size limit of 100, but the server locates 500 matching entries, only the first 100 will be returned to the client, along with a result code of LDAP_SIZELIMIT_ EXCEEDED . A size limit of 0 means that the client wants to receive all matching entries. (Note that servers may impose a maximum size limit that cannot be overridden by unprivileged clients.) Time LimitThe fifth search parameter is the time limit. This parameter tells the server the maximum time in seconds that it should spend trying to honor a search request. If the time limit is exceeded, the server will stop processing the request and send a result code of LDAP_TIMELIMIT_EXCEEDED to the client. A time limit of 0 indicates that no limit should be in effect. (Note that servers may impose a maximum time limit that cannot be overridden by unprivileged clients.) Attributes-Only ParameterThe sixth search parameter, attrsOnly , is a Boolean parameter. If it is set to true , the server will send only the attribute types to the client; attribute values will not be sent. This parameter can be used if the client is interested in finding out which attributes are contained in an entry but not in receiving the actual values. If this parameter is set to false , attribute types and values will be returned. Search FilterThe seventh search parameter is the search filter, an expression that describes the types of entries to be returned. The filter expressions used in LDAP search operations are flexible; they are discussed in detail in the next section, The LDAP Search Filters.
List of Attributes to ReturnThe eighth and final search parameter is a list of attributes to be returned for each matching entry. If this list is empty, all user attributes are returned. The special value * also means that all user attributes are to be returned, but it allows you to specify additional nonuser (operational) attributes that should be returned. (Without this special value, there would be no way to request all user attributes plus some operational attributes.) Occasionally, you will want to verify that an entry exists but you won't be interested in retrieving any of the attributes. If you want to retrieve no attributes at all, you should specify the attribute name 1.1 . Table 2.2 provides some examples of attribute lists and the corresponding attributes returned by the server. Note Readers familiar with the ldapsearch command-line utility will note that it's not necessary to supply all the search parameters just discussed. The reason is that the ldapsearch utility provides default values for all options except the base object and the search filter. Table 2.2. Examples of Attribute Lists and Corresponding Attributes Returned by the Server
The LDAP Search FiltersAn LDAP filter is a Boolean combination of attribute “value assertions. An attribute “value assertion consists of two parts: an attribute name and a value assertion, which you can think of as a value with wildcards allowed. The following sections look at the various types of search filters. We use the RFC 2254 notation for LDAP search filters, which is convenient because the filters are encoded as text strings (within the LDAP protocol itself, the filters are encoded with BER, as discussed earlier). This notation is also what you use when using the ldapsearch command-line utility, which will be discussed later in this chapter. Equality FiltersAn equality filter allows you to look for entries that exactly match a particular value. Here's an example: (sn=smith) This filter matches entries in which the sn (surname) attribute contains a value that is exactly smith . Because the equality matching rule associated with the sn attribute is caseIgnoreMatch , the case of the attribute and the filter is not important when matching entries are being located. Substring FiltersWhen you use wildcards in filters, they are called substring filters . For example, the filter (sn=smith*) matches any entry that has an sn attribute value that begins with "smith". Entries with a surname of Smith , Smithers , Smithsonian , and so on will be returned. Wildcards may appear anywhere in the filter expression, so the filter (sn=*smith) matches entries in which the surname ends with "smith" (for example, Blacksmith ). The filter (sn=smi*th) matches entries in which the surname begins with "smi" and ends with "th", and the filter (sn=*smith*) matches entries that contain the string "smith" in the surname attribute. Note that the wildcard character matches zero or more instances of any character, so the filter ( sn=*smith* ) would match the entry with the surname Smith as well as any surnames in which the string "smith" was embedded. Approximate FiltersIn addition to the equality and substring filters, servers support an approximate filter . For example, on most directory servers, the filter (sn~=jensen) returns entries in which the surname attribute has a value that sounds like "jensen" (for example, jenson ). Exactly how the server implements this filter is particular to each vendor and the languages supported by the server. Netscape Directory Server, for example, uses the metaphone algorithm to locate entries when an approximate filter is used. Internationalization also throws an interesting wrinkle into the concept of approximate matching; each language may need its own particular sounds ”like algorithms. For example, algorithms used to implement approximate matching for English are different from those for Japanese. It's likely that your directory software supports approximate matching for English but not for other languages. "Greater Than or Equal To" and "Less Than or Equal To" FiltersLDAP servers also support "greater than or equal to" and "less than or equal to" filters on attributes that have some inherent ordering. For example, the filter (sn<=Smith) returns all entries in which the surname is less than or equal to Smith lexicographically. The ordering used depends on the matching rules associated with a particular attribute. The sn attribute, which is defined with the caseIgnoreOrderingMatch matching rule, is ordered lexicographically without respect to case. An attribute that has INTEGER syntax would be defined with a matching rule that would order values numerically . Attributes that have no inherent ordering, such as JPEG photos, cannot be searched for with this type of filter. If you find that you need a greater-than or less-than filter (without the equals part), note that "greater than" is the complement of "less than or equal to" and "less than" is the complement of "greater than or equal to." In other words, (age>21) is equivalent to (!(age<=21)) . Similarly, the filter (age<21) , which is also not a valid LDAP filter, is equivalent to (!(age>=21)) . In these cases, ! is the negation operator, which we will discuss in more detail shortly. Presence FiltersAnother type of search filter is the presence filter . It matches any entry that has at least one value for the attribute. For example, the filter (telephoneNumber=*) matches all entries that have a telephone number. Extensible MatchingThe last type of search filter is the extensible match filter . It is supported only by LDAPv3 servers. The purpose of an extensible match filter is to allow new matching rules to be implemented in servers and used by clients. Recall our earlier example involving the caseIgnoreMatch rule. Each matching rule has an associated method for comparing values, depending on whether case is to be considered significant when values are being compared. When new attribute types are defined, it may also be necessary to define a new way of comparing values. Extensible matching also allows language-specific matching rules to be defined so that values in languages other than English can be meaningfully compared. As an added benefit, extensible matching allows you to specify that the attributes that make up the DN of the entry should be searched. For example, using extensible matching you can locate all the entries in the directory that contain the attribute value assertion ou=Engineering anywhere in their DN. Without extensible matching, it's not possible to search on the individual components of the DN. The syntax of an extensible matching filter is a bit complicated. It consists of five parts, three of which are optional:
Formally, the grammar for the extensible search filter is attr [":dn"] [":" matchingrule ] ":=" value where
Although LDAP largely does away with the mandatory use of OIDs, you will see them from time to time, especially if you use extensible matching rules or if you design your own schema extensions. The topic of extending your directory schema is discussed in Chapter 8, Schema Design. Let's look at some examples of extensible matching filters:
NegationAny search element can be negated if the filter is preceded with an exclamation point ( ! ). For example, the filter (!(sn=Smith)) matches all entries in which the sn attribute does not contain the value smith , including entries with no sn attribute at all. Combining Filter TermsFilters can also be combined by AND and OR operators. The AND operator is signified by an ampersand ( & ), and the OR operator is signified by the vertical bar ( ). When combining search filters, you use prefix notation , in which the operator precedes its arguments. Those familiar with the "reverse polish notation" common on Hewlett-Packard calculators will be familiar with this concept (although reverse polish is a postfix notation, not a prefix notation like that used in LDAP search filters). Let's look at some examples of combinations of LDAP search filters. The filter (&(sn=Smith) (L=Mountain View)) matches all entries with a surname of smith that also have an L (locality) attribute of Mountain View . In other words, this filter finds everyone named Smith in the Mountain View location. The filter ((sn=Smith) (sn=Jones)) matches everyone with a surname of Smith or Jones . You use parentheses to group more complex filters to make the meaning of the filter unambiguous. For example, if you want to search the directory for all entries that have an e-mail address but do not have a telephone number, you use the following filter: (&(mail=*)(!(telephoneNumber=*))) Note that the parentheses bind the negation operator to the presence filter for telephone number. Technically speaking, parentheses are always required, even if the filter consists of only a single term. Some LDAP software allows you to omit the enclosing parentheses and inserts them for you before sending the search request to the server. However, if you are developing your own software using one of the available SDKs, you need to include the enclosing parentheses. Table 2.3 summarizes the six types of search filters and the three Boolean operators. Escaping in Search FiltersIf you need to search for an attribute value that contains one of five specific characters, you need to substitute the character with an escape sequence consisting of a backslash and a two-digit hexadecimal sequence representing the character's value. Table 2.4 shows the characters that must be escaped, along with the escape sequence you should use for each. For example, to search for all entries in which the cn attribute exactly matches the value A*Star , you use the filter (cn=A\2AStar) . Note that the rules for escaping search filters and the rules for escaping distinguished names are different and not interchangeable. Table 2.3. Types of LDAP Search Filters
Table 2.4. Characters That Must Be Escaped If Used in a Search Filter
Common Types of SearchesAlthough the LDAP search operation is flexible, some types of searches you'll use more frequently than others:
Hiding LDAP Filters from UsersYou might justifiably be thinking that your users will never be able to understand LDAP filter syntax. The prefix notation it uses is hardly intuitive, after all! Bear in mind, though, that any good directory access GUI hides the details of filter construction from end users. Instead of requiring users to type raw LDAP filters, a set of pop-up menus and text boxes is typically used to allow the user to specify the search criteria, and the GUI client constructs the filter for the user. In Figure 2.15, for example, Netscape Communicator's Search window uses the provided information to construct the filter (&(cn=*Smith*) (L=*Dearborn*)) . Figure 2.15. A GUI Interface for Searching the Directory
If you are a directory administrator, it's a good idea to become familiar with LDAP filter syntax. You can use this knowledge to provide complex "canned" queries for your end users, for example. Filter syntax also crops up in LDAP URLs and configuration files. Spending a little time understanding filter syntax is well worth the effort. The Compare OperationThe second of the two interrogation operations, the LDAP compare operation, is used to check whether a particular entry contains a particular attribute value. The client submits a compare request to the server, supplying a DN, an attribute name, and a value. The server returns an affirmative response to the client if the entry named by the DN contains the given value in the given attribute type. If not, a negative response is returned. It may seem odd that the compare operation even exists. After all, if you want to determine whether a particular entry contains a particular attribute value, you can just perform a search with a search base equal to the DN of the entry, a scope of base , and a filter expressing the test you want to conduct. If the entry is returned, the test was successful; if no entry is returned, the test was not successful. The reasons that the compare operation exists are mainly historical and related to LDAP's roots in X.500. In only one case do the compare and search operations behave differently. If a comparison is attempted on an attribute but the attribute is not present in the entry, the compare operation returns a special indication to the client that the attribute does not exist. The search operation, on the other hand, simply does not return the entry in such cases. This capability to distinguish between "the entry has the attribute but contains no matching value" and "the entry does not have the attribute at all" may be convenient in some situations. The other advantage of the compare operation is that it is more compact in terms of the number of protocol bytes exchanged between the client and the server. The LDAP Update OperationsLDAP has four update operations: add, delete, rename (modify DN), and modify. These four operations define the ways that you can manipulate the data in your directory. The Add OperationThe add operation allows you to create new directory entries. It has two parameters: the distinguished name of the entry to be created, and a set of attributes and attribute values that will constitute the new entry. For the add operation to complete successfully, four conditions must be met:
If all these conditions are met, the new entry is added to the directory. The Delete OperationThe delete operation removes an entry from the directory. It has a single parameter: the DN of the entry to be deleted. For the delete operation to complete successfully, three conditions must be met:
If all these conditions are met, the entry is removed from the directory. The Rename (Modify DN) OperationThe rename, or modify DN, operation is used to rename and/or move entries in the directory. It has four parameters: the DN of the entry to be renamed , the new RDN for the entry, an optional argument giving the new parent of the entry, and the delete-old-RDN flag. For the modify DN operation to succeed, the following conditions must be met:
If all these conditions are met, the entry is renamed and/or moved. If the entry is to be renamed but will still have the same parent entry, the new-parent argument is left blank. Otherwise, the new-parent argument gives the DN of the container where the entry is to be moved. The delete-old-RDN flag is a Boolean flag that specifies whether the old RDN of the entry is to be retained as an attribute of the entry or removed. Figures 2.16 through 2.20 show the various combinations of renaming and moving entries that can be performed with the modify DN operation. Figure 2.16. Renaming an Entry without Moving It
Figure 2.20. Renaming an Entry, deleteoldrdn=false
LDAPv2 did not have a modify DN operation; it had only a modify RDN operation. As the name implies, modify RDN allows only the RDN of an entry to be changed. This means that an LDAPv2 server may rename an entry but may not move it to a new location in the tree. To accomplish a move with LDAPv2, you must copy the entry, along with any child entries underneath it, to the new location in the tree and delete the original entry or entries. Figure 2.17. Moving an Entry without Changing Its RDN
Figure 2.18. Moving an Entry and Changing Its RDN Simultaneously
The Modify OperationThe modify operation allows you to update an existing directory entry. It takes two parameters: the DN of the entry to be modified and a set of modifications to be applied. These modifications can specify that new attribute values are to be added to the entry, that specific attribute values are to be deleted from the entry, or that all attribute values for a given attribute are to be replaced with a new set of attribute values. The modify request can include as many attribute modifications as needed. For the modify operation to succeed, the following conditions must be met:
If all these conditions are met, the entry is modified. Note that all the modifications must succeed, or else the entire operation fails and the entry is not modified. This requirement prevents inconsistencies that might arise from half-completed modify operations. This last point raises one additional but important topic about the LDAP update operations: Each operation is atomic , meaning that the whole operation is processed as a single unit of work. Either this unit completely succeeds, or no modifications are performed. For example, a modify request that affects multiple attributes within an entry cannot half-succeed, with certain attributes updated and others not updated. If the client receives a success result from the server, then all the modifications were applied to the entry. If the server returns an error to the client, then none of the modifications were applied. The LDAP Authentication and Control OperationsLDAP has two authentication operations (bind and unbind) and one control operation (abandon). The Bind OperationBy providing a DN and a set of credentials, a client can use the bind operation to authenticate itself to the directory. The server checks whether the credentials are correct for the given DN and, if they are, notes that the client is authenticated as long as the connection remains open or until the client reauthenticates. The server can grant privileges to the client on the basis of its identity. There are several different types of bind methods . In a simple bind, the client presents a DN and a password in cleartext to the LDAP server. The server verifies that the password matches the password value stored in the userPassword attribute of the entry and, if so, returns a success code to the client. The simple bind does send the password over the network to the server in the clear. However, you can protect against eavesdroppers intercepting passwords by encrypting the connections using Secure Sockets Layer (SSL) or TLS, which are discussed in the next section, The LDAP Security Model. LDAPv3 also includes a new type of bind operation: the SASL bind. SASL is an extensible, protocol-independent framework for performing authentication and negotiation of security parameters. With SASL, the client specifies the type of authentication protocol it wants to use. If the server supports the authentication protocol, the client and server perform the agreed-on protocol. For example, the client could specify that it wants to authenticate using the DIGEST-MD5 SASL mechanism. If the server implements DIGEST-MD5 (all LDAPv3-compliant servers must), it constructs a challenge and sends it to the client. The client computes the response to the challenge and sends the response to the server, which verifies the response and returns a final result to the client. DIGEST-MD5 authentication, if properly implemented, is immune to eavesdroppers. Incorporation of SASL into LDAPv3 means that new authentication methods, such as smart cards or biometric authentication, can be easily implemented for LDAP without the protocol having to be revised. It's perfectly legal for a client to bind, perform some operations, bind again, and perform more operations. If it does, all operations performed after the client rebinds are performed with the new bind identity. In the event that a bind operation fails, the client is treated as if it has bound anonymously. We discuss anonymous binds shortly, in the section titled The LDAP Security Model. Note In the Active Directory Services Interface (ADSI) SDK, the meaning of the word bind is slightly different. When you bind to a directory entry using ADSI, you not only authenticate to the directory; you also set the base object for subsequent directory searches. The Unbind OperationThe second authentication operation is the unbind operation. The unbind operation has no parameters. When a client issues an unbind operation, the server discards any authentication information it has associated with the client's connection, terminates any outstanding LDAP operations, and disconnects from the client, thus closing the TCP connection. Although it's considered good practice for a client to issue an unbind operation before disconnecting, server implementations must behave properly if the client disconnects without unbinding. The Abandon OperationThe abandon operation has a single parameter: the message ID of the LDAP operation to abandon. The client issues an abandon operation when it is no longer interested in obtaining the results of a previously initiated operation. Upon receiving an abandon request, the server terminates processing of the operation that corresponds to the message ID. The abandon request, typically used by GUI clients, is sent when the user cancels a long-running search request. Note that it's possible for the abandon request (coming from the client) and the results of the abandoned operation (going to the client) to pass each other in flight. The client needs to be prepared to receive (and discard) results from operations that it has abandoned but that the server sent anyway. If you are using an LDAP SDK, however, you don't need to worry about this; the SDK takes care of this housekeeping for you. The LDAP Security ModelWe've discussed three of the four LDAP models so far. We have a set of directory entries, which are arranged into a hierarchy, and a set of protocol operations that allow us to authenticate to, search, and update the directory. All that remains is to provide a framework for protecting the information in the directory from unauthorized access. This is the purpose of the LDAP security model. The security model relies on the fact that LDAP is a connection-oriented protocol. In other words, an LDAP client opens a connection to an LDAP server and performs various protocol operations on the same connection. The LDAP client may authenticate to the directory server at some point during the lifetime of the connection, at which point it may be granted additional (or fewer) privileges. For example, a client might authenticate as a particular identity that has been granted read/write access to all the entries in the directory. Before this authentication, it has a limited set of privileges (usually a default set of privileges extended to all users of the directory). After it authenticates, however, it is granted expanded privileges as long as the connection remains open. What exactly is authentication ? From the client's perspective, it is the process of proving to the server that the client is a particular entity. In other words, the client asserts that it has a certain identity and provides some credentials to prove this assertion. From the server's perspective, the process of authentication involves accepting the identity and credentials provided by the client and checking whether they prove that the client is who it claims to be. To illustrate this abstract concept with a concrete example, let's examine how LDAP simple authentication works. In simple authentication , an LDAP client provides to an LDAP server a DN and a password, which are sent to the server in the clear (not hashed or encrypted in any way). The server locates the entry in the directory corresponding to the DN provided by the client and checks whether the password presented by the client matches the value stored in the userPassword attribute of the entry. If it does, the client is authenticated; if it does not, the authentication operation fails and an error code is returned to the client. Note In Netscape Directory Server, a hashed version of the password can be stored instead of the cleartext password. The hash is computed with one of several cryptographic one-way hash algorithms. When servicing a simple bind operation, the server takes the cleartext password provided by the client in the bind operation, hashes it, and compares it to the hashed password stored in the database. If the hashes match, the bind operation succeeds. Because the hash operation is one-way, it is difficult to determine the password if given only the hash. Storing passwords in hashed form improves the security of your directory somewhat. The process of authenticating to the directory is called binding . An identity is bound to the connection when the bind operation achieves a successful authentication. If a client does not authenticate, or if it authenticates without providing any credentials, the client is bound anonymously. In other words, the server has no idea who the client is, so it grants a default set of privileges to the client. Usually this default set of privileges is minimal. In some instances, the default set of privileges is completely restrictive: No part of the directory may be read or searched. How you treat anonymously bound clients is up to the directory administrator and depends on the security policy appropriate to your organization. You can find more information on security and privacy in Chapter 12, Privacy and Security Design. Many different types of authentication systems are independent of LDAP. LDAPv2 supported only simple authentication, in which a DN and password are transmitted in the clear from the client to the server. Note The statement that LDAPv2 supported only simple authentication is not completely correct because LDAPv2 also supported Kerberos version 4 authentication, which does not require that passwords be sent in the clear. However, Kerberos v4 was not commercially successful and was superseded by Kerberos version 5. Kerberos support was therefore dropped from the core LDAPv3 protocol, although it's entirely feasible to support it via a SASL mechanism. Acknowledging the need to support many different authentication methods, LDAPv3 has adopted the SASL framework. SASL provides a standard way for multiple authentication protocols to be supported by LDAPv3. Each type of authentication system corresponds to a particular SASL mechanism. A SASL mechanism is an identifier that describes the type of authentication protocol being supported. After the server verifies the identity of the client, it can choose to grant additional privileges on the basis of a site-specific policy. For example, you might have a policy that, when authenticated, enables users to search the directory but does not enable them to modify their own directory entries. Or you might have a more permissive policy that allows some authenticated users to modify certain attributes of their own entries, whereas other users (your administrative staff) may modify any attribute of any entry. The way you describe the access rights, the entities to which those rights are granted, and the directory entries to which those rights apply are collectively called access control . LDAPv3 Authentication MethodsDuring work on LDAPv3, it became clear that it was necessary to define the minimum set of authentication methods that must be supported by LDAPv3 servers. Without such a definition, a client from one vendor and a server from another vendor might not have any authentication methods in common other than simple authentication. Recall that LDAP simple authentication sends passwords in the clear over the network, with no encryption. Allowing such a situation to exist would severely limit LDAP's adoption. To address this problem, the LDAP Working Group defined authentication methods whose implementation was mandatory in RFC 2829, Authentication Methods for LDAP . In this document, LDAP servers are broken down into three distinct groups, with separate requirements for each:
Of course, any server can use a more secure authentication method than is strictly required. For example, servers that support password-based authentication may also support StartTLS. The intent of RFC 2829 is to ensure that any LDAPv3-compliant client can authenticate to any LDAPv3-compliant server in a secure fashion, without sending passwords in the clear. Access Control ModelsIt may come as somewhat of a disappointment to learn that LDAP does not currently define a standard access control model. However, this does not mean that individual LDAP server implementations have no access control model. In fact, any commercially successful server software must have such a model. Netscape Directory Server, for example, has a rich access control model. The model works by describing what a given identity can do to a particular set of entries, with granularity down to the attribute level. For example, with the Netscape server it is possible to specify an access control instruction (ACI) that allows a person to modify only the description attribute of his or her own entry. Or the model can allow you to grant complete rights to the directory to all persons in a particular group. This approach allows easy creation of a set of directory administrators; a given person's rights can be easily revoked by removal of the person from the group. The model is fully documented in the Netscape Directory Server Administrator's Guide . The IETF continues to work on defining a standard access control model and a standard syntax for representing access control rights. The promise for the future is that you, as a directory deployer, will be able to deploy directory servers from several vendors and implement a consistent security policy across those servers ”whether they cooperate to serve a distributed directory or are replicas of each other. Unfortunately, that is not the case today. You would be wise to document your access control policy in plain language so that you can adapt it to whatever model and syntax emerge from the standards bodies in the future. Transport Layer Security (TLS)TLS is a security technology that supports privacy, data integrity, and encryption for connection-oriented protocols like TCP. Clients that use TLS to communicate with a server
SSL has been a successful technology for the World Wide Web, securing electronic commerce and other transactions that depend on transmission of data being hidden from eavesdroppers. TLS, the follow-up to SSL, is an emerging Internet standard. LDAP offers a standard way for clients to begin encrypting all data flowing to and from LDAP on the connection using TLS. Just as SSL and TLS enabled a new class of applications on the Web, they will enable new uses of directory technology. For example, two companies in a trading-partner relationship can allow directory queries from their trading partners to travel over the Internet. Because TLS encrypts these queries and the results, each company can rest assured that the directory data is protected while in transit over the Internet. Figure 2.21 depicts this scenario. Figure 2.21. TLS Allows Secure Transmission of Directory Data over the Internet
Readers familiar with existing directory server implementations, such as Netscape Directory Server, will point out that there already is a way to use SSL with LDAP. Many server implementations support the use of LDAP-over-SSL, known as LDAPS. Servers that implement LDAPS must provide this service on a TCP port distinct from the normal LDAP service. Typically, a server listens on port 389 for LDAP connections and port 636 for LDAPS connections. By contrast, TLS allows a client to begin a connection without encryption, and to negotiate encryption and authentication after the connection is established. This means that an LDAP server supporting TLS can support both types of clients (secure and nonsecure) on the same TCP port. The StartTLS extended operation, defined in RFC 2830, Lightweight Directory Access Protocol (v3): Extension for Transport Layer Security , is the means by which an LDAP client indicates to an LDAP server that TLS should be used on an existing LDAP connection. After an LDAP client initiates TLS, it can bind through use of the the SASL EXTERNAL mechanism. The server typically maps the certificate provided by the client to a directory entry using an implementation-specific method (for example, Netscape Directory Server maps certificates to entries using a method configurable via the certmap . conf configuration file). An LDAP client usually goes through the following steps to establish a secure, authenticated connection to a directory server:
After TLS has been established and a bind operation performed, the client has a secure, authenticated connection to the directory. |