Linux Authentication Using OpenLDAP

by David "Del" Elson

Part 1

Introduction

This is the first of two articles that will discuss a number of issues with LDAP authentication on Linux. In this installment, I will discuss an overview of LDAP, installing and configuring OpenLDAP, migrating to OpenLDAP and setting up LDAP queries. In this series, I will focus on Red Hat Linux version 7.1 (with some comments about earlier revisions;) however many of the same principles apply to Debian and other Linux distributions.

Authentication, PAM, and NSS

Authentication is the process wherein a user logging on to a Linux system has their credentials checked before being allowed access. Usually, this means that a user needs to provide a login name and a password.

Many different programs provide authentication, each using a different method. For example, the basic Unix login program provides a simple text interface for a user to enter a user ID and password. Graphical login systems such as XDM (or GDM or KDM) provide a different interface. Programs such as SSH can authenticate users based on things like RSA or DSA keys as well as passwords.

There are many different authentication suites or protocols available on Linux today. Like all traditional Unix systems, Linux is capable of authenticating users against entries in the /etc/passwd and /etc/shadow files, but it also supports such authentication schemes as Kerberos, RADIUS, and LDAP, which stands for Lightweight Directory Access Protocol.

PAM (which stands for Pluggable Authentication Modules) is a set of libraries provided with most modern Linux distributions, and it is installed by default in Red Hat Linux. The PAM libraries provide a consistent interface to an authentication protocol. An application can use the PAM libraries to allow the use of any authentication protocol within that application, so that if the system administrator wants to change from, for example, /etc/passwd authentication to LDAP, the application does not have to be re-written or recompiled. PAM requires a PAM module for each authentication system. There are many such PAM modules on the above web site.

Unfortunately, PAM only provides part of the information needed to keep track of users on a Linux system. In addition to being able to check that a user has entered the correct password, a Linux system needs other information, such as the user's numeric user ID, their home directory, default shell, etc. This information, which would normally be stored in the /etc/passwd file, can be determined through a system interface known as NSS, or Name Service Switch.

Only some authentication schemes provide enough information to be useful to NSS. For example, Kerberos only stores user authentication information, not details such as a home directory or default shell. Therefore, there is no NSS module for Kerberos.

What is LDAP?

LDAP, or Lightweight Directory Access Protocol, is a network protocol that is used for accessing information in an object-oriented database. LDAP includes features that make it useful to both PAM and NSS, as it can authenticate users, as well as providing user information such as home directory names and default shells to NSS.

An LDAP Server or Directory Server (sometimes called a DS for short) is a server that can send and receive information in the LDAP protocol. Typically, an LDAP server will be a piece of software that listens on the standard LDAP ports (389 and sometimes 636) for connections, and responds to LDAP queries and requests. To draw an analogy with databases, LDAP is the equivalent of SQL, and an LDAP server is like a database server such as Oracle or MySQL.

LDAP servers are particularly useful for storing information about people. This is because of the object-oriented nature of LDAP. Unlike a relational database, an object in an LDAP directory can contain an arbitrary number of attributes, and each attribute can have an arbitrary number of values. This is useful for many reasons. For example, a database row containing a column for a phone number would allow a single entry in that phone number column for each row in the database table. A person, however, may have more than one phone number, and so LDAP allows multiple phone numbers to be stored in the same person object. Note the slightly different terminology here: we say an LDAP 'directory' as opposed to a 'database', we call entries in the directory 'objects' instead of 'rows', and we call field values of an object 'attributes' instead of 'columns'.

Why Use LDAP?

There are a number of reasons why we might use LDAP:

OpenLDAP

OpenLDAP is an open source implementation of an LDAP directory server. OpenLDAP is installed by default with Red Hat 7.1 or later, and is available on Red Hat versions from 6.2 onwards. Note that earlier releases of Red Hat used release 1 of the OpenLDAP product. Although this is still considered a stable release by the OpenLDAP team, for a number of security reasons, I would advise against using it. For example, it does not support SSL or schema checking. Your OpenLDAP version should be 2.0.7-3 or later.

