oreilly.comSafari Books Online.Conferences.


Getting Started with LDAP
Pages: 1, 2


As you may have already guessed, attributes can have multiple values. Whether an attribute supports multiple values is stated in the definition of the attribute, but most do.

As we mentioned earlier, the top object class requires that the objectclass be present, and it is. Thus, the presence of top has no other effect on this entry. The posixAccount object class requires cn, uid, uidNumber, gidNumber, and homeDirectory, and allows userPassword, loginShell, gecos, and description. Because a valid login account should have all of this information except the description, we have included all of it in our entry.

All of our attribute values are self-explanatory, except for the value of the userPassword. Because most (all?) Unix machines store passwords in crypt format, and because we are going to dump the LDAP entry into the passwd file, we must also store the LDAP password in crypt format. Many LDAP servers support multiple password formats, and we have included an example of how to specify the format. Servers that support multiple formats should allow specification of the default format, and it is recommended that you set the default format to crypt if you plan on using your LDAP server for storing Unix accounts. The only exception to this is if all of your Unix machines can authenticate directly off of the LDAP server and can understand formats other than crypt.

Using the data

Okay, we have the entry in the LDAP server, and we have a basic understanding of the entry itself. Now it's time to start using the data. As mentioned earlier, if you want to read an entry, you have to search for it. So, to verify that our entry is present, we will do so.

There are a total of eight (yes, eight) different options for every LDAP search, but most of them have reasonable defaults and they mostly make sense. We won't be using very many of these options to start, to keep it simple.

Here's an example search:

$ ldapsearch -h server -b "dc=domain,dc=com" "(uid=luke)"
cn=Luke A. Kanies
gecos=Luke A. Kanies

This is on a Solaris box; horror of horrors -- notice that the output is not in LDIF format (equal signs are used instead of colons and spaces). Amazing but true. Notice also that the password is not printed; this is for security reasons, in the same way that /etc/shadow is only readable by privileged users.

In our search, we included two flags and an argument. The first flag is obvious: We specified the server. The second flag specified the base for the search, similar to how one specifies the start point of a search using the find command; we could have specified any branch including the object itself. The argument to the search is called the filter, and it's how we specify the specific entry or entries we want. All entries matching the filter will be returned. Fortunately the filter format is somewhat sophisticated, so you shouldn't have problems performing complex searches to find exactly what you want, but I'm only going to use basic filters to get the job done. For more information, consult a reference of some kind.

Because we know the dn of the entry, we could have also performed our search thus:

$ ldapsearch -s base -h server -b "uid=luke,ou=People,dc=domain,dc=com" "(objectclass=*)"

Because we know the dn, we can set that dn as the base of our search. If we do that, however, we can change the scope of the search. By default, an LDAP query searches for objects anywhere in the heirarchy beginning at the base of the search. You can also specify a scope of "one", which only searches the next lower level of the hierarchy, and base, which searches only the base itself. I have actually noticed some discrepencies here when using iPlanet Directory Server 4.x; usually the base of the search is returned if it matches the filter, but I have seen instances where that is not the case. The above method is the preferred method of retrieval if you know the dn of the entry, because it is faster and requires less work from the server.

Notice also that our filter has changed. We previously searched for a specific value of uid, but because we are using the entry's dn as the base of our search in order to retrieve it directly we use what is called an existence filter. When an attribute is searched for with a value of *, the LDAP server returns every entry which has any value for that attribute. Because all entries have values for objectclass, using a filter of objectclass=* is the standard method for returning all entries matching a given base and scope. The reason for preferring an existence filter over a more specific filter is that a specific filter causes the LDAP server to work harder, and using an existence filter here provides the same result with less work for the server.

Creating the Unix account

This is all fine and good, we've got the data in the LDAP server, and we can look at it, but how are we going to turn it into a Unix account?

Well, assuming you have added this entry and all other desired entries to your LDAP server, all it takes is a simple shell script to convert this data to the passwd and shadow files:

# shell script to convert from LDAP to passwd/shadow files
' # set the internal file separator to a carriage return, in case
  # attributes have spaces or tabs in them

