Chapter 2

LDAP Basics

This chapter is a guided tour through a mini-application using LDAP. It is intended to give you a basic impression of what you can do with LDAP. Experience has shown that the best way to understand a new tool is simply to use and play around with it. That is what we will do in this chapter. As mentioned previously, we will use OpenLDAP for the examples. OpenLDAP is available for UNIX and Win32 platforms. Because LDAP is an open standard, users of Netscape or other nonstandard products are not excluded from trying out the examples presented in this book. Note that the exact syntax might be different between the various implementations. The syntax of the command-line tools in Netscape is almost identical. In any case, take a look at the documentation delivered with whatever product you are using.

First, we learn about the data structures that we will be using throughout the rest of this chapter. This example is far from complete. Indeed, it is not really an example of directory design. Rather, the example is intended to give the reader a feeling of how to use a directory server. It shows you a basic configuration so that you can begin working with LDAP. Next, we install a few entries by hand using the command-line tools. Once these entries are installed, we will try to make the usual operations on data in a repository: We will search for the entries we stored in the directory; we will update the data; and then we will delete some entries. Then we will learn how to insert bulk data, and at the end we will use the import/export utilities. We will also learn about the LDIF (LDAP data interchange format) file format, which is the format that LDAP uses to import and export files. Finally, we will learn to use the URL form of an LDAP query to find entries in the directory. This form was briefly introduced in Chapter 1. In this chapter, you can see it at work and play around with it.

This chapter provides only a rough overview of what you can do with LDAP and does not get into the details. This will be done in later chapters, mostly in Chapter 6 (LDAP APIs) but also in Chapter 4, where we will see some of the details of LDAP, and in Chapter 7, where we will see how the World Wide Web and LDAP can be used together.

Example: An Enterprise with a Few Departments

First of all, let us look at the problem at hand. We will use a classic example to illustrate an LDAP application: a directory of employees. Note that this is a widely used LDAP application, but it is not the only one. We will see other applications later in this book.

Let us assume that we have an enterprise named ldap_abc. To simplify, let this enterprise work in only one country. The enterprise ldap_abc has a number of departments, and a certain number of people work in each department. Our goal is to find the phone number of a certain employee, knowing surname and given name. For now, we will not concentrate much on the overall design. This aspect will be treated in Chapter 9. This chapter is only intended to give a quick overview of what you can do with LDAP. Nor will we care about performance or more sophisticated queries, such as finding a Mr. Smith working in Australia whose given name begins with A and who does not have a fax. Be patient, we will address these and other arguments later.

The first job on our to-do list is to reproduce the hierarchical structure of our enterprise in the tree structure in LDAP. The root of this treelike data structure defines the “namespace” within which we will work. Now you may well ask, “What is our tree made of?” The answer is that the tree is made of objects. Exhibit 1 shows a small part of the tree.

Looking at Exhibit 1, you may wonder what o= ldap_abc.de and the other abbreviations mean. We will discuss this in Chapter 3 when we look at the theory behind LDAP. For now it is enough to know that o stands for organization, ou for organizational unit and cn for common name, i.e., surname. All these abbreviations must be declared in the schema defining the data structures the directory can hold.

Now let us have a look at the individual objects: The root of the tree is the enterprise itself, ldap_abc. The root branches out into individual departments. To simplify the discussion, we will limit ourselves to four: Marketing, Sales, Research, and IT. Note that every department is one object, as is the root element. What is missing now are the employees. Every employee is an object under the corresponding department.

Image

Exhibit 1. Example Directory Tree

In developing our design, we learned that the LDAP database is organized in a tree structure of objects. This tree spans the namespace we are moving in. Now that we have completed our design, we can proceed to implement the single objects.

Objects in LDAP: Object Classes, Attributes, and Schema

Before you can enter any objects into a directory, you must first define what kind of objects the directory will accept. This is much like the design of an object-oriented database. We begin the process by declaring the object classes the directory should accept. In our example we will have an object class called “organization” corresponding to the whole enterprise, a number of objects called “organizational unit,” and objects of the object class “person.” (Forgive me for calling a person an object, but let us agree to accept this point of view in the context of this discussion.)

You do not have to invent these object classes by yourself. There are a number of predefined standard object classes from which you can choose. The names of these object classes are standardized too, most of them being derived from the original X.500 protocol. You will learn more about this in Chapter 3, which discusses the models standing behind LDAP.

The directory will also contain a number of entries, with each of the entries corresponding to an object in the real world. Each class is characterized by a number of “attributes.” For example, a person has a name, surname, phone number, and so on. The attributes are made up of an attribute name and one or more attribute values. The attribute names, like the class names, are standard, most of them being inherited from the X.500 protocol.

To refer unambiguously to an object, a special attribute called a “distinguished name” is used. There are no particular rules of how to build this distinguished name; the only important thing is that this name be unique within the namespace. Chapter 3 discusses the distinguished name in detail.

To define the data structures for the directory, you must first define a schema. A schema comprises object classes accepted by the implementation and governs how these object classes should interact. Chapter 3 discusses this issue in greater depth. For now, it is sufficient to know that the directory server has a number of schema files that contain the description of the object classes the directory can contain. This description is nothing but a list of attributes the entries can contain, together with a specification of the type and properties of these attributes. The schema also contains a specification for making comparisons between the values of these attributes. For example, the name or surname is not case sensitive, so if you are searching for King, KING, or king, you will find the entry. Similarly, consider the attribute “telephone number.” There are several ways to write a phone number. The directory should ensure that you find the number:

0-100-203-440

even if you typed in:

0 100 203 440

This behavior is important not only for queries, but also for the ordering of values. Again, we will learn more about this in Chapter 3.

Every LDAP implementation is shipped with ready-to-use schema files. Both object classes and attributes are fixed in standards distributed in the form of requests for comments (RFCs), but you can extend these standards to fit your particular requirements. That is enough theory for now. Let us move on to the praxis.

Server Configuration

The first thing you have to do is configure your directory server. You do this by setting up the root of your directory tree and then including the schemas you are going to use.

The root of our directory tree is “o = ldap_abc.de,” where “o” stands for “organization.” Chapter 3 provides more details about selecting the directory root. Most commercial products have only a few predefined schemas. They also have a graphical user interface to browse through the object classes and attributes that are known by the directory server. The vendor documentation provides specific details. The OpenLDAP software that we are using has one simple configuration file where you can set up the root DN and select the schema files you wish to use.

Next, you will need to set up the distinguished name (DN) and the password of the LDAP administrator. For our example, we will choose:

DN: uid=Administrator, o=ldap_abc.de

Password: passl

Using the i-planet directory server, you have to set up DN and password, the administrator password, and the server’s port number during software installation. Other commercial products behave similarly.

As mentioned previously, when using OpenLDAP, you have to include the schema files you are going to use. For this example, you need the object class “inetOrgPerson,” so make sure you include the schema file where the inetOrgPerson class is defined. To complete the examples that follow, you must include the following schemas:

■  core.schema for the basic classes and attributes

■  cosine.schema for some useful extensions as defined by RFC 1274, such as userlD, mail, etc.

■  inetorgperson.schema for some further extensions needed for additional attributes as specified in RFC 2798

First Steps with LDAP

Now that the server is set up correctly and running, we are ready to take our first steps in the land of LDAP. LDAP organizes the information it holds in a treelike namespace called a “directory information tree” (DIT). In our case, the root of the tree is the enterprise called ldap_abc. The command to add an entry with the command-line tool is:

ldapmodify –a

Exhibit 2 illustrates the command you have to use. From this command we can note other useful things.

The first line of the actual data begins with

dn: o=ldap_abc.de

where dn means distinguished name. The distinguished name is just a key to access this particular entry. Therefore, it must be unique across the whole directory, as explained previously.

The following lines also appear in Exhibit 2:

objectclass: top

objectclass: organization

Note that ldap_abc.de is an object of the class “organization,” and “organization” is a subclass of “top.” Both top and organization are declared in the configuration files. If you look at the configuration files of your LDAP implementation, you will see that the only element that top requires is the attribute “objectClass.” So the function of the object class “top” is also to ensure that all object classes will have the objectClass property.

Exhibit 2 Adding the “organization” Entry with Idapmodify

Idapmodify –a –D “uid=admin, o=ldap_abc.de” –w passl

dn: o=ldap_abc.de

objectclass: top

objectclass: organization

o: ldap_abc.de

1: Munich

adding new entry “o=ldap_abc.de”

The organization ldap_abc.de has two other properties: “o” (organization) and “l" (location), both of them defined in the schema. As noted previously, these are historical names derived from the original X.500 protocol. Reading your configuration files, you will note that some properties are required, and others are optional. A number of attributes can also be multivalued. Chapter 3 will address these issues.

The last line:

adding new entry “o=ldap_abc.de”

is the output the command line echoes to confirm that the command has been executed successfully. Otherwise, you will get an error message. If you get

ldap_bind: Invalid credentials (49)

you mistyped DN or password.

Be sure to enclose the distinguished name in quotation marks. Otherwise, the shell will interpret the command incorrectly, and the command-line utility will complain about the syntax. If you hit the “enter” key after the first line, the command-line utility waits for you to type the data in. Press “enter” only once to finish each line. If you press it twice, the utility assumes the entry you are typing is complete and parses the entry. It complains if required attributes are missing and quits. For example, if you push “enter” twice after the first line, as in:

Idapmodify –a –D “uid=admin, o=ldap_abc.de” –w passl dn: o=ldap_abc.de

the utility answers:

Idapmodify: no attributes to change or add (entry="o=ldap_abc.de”)

After that, the program waits for further input. You can continue to add further entries. When you are finished, you can exit from the program with Control-C.

Once we have added the root of the directory, we can proceed to add the various departments, called “organizationalUnit” in LDAP. Exhibit 3 shows how to proceed. In this case, we add an entry of the type “organizationalUnit.” Obviously the dn attribute is now different. It is built up from the previous one “o = ldap_abc.de” plus an additional string “ou = Information Technologies.” The additional string is called a “relative distinguished name” (RDN). The relative distinguished name has to be unique inside its scope. This means that, at the tree below o = ldap_abc.de, there can be no further “ou = IT” entry. Exhibit 4 shows the syntax for adding three additional organizational units.

Exhibit 3. Adding the “organizationUnit” Entry with Idapmodify

# Idapmodify –a –D “uid = admin, o=ldap_abc.de” –w passl

dn: ou=IT, o=ldap_abc.de

objectclass: top

objectclass: organizationalUnit

ou: IT

description: Information Technologies

adding new entry “ou=IT, o=ldap_abc.de”

Exhibit 4. Adding Three Other “organizationUnit” Entries with Idapmodify

# Idapmodify –a –D “cn=admin, o=ldap_abc.de” –w passwordl

dn: ou=HR, o=ldap_abc.de

objectclass: top

objectclass: organizationalUnit

ou: IT

description: Human Resources

adding new entry “ou=HR, o=ldap_abc.de”

dn: ou=R&D, o=ldap_abc.de objectclass: top objectclass: organizationalUnit ou: IT

description: Research and Development

adding new entry “ou=R&D, o=ldap_abc.de”

dn: ou=Mkt, o=ldap_abc.de objectclass: top objectclass: organizationalUnit ou: IT

description: Marketing

adding new entry “ou=Mkt, o=ldap_abc.de”

Now that we have added so many entries, we will look in the directory to verify that the data in the directory matches what we typed in. The tool we use is called “ldapsearch.” Exhibit 5 shows it in action, and the result shows that the output is exactly what we put in.

Let us take a closer look at the ldapsearch command.

ldapsearch –b “o=ldap_abc.de” “(objectclass=*)”

Exhibit 5. Searching the Directory

ldapsearch –b “o=ldap_abc.de” “(objectclass=*)”

# extended LDIF

# LDAPv3

# filter: (objectclass=*)

# requesting: ALL

# ldap_abc.de

dn : o=ldap_abc.de

objectclass: top

objectclass: organization

o: ldap_abc.de

l: Munich

# IT, ldap_abc.de

dn: ou=IT, o=ldap_abc.de

objectclass: top

objectclass: organizationalUnit

ou: IT

description: Information Technologies

# HR, ldap_abc.de

dn: ou=HR, o=ldap_abc.de

objectclass: top

objectclass: organizationalUnit

ou: IT

description: Human Resources

# R&D, ldap_abc.de

dn: ou=R&D, o=ldap_abc.de

objectclass: top

objectclass: organizationalUnit

ou : IT

description: Research and Development

# Mkt, ldap_abc. de

dn: ou=Mkt, o=ldap_abc.de

objectclass: top objectclass: organizationalUnit

ou : IT

description: Marketing

# search result

search: 2

result: 0 Success

# numResponses: 6

# numEntries: 5

The switch “−b” specifies the base from which we want to see all entries, here the root of the directory. The term “(objectclass = *)” specifies that we are interested in seeing all object classes in the directory, not just a particular one. Again, leave the quotation marks where there are. The parentheses in this case are optional, but for more complicated queries, it is a good practice to use parentheses.

If you are not working on the same machine the directory server is running on, you should specify the switch “-h servername” to indicate the machine where the directory server is running. For example, if your server was installed on www.directoryserver.de, your search would look like this:

ldapsearch –h www.directoryserver.de –b o=ldap_abc.de “objectclass = *”

Later in this chapter we will examine the search operation in greater detail.

Now let us finally add an entry for a person. Exhibit 6 shows the command line. This time there are more object-class attributes. The object we want to insert is an inetOrgPerson. It should contain a user ID (uid), a password (userPassword), and an e-mail address (mail).

At this point, if you get an error message complaining about “object class violation” specifying an “unrecognized objectClass: 'inetOrgPerson',” you may have forgotten to include the schema file containing the definition of the object class inetOrgPerson into your configuration file. Put the schema in, stop the server, and restart it again. If the server does not start, complaining instead of a missing attribute type, then you forgot to include another schema file the server needs. In this case, it is the file containing the definition of the attribute type “audio,” provided by the file cosine.schema. At startup the directory server loads the schema files and checks to see if all attributes mentioned in the object classes have been defined.

Now that we have provided definitions for all object classes and attribute types, you will get a message confirming that the person has been successfully added. (See last line in Exhibit 6.)

The object class in LDAP offering these entries is inetOrgPerson. We notice that inetOrgPerson derives from organizationalPerson, which in turn derives from person. As stated before, person finally derives from the top, which enforces the presence of the object-class attributes.

If you look at the point where the object classes are defined, you will see that “person” defines a number of attributes, such as “sn,” the surname, and “cn,” the common name, with the full name being composed of surname + given name. Optionally, the “person” entry can contain a userPassword, a telephoneNumber, a seeAlso reference, and a description. Look at the definition of organizationalPerson. Because this object class inherits from person, the above-listed attributes are not listed anymore. Instead, only the new attributes extending the person class are listed.

Exhibit 6. Adding the “inetOrgPerson” Entry with Idapmodify

# Idapmodify –a –D “uid=admin, o=ldap_abc.de” –w passl

dn: uid=RVoglmaier, ou=IT, o=ldap_abc.de

objectclass: top

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

cn: Reinhard E. Voglmaier

cn: Reinhard Erich Voglmaier

cn: Reinhard Voglmaier

sn: Voglmaier

givenName: Reinhard Erich

ou: IT

uid: RVoglmaier

mail: Reinhard.Voglmaier@ldap_abc.de

adding new entry “uid=RVoglmaier, ou=IT, o=ldap_abc.de”

Let us do another search, but this time we are interested in the object classes of type “organizationalUnit.” Exhibit 7 shows the syntax.

If we want to see the entries for all persons, we must make a query like that shown in Exhibit 8.

At this point, you know enough to start playing around with the software. Add some entries, try to find different object classes, and see what happens. You could also add an “inetOrgPerson” object and an “organizationalPerson” object. Then try to search for “organizationalPerson” or “inetOrgPerson” and see the different results. The more you play, the more you will learn.

Updating a Directory with a Batch Process

We have been typing commands using the command-line tool. This has two drawbacks: the risk of typos and the lack of documentation showing what you typed in. Fortunately, the Idapmodify command also accepts a file as input. Exhibit 9 shows what this file looks like. You will recognize the same input as you gave at the command line. Exhibit 10 shows the messages confirming execution of the file in Exhibit 9.

Until now, we have used Idapmodify only in an interactive mode. Now that we know how to insert the data and instructions from a file, there is no need to use a command line to communicate with Idapmodify. Use Control-C to stop reading input from the prompt.

So far, we have learned that the directory is made up of a hierarchical tree of objects. We have seen that the position of a single object is given by its distinguished name (DN), which must be unique inside the directory. We have also seen that the distinguished name is constructed from the distinguished name of its ancestor plus its own relative distinguished name (RDN). Further, we have learned how to add entries and how to search in the directory. Finally, we have seen that instead of manually typing command-line entries, we can instruct Idapmodify to take its input from a file instead of from the command line. In the next section, we will see that Idapmodify has other functions beyond adding entries.

Exhibit 7. Searching for All Classes of Type “organizationalUnit”

ldapsearch –b “ldap_abc.de” “(objectclass=organizationalUnit)”

# extended LDIF

#

# LDAPv3

# filter: (objectclass=organizationalUnit)

# requesting: ALL

#

# IT, ldap_abc.de

dn: ou=IT, o=ldap_abc.de

objectClass: top objectClass: organizationalUnit

ou: IT

description: Information Technologies

# HR, ldap_abc.de

dn : ou=HR, o=ldap_abc.de

objectClass: top objectClass: organizationalUnit

ou: HR

description: Human Resources

# R&D, ldap_abc.de

dn: ou=R&D, o=ldap_abc.de objectClass: top objectClass: organizationalUnit ou: R&D

description: Research and Development

# Mkt, ldap_abc.de

dn : ou=HR, o=ldap_abc.de objectClass: top objectClass: organizationalUnit ou : Mkt

description: Marketing

# search result

search: 2

result: 0 Success

# numResponses: 5

# numEntries: 4

Exhibit 8. Searching for All Classes of Type “person”

ldapsearch –b “ldap_abc.de” “(objectclass=person)”

# extended LDIF

#

# LDAPv3

# filter: objectclass=person

# requesting: ALL

#

# RVoglmaier, IT, ldap_abc.de

dn: uid=RVoglmaier, ou=IT, o=ldap_abc.de

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: Reinhard E. Voglmaier

cn: Reinhard Erich Voglmaier

cn: Reinhard Voglmaier

givenname: Reinhard Erich

sn: Voglmaier

ou: IT

uid: RVoglmaier

mail: RVoglmaier@ldap_abc.de

mobile: +49 170 36273 3747 3747

# search result

search: 2

result: 0 Success

# numResponses: 2

# numEntries: 1

The LDIF Standard

Let us make a small change in our command file. After the first line (i.e., the line specifying the distinguished name), add the following line:

changetype: add

Now you can execute the Idapmodify command without the “-a” switch. You might not consider this to be an elegant solution, but look at Exhibit 11, where we execute Idapmodify without using the –a switch and give it some new instructions. Exhibit 12 shows the command together with the program’s output.

Let us look more closely at the instruction file in Exhibit 11. The first line of each instruction contains, as always, the distinguished name we wish to operate on. The rest is self-explanatory: Next to the distinguished name, we specify the operation we want. First we add an entry, a command we have already seen in action. We specify with “changetype,” which allows us to add, modify, or delete an entry. In this case, we want to modify some entries. Specifically, we want to replace the value for the mail attribute “RVoglmaier@ldap_abc.de,”

Exhibit 9. Input File for Idapmodify

# cat Persons.ldif

dn: uid=TKlein, ou=Mkt, o=ldap_abc.de

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: Thomas Klein

sn: Klein

givenName: Thomas

ou : Mkt

uid: TKlein

mail: ThomasKlein@ldap_abc.de

dn: uid=PSmith, ou=Mkt, o=ldap_abc.de

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: Peter Smith

sn: Smith

givenName: Peter

ou : Mkt

uid: PSmith

mail: PeterSmith@ldap_abc.de

Exhibit 10. Execution of Idapmodify with Input from a File

Idapmodify –a –D “uid=admin, o=ldap_abc.de” –w “passl” –f

Persons.ldif

adding new entry “uid=TKlein, ou=Mkt, o=ldap_abc.de”

adding new entry “uid=PSmith, ou=Mkt, o=ldap_abc.de”

which we entered in Exhibit 8, into the correct name “ReinhardVoglmaier@ldap_abc.de.” After the instruction “changetype: modify,” we insert a line instructing Idapmodify that we want to replace the value of the mail attribute. In the next line, we simply specify the new value.

Next, we add a new attribute – the mobile phone number – for the qualified entry. Again, we specify what we intend to do: We want to modify an entry, adding a new attribute.

Finally, we instruct Idapmodify to delete an entry. Again, the syntax is straightforward: Identify the distinguished name and carry out the associated action, “delete.”

All of these commands are executed with the familiar Idapmodify command, but without the -a switch.

Now you can really play around with your LDAP installation. You can add, delete, and modify entries, and you can see what you have in your directory.

Exhibit 11. More Instructions for Idapmodify

# cat modify.ldif

dn: uid=SParker, ou=HR, o=ldap_abc.de

changetype: add

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: Sarah Parker

sn: Parker

givenName: Sarah

ou: HR

uid: SParker

mail: SarahParker@ldap_abc.de

dn: uid=RVoglmaier, ou=IT, o=ldap_abc.de

changetype: modify

replace: mail

mail: ReinhardVoglmaier@ldap_abc.de

dn: uid=RVoglmaier, ou=IT, o=ldap_abc.de

changetype: modify

add: mobile

mobile: (0049) 89 671 293

dn: uid=TKlein, ou=Mkt, o=ldap_abc.de

changetype: modify

delete: mail

dn: uid=PSmith, ou=HR, o=ldap_abc.de

changetype: delete

Exhibit 12. Execution of Idapmodify Using the Instructions from the File in Exhibit 11 in the Idapmodify Command

# Idapmodify –D “uid=admin, o=ldap_abc.de” –w “passl” –f Persons.ldif

adding new entry “uid=SParker, ou=HR, o=ldap_abc.de”

modifying entry “uid=RVoglmaier, ou=IT, o=ldap_abc.de”

modifying entry “uid=RVoglmaier, ou=IT, o=ldap_abc.de”

modifying entry “uid=TKlein, ou=Mkt, o=ldap_abc.de”

deleting entry “uid=PSmith, ou=HR, o=ldap_abc.de”

The format of the input file is standardized and is defined in the RFCs, as explained in Chapter 1. The RFC for this standard LDIF format is RFC 2849, “The LDAP Data Interchange Format (LDIF) – Technical Specification.”

An LDIF file is an ASCII file containing all instructions to modify the directory. Using a pure ASCII file is enormously helpful. First of all it is easy for you to read and understand. This makes it possible for you to control without great effort the contents of this file. An ASCII file is furthermore very easy to produce using home grown scripts, and debugging is facilitated. Finally, it is self-explaining. The LDIF file has further advantages as a tool for directory migration. You can export your entire directory as an LDIF file and import it to another directory implementation, even if both directories are incompatible with each other. You can also use LDIF to save your directory on a storage medium such as tape or CD. And because the format is standardized, you can produce LDIF files in your preferred programming language. If you want to modify the structure of your directory, you can do it easily using a scripting language such as the powerful Perl language. First you export the directory as an LDIF file, make the conversion, and then delete the obsolete directory and import the new LDIF files.

Rewriting and then destroying the old directory might seem to be an overly aggressive management style. Why destroy the whole directory if you only have to make a few changes? Consider what should be a trivial operation: changing the distinguished name of a single organizational unit. If you wanted to change the distinguished name for “human resources,” giving it a more self-explanatory name, you might proceed as follows. The previous name was:

dn: ou=HR, o=ldap_abc.de

Now we would like to rename it as:

dn: ou=Human Resources, o=ldap_abc.de

The directory server will refuse the name change because the “HR” entry has subentries. The “HR” organizational unit has sibling entries of the objectClass “person.” The logical approach would be to change the “person” entries, but this does not solve the problem because the “person” entries would no longer have an ancestor. Using this “logical” approach, the only solution is to create a new entry of the objectClass “organizational unit,” move all relevant persons to the new name, and then delete the obsolete organizational unit. A simpler solution is the “aggressive” approach mentioned above: Export the directory in a file, clear the directory, modify the exported file, and re-import it.

Consider this common real-world example. Two companies have merged. Every entry in the LDAP directory has to be changed.

■  In the object “organization,” you have to change the attributes “distinguished name” and “organization.”

■  In the object “organizationalUnit,” you have to change the attribute “distinguished name.”

■  In the object “inetOrgPerson,” you have to change the attributes “distinguished name” and “mail.”

Exhibit 13. Simple Perl Script to Modify the Enterprise Name

#!/usr/bin/perl –w

# Name: convert.pl

# Version: 1.0

# Author: Reinhard E. Voglmaier

# Description: Conversion Utility per LDAP repository

# Date: 10.09.2002

$in_ldif = “Directory_In.ldif”;

$out_ldif = “Directory_0ut.ldif”;

# open the original file

open(IN,”>$in_ldif”) || die “could not open input file:

$in_ldif” ;

#open the output file

open(0UT,”> $out_ldif”) || die “could not open output file: $out_ldif” ;

# Conversion:

while (<IN>) {

# we simply substitute the enterprise name s/ldap_abc.de/LdapAbc.org/g ;

# here we could change other things, too s/Mkt/Marketing/g ;

s/HR/Human Resources/g; print OUT ;

}

# close INPUT and OUTPUT files

close(IN);

close(OUT);

Exhibit 13 shows a Perl script that automates this process. The script may be simplistic, but it effectively illustrates how easy it is to make changes in a running directory while maintaining consistency.

Ldapsearch Revisited: Search Filter

The output of our previous search was not particularly sophisticated, nor was the query we made to our directory. Had we been searching a directory with millions of entries (like a phone book), we would have produced a simple dump of all entries.

Let us concentrate first on refining the output. You can easily specify relevant fields for an ldapsearch, such as the full name (common name called “cn” and surname called “sn”) and the e-mail address (called “mail”), for example. Exhibit 14 shows how this is done.

Remember that we had some entries with more than one value for the attribute “common name.” Suppose we want to pull the data for someone and we only know the surname. The query string in LDAP parlance is called “filter.” Here, the filter is rather simple: We wish to get all persons whose name is “Parker.” The filter would therefore simply be:

sn=Parker

Look at Exhibit 15 to get the correct syntax. An exact description of this syntax is found in Chapter 5, where we will not only look at the command-line tools, but also at other, more-sophisticated APIs, such as Perl or Java.

The query produced two entries with the sn Parker. To further refine the query, we could search for all people named Parker and working in the Research department. The additional condition is:

(ou=Research)

Exhibit 14. Limited Output with Idapsearch

ldapsearch –b “LdapAbc.org” “(objectclass=person)” cn mail

# extended LDIF

#

# LDAPv3

# filter: (objectclass=person)

# requesting: cn mail

#

# RVoglmaier, IT, LdapAbc.org

dn: uid=RVoglmaier, ou=IT, o=LdapAbc.org

cn: Reinhard E. Voglmaier

cn: Reinhard Erich Voglmaier

cn: Reinhard Voglmaier

givenname: Reinhard Erich

mail: [email protected]

# TKlein, Mkt, LdapAbc.org

dn: uid=TKlein, ou=Mkt, o=LdapAbc.org cn: Thomas Klein

# PSmith, Mkt, LdapAbc.org

dn: uid=PSmith, ou=Mkt, o=LdapAbc.org

cn: Peter Smith

mail: [email protected]

# SParker, HR, LdapAbc.org

dn: uid=SParker, ou=HR, o=LdapAbc.org

cn: Sarah Parker

mail: [email protected]

# search result

search: 2

result: 0 Success

# numResponses: 5

# numEntries: 4

Exhibit 15. A Simple Query Filter

ldapsearch –b “LdapAbc.org” “(sn=Parker)”

# extended LDIF

#

# LDAPv3

#

# filter: (sn=Parker)

# requesting: ALL

#

# JParker, Human Resources, LdapAbc.org

dn: uid=JParker, ou=Human Resources, o=LdapAbc.org

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: James Parker

sn: Parker

givenName: James

ou : Human Resources

uid: JParker

mail: [email protected]

# TParker, Research, LdapAbc.org

dn: uid=JParker, ou=Human Resources, o=LdapAbc.org

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: Tina Parker

sn: Parker

givenName: Tina

ou: Human Resources

uid: TParker

mail: [email protected]

# search result

search: 2 result: 0 Success

# numResponses: 3

# numEntries: 2

However, the two filters have to be joined by a logical AND operator. LDAP uses a particular notation known as Polish notation, or prefix notation, where the two operands to be connected are prefixed by the operator.* The AND condition reads:

(& (sn=Parker) (ou=Research))

Exhibit 16 shows the result.

Exhibit 16. A Somewhat More Complicated Query

ldapsearch –b “LdapAbc.org” “(&(sn=Parker)(ou=Research))”

# extended LDIF

#

# LDAPv3

# filter: (&(sn=Parker)(ou=Research))

# requesting: ALL

#

# TParker, Research, LdapAbc.org

dn: uid=JParker, ou=Human Resources, o=LdapAbc.org

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: InetOrgPerson

cn: Tina Parker

sn: Parker

givenName: Tina ou: Human Resources uid: TParker

mail: [email protected]

# search result search: 2 result: 0 Success

# numResponses: 2

# numEntries: 1

The attribute values can also contain white spaces as well as special characters. However, a number of special characters that have a specific meaning for the LDAP protocol cannot be used directly as attribute values. They have to be encoded. Chapter 4 provides more information on this topic. LDAP also recognizes other logical operators such as OR and NOT. For example, you could search for a person named Parker working in the IT department or in Marketing. The filter would look like this:

(& (sn=Parker) (| (ou=Information Technologies)(ou=Marketing)))

If you were searching for Parker but NOT in the Human Resources department, the filter would be as follows:

(& (sn=Parker) (!(ou=Human Resources)))

The example search in Exhibit 17 simply shows all entries having a certain attribute, in this case a mobile phone number.

The final example of a query filter is presented in Exhibit 19, which illustrates the use of wild cards in a filter. In this case, the ldapsearch tool is instructed to print only the common name, the surname, and the e-mail address. The ldapsearch tool suppresses any additional information, printing only the explicitly requested information. Here we search for all entries with sn beginning with “Vogl,” so it finds sn = Vogl and sn = Voglmaier.

Exhibit 17. Search with Query Filter

ldapsearch –b “LdapAbc.org” “(mobile=*)”

# extended LDIF

#

# LDAPv3

#

# filter: (mobile=*)

# requesting: ALL

#

# RVoglmaier, IT, LdapAbc.org

dn: uid=RVoglmaier, ou=IT, o=LdapAbc.org

objectClass: top

objectClass: person

objectClass: organizationalPerson

objectClass: inetOrgPerson

cn: Reinhard E. Voglmaier

cn: Reinhard Erich Voglmaier

cn: Reinhard Voglmaier

givenname: Reinhard Erich

sn: Voglmaier

ou: IT

uid: RVoglmaier

mail: [email protected]

mobile: +49 170 36273 3747 3747

# search result search: 2

result: 0 Success

# numResponses: 2

# numEntries: 1

Exhibit 18. A More Complete Example of Search

ldapsearch –LLL –b “LdapAbc.org” “(sn=Vogl*)” cn sn mail

dn: uid=RVoglmaier, ou=IT, o=LdapAbc.org

cn: Reinhard E. Voglmaier

cn: Reinhard Erich Voglmaier

cn: Reinhard Voglmaier

givenname: Reinhard Erich

sn: Voglmaier

mail: [email protected]

dn: uid=KVogl, ou=Research, o=LdapAbc.org

cn: Kurt Vogl

sn: Vogl

mail: [email protected]

That will be the last example of a filter application for now. Nevertheless, you will see the filter again in Chapter 3, when we speak about the theory of LDAP, and again in Chapter 6, which covers the other LDAP APIs.

As you have seen, the filter mechanism is robust and LDAP can execute powerful queries using Polish notation. LDAP, however, does not offer joins between different objects as does a relational database management system (RDBMS). Having seen the examples presented in this section, you should play with the command-line language to become more familiar with the directory server. Again, the syntax of the ldapsearch utility could be slightly different on your server implementation. However, the logic should be the same. Refer to the documentation delivered with the product you are using.

LDAP: Is This a Protocol?

In Chapter 1, we learned that LDAP is the abbreviation for Lightweight Directory Access Protocol. Until now, however, it did not matter that it is a network protocol. You should not need to pay attention to that fact unless you are using a directory server installed on a remote machine. If you are using a directory server such as this, you will need to jump from the beginning of this chapter to here. I will explain to you how you have to proceed in order to try out the examples. You have to specify on which computer the directory server is running. You do so using the –h <computername> switch. Exhibit 19 shows you how to do this. In this example, you need to assume that the directory server is running on a computer named “ldap2.co.uk.” With this knowledge, you can execute all exercises that we have had up until now as if they were running on the local computer. Now let us discuss the LDAP protocol.

The LDAP protocol runs over TCP/IP (Transmission Control Protocol/Internet Protocol), and the command-line tools are no more than small client applications. Of course, the client application has to be installed on your system, and it is the client application that imposes the syntax of the commands entered by the user. The client application then speaks with the directory server using the standard LDAP protocol.

To speak with a directory server located on the remote machine http://ldap2.co.uk, you simply have to specify the host in the command-line tool. On my implementation (OpenLDAP), the -h switch specifies the host where LDAP is running. Exhibit 19 shows the transaction.

In this example, I have also specified the port number for the directory server. This is not necessary unless the server runs on a nonstandard port, such as might occur if you have an administration server and a data server. The administration server might run on a different port than the data server, improving the performance of the data server by freeing it from administration traffic. The administration server also could be shut down when not in use and restarted only when it had work to do.

Exhibit 19. A Search against a Remote Directory Server

ldapsearch –h ldap2.co.uk –p 389 –LLL –b “LdapAbc.org”

“(sn=Vogl*)” cn sn mail

dn: uid=RVoglmaier, ou=IT, o=LdapAbc.org

cn: Reinhard E. Voglmaier

cn: Reinhard Erich Voglmaier

cn: Reinhard Voglmaier

givenname: Reinhard Erich

sn: Voglmaier

mail: [email protected]

dn: uid=KVogl, ou=Research, o=LdapAbc.org

cn: Kurt Vogl

sn: Vogl

mail: [email protected]

Your Favorite Browser Speaks LDAP

The following example demonstrates that your browser speaks LDAP. For this exercise, you need

1.  A directory server running on a machine (call it “ldap.mycompany.uk”)

2.  A Web browser installed on your machine

That is all you need. Open your favorite browser and type in the following:

ldap://ldap.mycompany.uk/o=LdapAbc.de

I assume that the directory is named that way, but if you use a different baseDN, change it according to your installation. Exhibit 20 shows what I see on my machine (SuSE Linux with the Konqueror browser). It also works with Netscape or IE.

Now that you have located the directory, you can navigate the whole tree. In the Konqueror browser, one simply clicks on the icons and the correct LDAP URL opens. On other browsers, you have to do the typing yourself. Either way, the information you get is the same. Exhibit 21 shows the view after opening the Human Resources object. Exhibit 22 shows the view for one of the inetOrg-Person entries in the Human Resources object. Note that it is possible to specify selected values for an entry, such as the cn, sn, and mail attributes.

Image

Exhibit 20. Base URL via Web Browser

Image

Exhibit 21. Human Resources DN via Web Browser

Image

Exhibit 22. InetOrgPerson Entry via Web Browser

The LDAP URL format is standardized and defined in RFC 2255, “The LDAP URL Format.” It is treated in Chapter 4 of this book when we discuss the details of LDAP. For now, we will, just for completeness, show the syntax of the command:

“ldap://”[hostname[“:” portNumber] ] “/” baseDN [ query ]

where the query is:

[“?” attributeList [“?” scope “?” filter [“?” extensions ] ] ]

Conclusion

This chapter covered many aspects of LDAP without going into the details. The scope was simply to introduce some key concepts and present examples of LDAP at work so that the reader could begin using basic LDAP commands. The best way to learn how to use new software is to install it and then play around with it. Armed with the basic concepts presented here in Chapter 2, we are ready to delve further into the details covered in Chapter 3, a chapter of pure theory explaining how LDAP works.

Notes

The Polish notation was published by the Polish philosopher and mathematician Jan Lucasiewicz (1878-1956). Reverse Polish notation (RPN), which postfixes the operands with the operator, was used in the first Hewlett-Packard electronic calculators.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.13.116