Installing OpenLDAP

As usual, you can install OpenLDAP from the source code by obtaining the source files from the OpenLDAP web site and following the compilation instructions. My preference, however, is to install the OpenLDAP packages from the RPM files as follows. Note that you will need to install both the server and client packages if you want to set up an OpenLDAP server. First, put your Red Hat CD-ROM into your CD-ROM drive and use the following sequence of commands:

1. mount /dev/cdrom /mnt/cdrom
2. cd /mnt/cdrom/RedHat/RPMS
3. rpm -Uhv openldap-2.0.7-14.i386.rpm openldap-servers-2.0.7-14.i386.rpm 
openldap-clients-2.0.7-14.i386.rpm
4. umount /mnt/cdrom

It's possible that the packages are already installed on your system (to verify this you can do rpm -q openldap.) It is also possible that you may hit one or more dependencies in installing the above RPMs. In particular, the OpenLDAP packages require the OpenSSL package, and at least the krb5-libs package.

LDAP,PAM and NSS libraries

Using LDAP will almost certainly require you to install the PAM libraries for LDAP. In Red Hat 6.2 and later, these are packaged in with the nss_ldap package (since the pam_ldap libraries are not much use without the nss_ldap libraries and vice-versa). These are normally installed by default - to test this you can run rpm -q nss_ldap. If the nss_ldap package is not installed, you can install it using RPM as follows:

  
  mount /dev/cdrom /mnt/cdrom
  cd /mnt/cdrom/RedHat/RPMS
  rpm -Uhv nss_ldap*.rpm
  umount /mnt/cdrom

If you need to obtain the source code for the pam_ldap and nss_ldap libraries, they are available from PADL.com at the following locations:

Configuring OpenLDAP

Configuration of OpenLDAP is done through the /etc/openldap/slapd.conf file. There is a manual page describing the contents of the slapd.conf file (see man slapd.conf) as well as an excellent administration guide on the OpenLDAP web site. As a starting point, you might like to use the following simple configuration file:

#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema
include         /etc/openldap/schema/rfc822-MailMember.schema
include         /etc/openldap/schema/autofs.schema
include         /etc/openldap/schema/kerberosobject.schema

#######################################################################
# ldbm database definitions
#######################################################################

database        ldbm
suffix          "o=MyCompany,c=AU"
rootdn          "uid=root,ou=People,o=MyCompany,c=AU"
rootpw          secret
directory       /var/lib/ldap
# Indices to maintain
index   objectClass,uid,uidNumber,gidNumber     eq
index   cn,mail,surname,givenname               eq,subinitial

#
# ACLs
#

access to dn=".*,ou=People,o=MyCompany,c=AU"
   attr=userPassword
 by self write
 by dn="uid=root,ou=People,o=MyCompany,c=AU" write
 by * auth

access to dn=".*,o=MyCompany,c=AU"
 by self write
 by dn="uid=root,ou=People,o=MyCompany,c=AU" write
 by * read

access to dn=".*,o=MyCompany,c=AU"
 by * read

defaultaccess read

One thing that should be noted in the configuration file above: users should replace "o=MyCompany,c=AU" throughout the file with a Base DN which represents their organization. Note that I prefer to use the X.500 style specification above, but you could use the DNS specification which is "dc=mycompany,dc=com,dc=au" or similar. For example, if your company was called "farnarkle.com" you could use "dc=farnarke,dc=com", or you could use "o=farnarke,c=US". Remember this Base DN, it will be important later.