# look for all entries which have the posixAccount objectclass
# we have to authenticate as a privileged user in order to read the
# password
for entry in $(ldapsearch -h server -D \
"uid=sysadmin,ou=People,dc=domain,dc=com" -w password \
-b dc=domain,dc=com "(objectclass=posixAccount)"); do

  # this is the logic that prints out the passwd entry for the
  # previous entry every time we hit a DN line
  echo $line | grep "dc=madstop,dc=com" > /dev/null
  if [ $? == 0 -a ! -z "$uid" ]; then
    echo $uid:+:$uidnumber:$gidnumber:$gecos:$homedirectory:$usershell \
    >> newpasswd
    echo $userpassword >> newshadow

  # this uses some trickery to cause the shell to interpret
  # ldapsearch output as variable assignments; this may need
  # to be modified depending on the output of the ldapsearch command,
  # but this works with the ldapsearch supplied on Solaris 8
  newline=$(echo $line | sed "s/'/'\''/g
  eval $newline
# this echo line puts our last entry into the files, because our
# method of dumping the entries is triggered by the next entry,
# and there is no next entry for the last entry
echo $uid:+:$uidnumber:$gidnumber:$gecos:$homedirectory:$usershell \
>> newpasswd
echo $userpassword >> newshadow

# backup the passwd and shadow files, and put the new ones in place
for file in passwd shadow; do
  cp $file $file.bak
  cp new$file $file

Is this pretty? Not really. Would I have rather done it in Perl? Yeah, but I don't want to get into the Perl API(s) just yet. Regardless, this script will take your LDAP entries and create valid passwd and shadow files for Solaris. They may require modification for other Unixes. This isn't terribly interesting or useful if you only have a couple of Unix machines, but if you have 200 machines all running different versions of Unix, you can easily make a version of this script for each version of Unix (if necessary), and thus consolidate all of your account information into one data store.

One thing we've ignored here is password management information. All information related to password aging and management is stored in the shadowAccount object class. It is straightforward to use, and would have only complicated this article, so its use is left to the reader. Another thing we've ignored is security; that is, we are doing a clear-text authentication to the LDAP server and all of the communication is in clear-text. A later article will begin to explain how to incorporate encryption into your directory service. SSL authentication isn't much more difficult than simple authentication.


We've now hopefully added our Unix account information to LDAP, and we've provided a way to pull the information back out and repopulate the passwd and shadow files. Yes, we've ignored the group files, which are also important, and we've assumed that every account is going to be present on every machine. Fortunately, it isn't much of a leap to put the group information into LDAP, and it is relatively easy to only pull certain classes of users to various classes of machines, for example, only adding developer and system administrator accounts to the web servers, and only adding system admininistrator and DBA accounts to the database servers. In fact, as you begin to use LDAP more, you'll find that like so many other automation/centralization processes, the hardest part is deciding how to make the above classifications. Most companies rely on the system administrator admin to decide if a user gets an account somewhere, or how often passwords get changed, and even if there are clear rules, those rules are usually obeyed only by system administrators, not the tools they use.

Related Reading

Running LinuxRunning Linux
By Matt Welsh, Matthias Kalle Dalheimer & Lar Kaufman
Table of Contents
Sample Chapters
Full Description
Read Online -- Safari

To fully take advantage of LDAP, all of those rules must be pushed into LDAP, such that all of these decisions can be made by the automated tools instead of by people. It's a one-time investment toward a future of of less work. Fortunately, development and codification of these rules is very good for your business even if you don't plan to use LDAP, and you will most likely find that doing so is a beneficial process in and of itself.

As we progress in this series of articles, we will develop an LDAP architecture for a simple example organization. One of the aspects of that process will be to create these LDAP rules which determine who has access to what services and information, including who has accounts on which machines.

Next time

We've introduced to some aspects of how authentication is handled within LDAP and how you can migrate your existing authentication data into LDAP. In the next article in this series, we will explore management of this data through a web interface, along with basic AAA control, which is necessary for acceptable management. If I can get it together in time, we might just be able to incorporate SSL into the mix, too.

Luke A. Kanies is an independent consultant and researcher specializing in Unix automation and configuration management.

Return to the Linux DevCenter.

Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!

Linux Resources
  • Linux Online
  • The Linux FAQ
  • Linux Kernel Archives
  • Kernel Traffic

  • Sponsored by: