Ldap Authentication on Debian

Bart Trojanowski

Thu Sep 27 08:12:29 EDT 2007


This document contains a HOWTO for setting up LDAP authentication on Debian.


1. About...

1.1. Warning!

This document probably contains errors and security flaws.  Use at your own risk.  I will gladly accept corrections. :)

1.2. Introduction

I run a small server of about a dozen users and used to maintain my user configuration in /etc/ files.  Over the last year, I have been been slowly increasing the complexity of user maintenance by adding a few vservers on this machine -- some for my exclussive use and some for everyone to use.

As I begin to write this I have 10 Linux installs, over 5 actual boxes (rest are vservers) which share files by NFS.  One of the drawbacks of NFS is that it relies on UIDs and GIDs to be the same to maximize the user experiance. :)  Maintaing users via /etc/passwd, /etc/groups, and /etc/shadow files was getting tiresome.

I have considered using NIS or NIS+ to distribute the user authentication information, but was warned that it sucked... so I never pursued it. The thing that seems to be in these days is LDAP... hey, even MS is using it so it must be good.

I have read a few pages on the web, and skimmed through others -- see bottom of this page for links -- to produce the following step-by-step guide of how I installed LDAP on my Debian based Linux network.  I found that the other documentation on the net lacked sufficient examples and detail in places.  Whereever possible I have provided snippets of my configuration files ... note that I am not an expert so I my examples could be competely wrong.

1.3. Acknowledgements

Special thanks go to the following people for writing up enough information to let me, an LDAP nubee, install my own LDAP authentication database and tell you about it.


2. Server

Note that this section only describes how to configure the server.

A server can be a client, but I have had mixed results.  In particular my /sbin/init tried to resolve some file's ownership and crashed (it only did this with the ldap daemon not present).  Being init there was little I could do to fix it.  In the end I decided to have the server not be a client.

2.1. Deciding on the "Base DN"

LDAP entries are organized in a tree.  A Distinguished Name (DN) is a unique name given to a node.  The Base DN is the name given to the root node of the tree (for non comp-sci folk: that is the top of the tree).

It is recommended, in LDAP literature, to set your Base DN to "dc=example,dc=net" if your domain is example.net.  I prefer to use "dc=example" to save on typing.

2.2. Installing components

You will need the following packages

On Debian this is pretty easy.

apt-get install slapd ldap-utils migrationtools

During the install you will be asked about the system.  You have chosen your Base DN, use that when answering these questions.  Here are a few pointers:

  1. The slapd debconf script will actually ask for the domain, so if your Base DN is "dc=example,dc=net" you will say example.net, but like I suggested above you can ommit the last word.  
  2. Use BDB database unless you know better... I don't.  
  3. Lastly, none of the tools described on this page use LDAPv2, you can disable it.

I recommended that you stop the LDAP database before proceeding.  According to what I read making any soft of changes while things are running is bad. So run this first:

/etc/init.d/slapd stop

You should not turn on the server until you are done this section.

2.3. Configuring LDAP server (slapd)

2.3.1. User and Group

Debian installs slapd as a daemon that runs as root.  But, as suggested by Markus Amersdorfer, we will create a user that will run the database. It's always a good idea to create a user to run a daemon whenever possible.

Note, that the benefits are demished if you chose to authenticate root via ldap; once the perpetrator gets a hold of your database they can do whatever they want with it, like change the root password.

The entry for this user, let's call her ldap, has to be in /etc/passwd since the entry must be available before slapd starts.

adduser --system --group ldap

Then change ownership of all slapd accessed files to this new user and group.