I have elected to include some elementary Access Control in the file. The standard slapd.conf file included with Red Hat Linux does not include ACLs, but they are mandatory for real use. You may want to expand on the above ACLs (see the slapd.conf manual or the administrator's guide.)

I have included a default root password - 'secret'. This is a bad idea once you have data in your LDAP directory. We will deal with this later.

I have not included TLS certificates, keys, or other information. I would consider this to be a security issue on a network, because without these the server will operate entirely in plain text mode. This will be covered later.

Once you have a working slapd.conf file, you should be able to start your server. This is easy enough to do, you can just run the following command:

/etc/rc.d/init.d/ldap start

Provided that the slapd.conf file is correct, you should be able to use pstree to see a running slapd process. If the slapd.conf file is incorrect, look for error messages (running slapd -d here might help), fix up any problems you see, and try again.

Migrating to OpenLDAP

Once you have your LDAP server started, you will have an empty directory. The first thing you need to do is to populate it with data from your existing authentication database.

Using the supplied LDAP tools

OpenLDAP provides a suite of tools to migrate data from your existing NIS or /etc/passwd database into LDAP. If you currently run another authentication scheme such as Kerberos or S/Key, and you are migrating to LDAP, then I'm afraid you are on your own.

In Red Hat Linux 7.1, the migration tools are in /usr/share/openldap/migration/. In Red Hat 6.2 and earlier they were in /usr/lib/openldap/migration/. In either case, open a shell window, change to that directory, and get to work. First, edit the migrate_common.ph file. Around line 72 you will see a couple of lines like this:

  $DEFAULT_MAIL_DOMAIN = "babel.com.au";
  $DEFAULT_BASE = "o=Babel,c=AU";

You will need to edit these two lines, providing your default mail domain and the Base DN that you defined earlier in the slapd.conf file. Next, it's a simple matter of running the migration tools. This can be done using a simple command, assuming that you are migrating from /etc/passwd files to LDAP:

migrate_all_online.sh

(make sure that your LDAP server is running before using the above command). This will ask you for the root DN and password (enter the password secret that we defined in the slapd.conf file), and will start to populate your LDAP directory.

Setting up LDAP queries

Having data in your LDAP directory is all very well and good, but at some stage you are going to want to query that data. There are a standard set of command line-based LDAP query and management tools provided with OpenLDAP. These include ldapadd, ldapmodify, and ldapsearch. Each of these tools has a man page, and you would do well to read these man pages in detail.

The standard configuration file for these tools is /etc/openldap/ldap.conf. The file format of this file is fairly simple; on a single system it need only contain the following two lines:

  BASE o=MyCompany,c=AU 
  URI ldap://127.0.0.1

Remember to substitute your Base DN that you defined in the slapd.conf file instead of the o=MyCompany, c=AU entry shown above.

On a network, you may have to substitute the IP address of your LDAP server instead of 127.0.0.1 shown above. For those of you who understand LDAP concepts a little better: OpenLDAP doesn't (yet) support SLP or DNS RR based location, so you have to be fairly precise about the location of the server -- either an IP address, a host name from /etc/hosts, or something that can be found in DNS.

Once you have done that, you should be able to perform a simple search. You could start by looking for your root user by using the following simple command:

  ldapsearch -x 'uid=root'

You should see an entry fairly similar to this one:

version: 2

#
# filter: uid=root
# requesting: ALL
#

# root,People,MyCompany,AU
dn: uid=root,ou=People,o=MyCompany,c=AU
uid: root
cn: root
sn: root
mail: root@mycompany.com.au
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: kerberosSecurityObject
objectClass: shadowAccount
shadowMax: 99999
shadowWarning: 7
krbName: root@MYCOMPANY.COM.AU
loginShell: /bin/bash
uidNumber: 0
gidNumber: 0
homeDirectory: /root
gecos: root

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

Now that you have come this far, stop and smile. You have managed to get LDAP working, which is sometimes not an easy task!

This brings us to the end of the first installment of this two-part series. In the next article, we will continue the discussion of OpenLDAP and Linux, covering subjects such as: Setting up PAM and NSS for LDAP, LDAP Tools, making OpenLDAP more secure and generating SSL keys for OpenLDAP.

Part 2

This is the second part of a two-part series devoted to discussing LDAP authentication on Linux. The first installment offered an overview of LDAP including: installing and configuring OpenLDAP, migrating to OpenLDAP, and setting up LDAP queries. This installment will look at setting up PAM and NSS for LDAP, securing the root account, some LDAP tools, securing OpenLDAP, OpenLDAP and SSL, and some concerns about OpenLDAP. Just a note, while this series focuses on RedHat 7.1, most of the same principles apply to Debian and other Linux distributions.

Setting up PAM and NSS for LDAP Using authconfig

First, a warning: this only works with authconfig on Red Hat versions 7.0 or later. If you are using Red Hat 6.2 or earlier, you will need to read the man pages regarding the configuration files and edit them all by hand. Note also that there is no /etc/pam.d/system-auth file on Red Hat 6.2.

Setting up PAM and NSS for LDAP requires editing a configuration file in /etc/pam.d (/etc/pam.d/system-auth), modifying the NSS configuration file, which is /etc/nsswitch.conf, and editing the pam_nss and pam_ldap configuration file, which is /etc/ldap.conf. Fortunately, Red Hat provides a utility called authconfig that will do this automatically for you. To use this, run authconfig from the command line. Within authconfig this is a fairly straightforward exercise. Mark the box labelled 'Use LDAP'. In the next boxes, you should enter a value for the server (this will be the same IP address you used in /etc/openldap/ldap.conf), and a Base DN (this will be the same as the Base DN that you specified in /etc/openldap/slapd.conf)

Once you have finished that, everything should be set up. I find that the best way to test this is as follows:

Secure the Root Account

The slapd.conf file that was set up earlier contains an entry for the root DN as well as a password. This password is used as a fallback password for the root DN in case the entry is not found in the directory. Of course, when you first set up LDAP with an empty database, this entry was required. Now it is not, so you should comment it out, as follows:

  
  rootdn          "uid=root,ou=People,o=MyCompany,c=AU"
  # rootpw          secret
  

Your root password should have been obtained from the /etc/passwd or /etc/shadow file and inserted into LDAP. To test this, repeat the above search using the -D flag of ldapsearch to attempt a logon to your LDAP directory, as follows:

ldapsearch -x -D 'uid=root,ou=People,o=MyCompany,c=AU' -W 'uid=root'

ldapsearch will ask you for a password - enter your root password here and, if everything goes according to plan, this should work correctly.

Command Line LDAP Tools

OpenLDAP comes with a range of Unix command line tools for LDAP directory management. These tools are useful as a reference, and since similar tools are provided with many other commercial LDAP systems, it is a good idea to learn these. The tools come with comprehensive man pages; however, it may be best to read some LDAP information on the Internet and/or an LDAP administration guide in order to learn some of the terminology.

The tools are:

These tools mostly take a common set of command line parameters, which include options such as:

Other LDAP tools

There is a wide variety of LDAP tools available either for free or commercially on the Internet. A quick search on freshmeat for LDAP will reveal several. Here are a couple that I quite like.

GQ

GQ is a powerful tool that allows you to look inside your LDAP directory and administer any part of it. GQ allows full control over your LDAP server, including:

GQ allows you to get inside your LDAP directory and see the internal workings of LDAP. GQ is available in source code from the web site, and the source code includes a .spec file so that you can build an RPM file for it if you prefer.

Directory Administrator

Directory Administrator is an application for managing user and group entries in LDAP directory servers. It provides a friendly interface to manage the user's personal details, address book information, and mail routing (for sendmail versions that support mail routing information stored in LDAP.) I find Directory Administrator's interface simple and intuitive, although it is not as powerful as GQ and doesn't go beyond simple user and group management.

The author of Directory Administrator has been promising a new version for some time, and I have a few items on my wish list for it, the main issue being that its main window provides an unsorted and unstructured view of all users in the directory tree. If there are a large number of users in the LDAP directory, this is unsatisfactory (I have around 1500 in one LDAP tree I manage, and it would not be uncommon for some organizations to have tens of thousands). As a basic tool for managing user information on a small Linux network with an LDAP directory, however, Directory Administrator is a great tool.

Red Hat Kickstart and OpenLDAP

Occasionally, I like to build systems using Red Hat's Kickstart tool. The latest version of the Red Hat installation system includes some Kickstart options that can be used to connect a system to an LDAP-based network as a client during system installation time. The options are described in detail in the Red Hat Linux Customization Guide but the main one you need is the "auth" parameter which should read:

auth --enableldap --enableldapauth --ldapserver= --basedn=

Red Hat also includes some information on OpenLDAP in their Red Hat Linux Reference Guide, especially chapter 4. If you are going to use Kerberos authentication with OpenLDAP then you will also need to read chapter 9.

Making OpenLDAP More Secure

The main way in which you can improve the security of OpenLDAP is to include secure sockets layer (SSL) and transport layer security (TLS) mode in your client/server connection. This encrypts all of the LDAP traffic using the SSL protocol. OpenLDAP version 2.0 and later have the capability to run in SSL and TLS mode using the OpenSSL libraries, although you should really be using a version later than 2.0.7 to get this capability working properly.

The main steps you need to follow in getting OpenLDAP to work with SSL are:

Note that there are two different modes of operating OpenLDAP with SSL. These are:

TLS mode is more flexible than SSL mode (since clients or servers that do not understand SSL can continue communicating by ignoring the Start TLS command), but unfortunately many older LDAP servers and clients do not implement this mode and only use SSL mode. Therefore it is preferable, in my opinion, to get your LDAP servers and clients working in both TLS and SSL mode.

Compiling OpenLDAP with OpenSSL

Hopefully, this is the easiest part of the job. If you are using a packaged installation of OpenLDAP provided with, for example, Red Hat or Debian Linux, you will find that this has already been done for you. Once again, make sure that you have a recent version of OpenLDAP (from Red Hat, any version that is 2.0.7-3 or later should be fine.)

If you are compiling OpenLDAP from source, you will simply need to give the following additional flag when running the OpenLDAP configure script:

 
 --with-tls

You also need to make sure that the OpenSSL libraries are present on your system.

Generating SSL keys for OpenLDAP

To use OpenLDAP in TLS or SSL mode you will need to generate a PEM format SSL key. Assuming that you have the OpenSSL package installed (otherwise you would not be doing this,) you will find a Makefile in the /usr/share/ssl/certs directory that contains the appropriate commands to create this key. You can run these with the following simple command:

  cd /usr/share/ssl/certs
  make slapd.pem

During the key-building process, you will be asked for a whole raft of details about your server. This includes the country code, state, organization name, e-mail address, server name, etc. Answer these questions as fully as possible - they are encoded in the PEM file. If you do not have OpenSSL's Makefile, or you cannot run the "make" program for some reason, then you will need to build the PEM file manually. Here is a rough outline of the commands needed to do this:

  /usr/bin/openssl req -newkey rsa:1024 -keyout tempfile1 -nodes -x509 -days 365 -out tempfile2
  cat tempfile1 > ldap.pem
  echo "" >> ldap.pem
  cat tempfile2 >> ldap.pem
  rm -f tempfile1 tempfile2

Note that this command creates an RSA key and then self-signs that key. Self-signed keys are not usual in (for example) HTTPS communications, as the keys are generally signed by a third party known as a Certification Authority. In this case, however, a self-signed key is perfectly okay, as most LDAP clients do not check the signature of the key. Of course, for more advanced users, it would be entirely possible to generate a key and have it signed by an external Certification Authority. It's up to you.

Important note: once you have generated the keys, it is important that they are made 'read only' by the user that is running the LDAP server. For Red Hat Linux, OpenLDAP's server (slapd) runs as an unprivileged user called 'ldap' in a group called 'ldap'. To make this user and group the owner of the key that you have just generated, run the following command:

  chown ldap.ldap slapd.pem

Configuring OpenLDAP to Use SSL Keys

To configure OpenLDAP to use the SSL key you have just generated, you need to modify the /etc/openldap/slapd.conf file. The following lines will need to be added to the file, (they can be anywhere in the file, but I suggest putting them in close to the top, after all of the 'include' statements):

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCertificateFile /usr/share/ssl/certs/slapd.pem
TLSCertificateKeyFile /usr/share/ssl/certs/slapd.pem

Note that there are different allowable values for the TLSCipherSuite line, but the above line is the one that I recommend.

You may also need to modify your LDAP startup script. If you are using Red Hat Linux version 7.0 or later then you won't need to do this. Otherwise, you should locate the line in your startup script (probably /etc/rc.d/init.d/ldap or /etc/init.d/ldap) that contains the line to start slapd, and modify it to look like this:

  slapd -h '"ldap:/// ldaps:///"'

It is the options after "-h" that we are most interested in at this point. You will notice that we are telling the LDAP server to work in both ldap and ldaps (secure) mode. Theoretically, once this is working, you could turn ldap mode off and only use the secure mode, but this is not recommended, as many LDAP clients don't support this secure mode. Note that there may be other options on the line that runs slapd in your startup script: you should leave those intact.

You will now need to restart your LDAP server in order for it to re-read the slapd.conf file:

  /etc/rc.d/init.d/ldap stop
  /etc/rc.d/init.d/ldap start

Testing OpenLDAP and SSL

The first step in testing that your LDAP server is listening in SSL mode is to run the following command:

  netstat -a | grep LISTEN

Looking through the output of that command, you should see that your slapd server is listening on port 389 (ldap) as well as port 636 (ldaps). If SSL mode is not working, then it will be listening on port 389 (ldap) only.

Fortunately, OpenSSL comes with not only a handy key generator, but also an SSL line tester. It works by running the following command:

  openssl s_client -connect localhost:636 -showcerts

Note that I have elected to use the direct connection to LDAP in SSL mode rather than going through TLS - the latter is possible, but somewhat trickier.

If all goes to plan, you should see some output from your LDAP server in the command window, showing information about the certificate, as well as the certificate, session IDs, and master keys, that are in use by the server.

You could now find an LDAP client that supports SSL or TLS mode, such as GQ, turn on the option in the client that enables TLS mode, and see if it works. Voila, you now have a secure LDAP server!

Issues with OpenLDAP

As much as I like free software, I have found a number of issues in the time that I have been using OpenLDAP. For instance, in comparison to some LDAP servers such as iPlanet DS and Novell's NDS, it is quite slow. This is particularly noticeable when both read and write operations are running at the same time.

I have also discovered a number of bugs in the OpenLDAP servers and libraries. These cause several issues, including things like having NSS lookups fail on occasion under load, having SSL transactions terminate unexpectedly, and having directory recovery problems after a system crash. To their credit, the OpenLDAP team maintains an active and publicly accessible bug tracking system where the status of such issues can be tracked and monitored. On occasion I have managed to repair certain bugs by reverting to previous versions of the NSS LDAP libraries.

As alternatives to OpenLDAP, both Novell and iPlanet have (non-free, non-open source) directory servers available on Linux. Both of these work fine with the standard LDAP NSS and PAM libraries, although Novell provide their own PAM and NSS libraries (for a price). Unfortunately, an indepth discussion of Novell's and iPlanet's directory service offerings will have to wait for another time, as it is outside the scope of this article.


Relevant Links

Authentication on Linux Using Open LDAP, Part One
David "Del" Elson, SecurityFocus