September 21, 2005

Linux LDAP authentication

Author: "American" Dave Kline

When you have to administer a network of many machines, you quickly find out how much duplication of effort is involved with normal administrative tasks. Routine operations like changing passwords, canceling accounts, and modifying groups become time-consuming if repeated on many individual machines. Centralizing user and authentication information can solve these issues. The former king of centralized authentication systems was NIS, or Network Information System. NIS is a simple and well-supported technology, but it's also insecure. LDAP, short for Lightweight Directory Access Protocol, is now the preferred way of managing centralized user accounts.

LDAP's purpose is to describe how directory data should be presented and how it should travel across networks. LDAP servers typically allow information to be read very quickly at the expense of writing. The basic functionality of an LDAP server is similar to that of a database, but more like a database designed for fast reads of relatively static information. Passwords and groups are good examples of relatively static information that needs to be read quickly. OpenLDAP is a free software implementation of the LDAP protocol. Installing OpenLDAP gives you everything needed to present and store data through LDAP.

Learning LDAP can be a frustrating experience. LDAP is complicated, and centralized authentication is only one of its many legitimate uses. As a result, the task of making Linux machines consult an LDAP server for authentication is a black art. Documentation tends to be spotty and confusing. But learning about LDAP authentication, despite its difficulty, is worth the time and effort. LDAP can provide a scalable and secure approach to network management.

Setting up an LDAP-based network

We will setup a simple LDAP-based authentication system. Our example will use two Debian 3.1 (Sarge) machines, one acting as client and one as a server. To make the process even simpler, use User Mode Linux to create virtual Linux boxes that you can break and abuse to your heart's content. For simplicity, we will not be encrypting communication and will stick to basic examples.

First we will cover the server configuration. On your "server" Debian system, issue the following command:

    apt-get install slapd ldap-utils

This will install OpenLDAP and related utilities. Debian will prompt you for slapd (the name of the OpenLDAP daemon) configuration values. The "Admin password" will be the password you want to use when adding or deleting from LDAP and for certain client tasks. "DNS domain name" is important and must be a domain name resolvable to your LDAP server.

    Omit OpenLDAP server configuration? no
    DNS domain name: example.org
    Name of your organization: example_organization
    Admin password: ldap
    Database backend to use: BDB
    Do you want your database to be removed when slapd is purged? no
    Allow LDAPv2 protocol? no

With slapd configured, you can test if your installation is working correctly. After running the following command, you should see LDAP information:

    ldapsearch -x -b dc=example,dc=org

We now have a functioning LDAP server, but it is of no use until we populate it with basic information. Make a file called base.ldif and populate it with the following values:

    dn: ou=People,dc=example,dc=org
    ou: People
    objectClass: top
    objectClass: organizationalUnit

    dn: ou=Group,dc=example,dc=org
    ou: Group
    objectClass: top
    objectClass: organizationalUnit

Save the file and add the data in it to the running LDAP server with the following command:

    ldapadd -x -D "cn=admin,dc=example,dc=org" -W -f base.ldif

You will be prompted for the password you chose during the configuration of slapd. If your password was correct and your ldif file was in good order, you will see a line beginning with "adding new entry."

Next we will add a group that our LDAP users will be a part of. Add the following values to a file called group.ldap:

    dn: cn=ldapusers,ou=Group,dc=example,dc=org
    objectClass: posixGroup
    objectClass: top
    cn: ldapusers
    userPassword: {crypt}x
    gidNumber: 9000

Though in my example I chose "ldapusers," you can change this value to anything you like. You can also choose any gidNumber you like. Once you have a group.ldif you like, add it the same way as you added the base.ldif:

    ldapadd -x -D "cn=admin,dc=example,dc=org" -W -f group.ldif

The final server step in this example is adding an LDAP user. Create an ldif file called myuser.ldif with the following values:

    dn: cn=Myuser,ou=People,dc=example,dc=org
    cn: Myuser
    objectClass: posixAccount
    objectClass: shadowAccount
    objectClass: inetOrgPerson
    sn: User
    uid: myuser
    uidNumber: 1025
    gidNumber: 9000
    homeDirectory: /tmp

This will make a user called "myuser" with a uid of 1025 who lives in /tmp and is a member of the LDAP-only group "ldapusers." This user doesn't have a password yet, but we will save that task for the client machine.

Client configuration

The client steps provided here will work for any machine you wish to make authenticate via LDAP. Make sure your client can communicate with the server and that pinging "example.org" from the client returns the correct IP address of the server.

On the client machine, install OpenLDAP and PAM (Pluggable Authentication Modules) utilities, as well as NSCD, the Name Service Cache Daemon, with the command:

    apt-get install ldap-utils libpam-ldap libnss-ldap nscd

One of the first packages Debian asks you to configure is libnss-ldap. Important values for your particular setup are the "LDAP server host" and the "distinguished name," or DN for short. The server host will be the IP address of the LDAP server, while the DN will be the server's host name. Also note the DN should be in the form of "dc=example,dc=org". The following is a typical libnss-ldap configuration:

    LDAP Server host: 192.168.1.30
    The distinguished name of the search base: dc=example,dc=org
    LDAP version to use: 3
    database requires login? no
    make configuration readable/writeable by owner only? yes

The values for libpam-ldap will be similar to those of libnss-ldap. Note that the "Root login password" is the same password you chose during the server's slapd configuration. Enter the following when prompted:

    The distinguished name of the search base: dc=example,dc=org
    Make local root Database admin: yes
    Database requires logging in: no
    Root login account: cn=admin,dc=example,dc=org
    Root login password: ldap
    Local crypt to use when changing passwords: exop

Next, we need to tell the client's underlying authentication system to use LDAP to look for users. The first file to edit is /etc/nsswitch.conf. Make sure to add "ldap" to the passwd, group, and shadow lines:

    passwd:     ldap compat
    group:      ldap compat
    shadow:     ldap compat

We need to configure the client's PAM software to check LDAP for user authentication. There are three files to edit under /etc/pam.d: common-account, common-auth, and common-password. First, /etc/pam.d/common-account should contain the following:

    account sufficient    pam_ldap.so
    account required    pam_unix.so try_first_pass

/etc/pam.d/common-auth should contain:

    auth sufficient        pam_ldap.so
    auth required        pam_unix.so nullok_secure try_first_pass

Finally, /etc/pam.d/common-password should contain:

    password sufficient    pam_ldap.so
    password required    pam_unix.so nullok obscure min=4 max=8 md5 try_first_pass

The changes we made to /etc/nsswitch.conf and the PAM configuration files allow the client to check LDAP before allowing a user on the system, but will also fall back on local authentication methods should LDAP fail or not have information about a given user.

The last file to edit is /etc/ldap/ldap.conf. Adding information about our LDAP server here makes issuing LDAP commands on the client easier. Add lines for your setup similar to the following:

    BASE  dc=example,dc=org
    URI   ldap://192.168.1.30

At this point, you should be able to change the password of the user you created earlier. First restart nscd, then change the ldap user's password:

    /etc/init.d/nscd restart
    password myuser

After changing the password, login as myuser on the client machine. Congratulations, you've just authenticated over LDAP.

Implementing LDAP on Linux isn't exactly difficult once you know the right changes to make. For reasons I cannot explain, however, most information I have read about LDAP seems to convey just how much trouble the author had implementing it. Finding the right changes in the first place is usually the most challenging part. Linux distributions could automate this process a little more; having front ends to server and client configuration would take Linux far in the LDAP world.