chown -R ldap.ldap /etc/ldap /var/run/slapd/ /var/lib/ldap /var/spool/slurpd
chmod 770 /etc/ldap
find /etc/ldap -type f -exec chmod 640 {} \;
find /etc/ldap -type d -exec chmod 771 {} \;
chmod 644 /etc/ldap/ldap.conf
chmod 750 /var/lib/ldap
rm /var/lib/ldap/* /var/spool/slurpd/*

Now you must edit the startup default so that slapd starts as the new user and group as we intended.  More specifically make sure that your /etc/default/slapd has the following lines:


2.3.2. LDAP daemon configuration

First backup the debconf config file so you have something to go back to.

cd /etc/ldap/
cp -p slapd.conf slapd.conf-deb_orig
chmod +w slapd.conf

Now, fire up your favorite editor and update /etc/ldap/slapd.conf ...

access to attr=userPassword
                        by dn="cn=admin,dc=example" write
                        by anonymous auth
                        by self write
                        by * none

access to attrs=loginShell,shadowLastChange
                        by dn="cn=admin,dc=example" write
                        by self write
                        by * read

access to dn.base="" by * read

access to *
                        by dn="cn=admin,dc=example" write
                        by dn="cn=nss,dc=example" read
                        by * auth

I also enabled loglevel (to an obscene 256) to see what was going on... obviously you will want to diable that once things are working.

2.3.3. Populate the database

There are two ways you can do this:

  1. start off clean, in which case you will still need the default records
  2. use migrationtools to convert your /etc files to the LDAP database

NOTE: important that your slapd be stopped before you proceed with either.

Take your pick... Minimal dataset

Get my example-base.ldif file, edit it and update your Base DN and update the userPassword entries for the admin and nss users.  To generate a password that slapd can use run the following (for each password you want to generate):

slappasswd -h {MD5}
Take the output of this command and set it in the userPassword field

Finally, use the following line to import it into your database:

slapadd -l example-base.ldif

NOTE: slapadd is in /usr/sbin

To add groups and users follow a similar procedure by getting these two files:

Edit (remember to set the password for the user) and add to the LDAP database. /etc Migration

TODO: expansion intended

Read over the migrationtools help files, edit the /usr/share/migrationtools/migrate_common.ph file, and run

cd /usr/share/migrationtools

TIP: If you just want to see what would happen, add an exit 0 after the echo "Preparing LDAP database..." line, at the end of the migrate_all_offline.sh file.  You can then examine what would be added to the database by looking at the file that the script generated in /tmp/nis.$$.ldif.  Be carefull with this file, it's likely going to be world legible and contains the MD5 sums of all the passwords that can be used in a brute-force attack.

2.4. Testing

Now we will start the daemon and see some data.

2.4.1. Starting

Can you start the daemon?

/etc/init.d/slapd start
pidof slapd

2.4.2. Cold test

Using the slapd commands requires that the database be offline, so we shut it down before attempting this test...

/etc/init.d/slapd stop
/etc/init.d/slapd start

2.4.3. Hot test

If you installed ldap-utils you can now run the following test.  Note that we did not configure ldap-utils so you have to specify a whack of extra options, that will not be required once you perform the steps in the next chapter.

 ldapsearch -x -W -b 'dc=example' -D 'cn=admin,dc=example' -H 'ldap://' 'objectclass=*'

If your /etc/ldap/ldap.conf is properly configured, you can attempt:

 ldapsearch -x -W -D 'cn=admin,dc=example' 'objectClass=*'

Both will ask you for the admin password.  You should also repeat this test for the nss user.  If you imported your database using migrationtools you should also be able to retrieve any user's record by using that user's credentials (ie: -D 'cn=thatuser,dc=example').


3. Client

3.1. Installing components

You will need the following packages on each of your clients

On Debian this is pretty easy.

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

During the install you will be asked about the system.  You have chosen your Base DN, use that when answering these questions.

3.2. LDAP utils

The ldap-utils package allows you to querry and alter the ldap database remotely.  I don't think that it's actually used by of the other tools, but you will need it for testing.

3.2.1. Configure LDAP utils

The ldap-utils is configured by the /etc/ldap/ldap.conf file.  Your's should read something along these lines:

URI ldap://ldap.example.net
BASE dc=example

pam_filter objectclass=posixAccount
pam_login_attribute uid
pam_crypt local

Make sure that URI points to your server.  Keep in mind that URI must resolve before you can authenticate via LDAP, to get around that dependency you can use an IP address instead of a hostname.  More importantly, if you use LDAP for distributing /etc/hosts entries then you should definately use an IP address for URI.

3.2.2. Test LDAP utils

You should now be able to querry the ldap database on your client machine by running this:

 ldapsearch -x -W -D 'cn=admin,dc=example' 'objectclass=*'

You should be able to see the same objects you saw when you ran this query on the server.

3.3. NSS

The Name Service Switch provides a facility for accessing entries usually found in /etc/passwd, /etc/group, /etc/host and several others from an alternate source.  These sources can be the flat files, local database files, NIS, NIS+, and of course LDAP.

3.3.1. Configure NSS

The /etc/libnss-ldap.conf file should contain something like this:

base dc=example

ldap_version 3
binddn cn=nss,dc=example
bindpw SeeKriT

nss_base_passwd ou=People,dc=example
nss_base_group ou=Group,dc=example

The first block describes how to connect to the LDAP database... use an IP as it's less likely spoofed and a more reliable.  

The next section defines the credentials we use to access the database for looking up information. Recall the server was configured to allows reads to only authenticated users.  The nss user was created for this purpose.  The unfortunate part is that this authentication requies a password to be stored in the clear... replace the SeeKriT above with the password set for the nss account on the server.  

Finally, the last section defines the organization of passwd and group entries in our database.  You can define a lot of mappings not just the two I used; see the debian provided example for more information.

There are a few things you need to change in /etc/nsswitch.conf.  The lines passwd, group, and shadow lines should look like this:

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

It means that for the three types of entries, NSS will try LDAP first and if that fails it will use the the default files.

3.3.2. Test NSS

Make sure you have an account defined in ldap and not in the passwd and group files on the client machine.  You can now querry the NSS interface for this information:

getent passwd username

You can also crate a file and change ownership to that user.

touch /tmp/foo
chown 1000.100 /tmp/foo
ls -l /tmp/foo

The system should display the name and group ower of the file (not 1000 and 100).

3.4. nscd

The nscd package caches queries from NSS to the ldap server.  This allows for tolerance of minor network outages, but more importantly it means that your ldap server does not have to be querried for everything.

3.4.1. Configure nscd

There is very little to configure here.  The default configuration that comes with debian is sane enough to use.  You may want to make sure that you have passwd and group caching enabled, while host lookups disabled. There are some insecurities with cachine host file lookups.

3.4.2. Test nscd

Repeat the NSS tests from above with nscd running.

3.5. PAM

The Pluggable Authentication Module allows for a flexible way of validating a user that is attempting access to your system.  Authentication data can come from various places including LDAP.

3.5.1. Configure PAM

The /etc/pam_ldap.conf file should contain something like this:

base dc=example

ldap_version 3
binddn cn=nss,dc=example
bindpw SeeKriT

pam_password exop
pam_filter |(host=myhostname)(host=\*)

#rootbinddn cn=admin,dc=example
# ^^^ password for rootbinddn is in /etc/ldap.secret (mode 600)

rootbinddn tells the system what credentials to use when the password (or other fields) are being modified by the priveledged account (root). Any user cna update their own accout, but you can also configure root to be able to update any account.  If you set rootbinddn properly and provide the password in /etc/ldap.secret,  then the root user on the client machien will be able to update arbitrary accoutns.

Note the similarities between this file and the NSS configuration file. The only real difference is in the last three lines.   pam_password states that OpenLDAP will do the password hashing (exop == extended operation).

pam_filter is a rule that filters which users can loginto this system. In the above, any user with the host line set to myhostname (you would want to change myhostname with the name of the client machine) or a star.

Now PAM is configured to use ldap for authentication.  But before you can actually use it, you need to tell PAM what modules should use it.  The files that set up this part of the configuration are located in /etc/pam.d/.  There is one for each program that wants to use PAM for authentication.  This is a bit different on Debian/Woody and Debian/Sarge.

Sarge's PAM contains shared include files, so modification need only be done on /etc/pam.d/common-* files.  Have a look at the changes I made on my Sarge install ( sarge-pam.d.patch ).

3.5.2. Test PAM

You should be able to login to the system with the credentials from OpenLDAP. You may need to restart the services that talk to PAM.  My first test usually involves ssh.

/etc/init.d/ssh restart
ssh username@localhost

3.6. TBD...

More to be added.


4. Tools

4.1. gq

4.2. cpu

4.3. directory_administrator


5. Links...

  1. LDAP Authentication for Linux
    • This is a pretty nice Debian specific document; it has pretty complete examples on how to setup the client that is authenticated via LDAP.
  2. Using OpenLDAP
    • This document comes from the same people as the above and describes the server side of LDAP authentication.  Also sweet and simple.
  3. Using OpenLDAP on Debian Woody to serve Linux and Samba users
    • This if full of good stuff.  Very detailed and full of step by step examples.  I used much of this, except that I use MD5 not Crypt.
  4. Using LDAP for name resolution
    • Debian specific, tries to use debconf to configure the LDAP server & client.  It's pretty good, but this method did not work for me. More specifically, I used MD5 so I had to modify the /etc/{libnss-,pam_}ldap.conf files to include the specific schema overrides.

6. Thanks...

  1. to Gustavo Mendes de Carvalho for catching several type-o's


Bart Trojanowski

This document was generated using AFT v5.096