October 27, 2005

Advanced Linux LDAP authentication

Author: "American" Dave Kline

In an earlier look at LDAP, we set up a simple LDAP-based authentication system. We configured client machines to retrieve authentication information from a server running OpenLDAP. Now let's go further by enabling encryption and looking at how to make user modifications through LDAP.

If client machines are to authenticate through LDAP, administrators must make sure user changes are reflected within the LDAP server. Most user management utilities on a client system expect to find information in files like /etc/passwd and /etc/group. If such information is only available through LDAP, utilities may complain about unknown users. To make changes in these cases, an administrator must modify the corresponding LDAP entries. While utilities such as phpLDAPadmin can help with this task, you must know what you're doing if you're to use them effectively.

Changing user information in LDAP

Just as creating users and groups with LDAP is often a process of populating and adding Lightweight Directory Interchange Format (LDIF) files, so is the process of making LDAP changes. Suppose you had used the following LDIF file to add a user called "myuser" to LDAP:

	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

Later you decide you would like a directory other than /tmp as myuser's home. Make a file with a name like myuser_change.ldif and add the following:

	dn: cn=Myuser,ou=People,dc=example,dc=org
	homeDirectory: /home/myuser

Notice all that is needed here is the DN (Distinguished Name) and the information we wish to change. Though we only changed the home directory, we could also have changed attributes like the uidNumber or uid. Add your changes with the ldapmodify command:

ldapmodify -x -D "cn=admin,dc=example,dc=org" -W -f myuser_change.ldif

Because the DN is a unique identifier, deleting a DN with the ldapdelete command will remove everything about a user or group:

ldapdelete -x -D "cn=admin,dc=example,dc=org" -W "cn=Myuser,ou=People,dc=example,dc=org"

Encrypting communication between the clients and server

Our LDAP authentication system works well but has a major drawback: nothing is encrypted. Anyone with a packet analyzer and access to the network can read all communication between the client and server, so it's vital to enable LDAP encryption.

OpenLDAP offers two major methods of encrypting communication: LDAP with Transport Layer Security (TLS), and LDAP over Secure Sockets Layer (SSL). LDAP with TLS describes a normal LDAP session where a client requests SSL communication. This type of encryption would occur over the normal LDAP port (389). LDAP over SSL is LDAP being transmitted through an SSL tunnel over port 636. This communication is also called "ldaps://". Both approaches offer the same amount of security. Our example will use the latter approach, LDAP over SSL.

On your machine running OpenLDAP, ensure you have OpenSSL installed. If not, issuing a simple apt-get install openssl will do the trick for Debian systems. If you're using a different Linux distribution, you should be able to find packages for OpenSSL.

Our example will create our own CA (certificate authority), but you can have a third party act as a certificate authority as well. The following commands create our CA:

mkdir /etc/myca
cd /etc/myca
sh /usr/lib/ssl/misc/CA.sh -newca

After running the CA.sh script, you will be prompted to enter a certificate filename or press Enter for a new certificate. In this case, you'll want to press Enter. Then you'll be prompted for a pass phrase; use "cacert," and enter it twice. Then you'll be prompted for the following information:

	Country Name (2 letter code) [AU]: US
	State or Province Name (full name) [Some-State]: Yourstate
	Locality Name (eg, city) []: Your City
	Organization Name (eg, company) [Internet Widgits Pty Ltd]: Exampleorg
	Organizational Unit Name (eg, section) []: Exampleunit
	Common Name (eg, YOUR name) []:	example.org
	Email Address []: ldapadmin@example.org

Enter the correct information for your company or organization.

The Common Name, or "CN" for short, must be a fully qualified domain name pointing to your server. Incorrect CN values will completely break encryption, and there exist countless examples of this error on mailing lists and forums throughout the Internet.

Next we will create a certificate request and private key. Perform the following:

openssl req -new -nodes -keyout newreq.pem -out newreq.pem

You will then be prompted for the following information:

	Country Name (2 letter code) [AU]: US
	State or Province Name (full name) [Some-State]: Yourstate
	Locality Name (eg, city) []: Your City
	Organization Name (eg, company) [Internet Widgits Pty Ltd]: Exampleorg
	Organizational Unit Name (eg, section) []: Exampleunit
	Common Name (eg, YOUR name) []: example.org
	Email Address []: ldapadmin@example.org

Enter the appropriate information for your certificate. You will also be prompted for a challenge password and optional company name, which you can leave blank. OpenLDAP does not support password-protected private keys.

Notice the questions are roughly the same as the ones we saw before, and be aware that the same domain name warnings apply to the CN value here. The CA we created earlier will now sign our certificate request, and we will move the resulting files into place:

sh /usr/lib/ssl/misc/CA.sh -sign

Enter your CA password and answer "y" to the two questions, then copy the certificates to /etc/ldap:


cp demoCA/cacert.pem /etc/ldap/cacert.pem
cp newcert.pem /etc/ldap/servercrt.pem
cp newreq.pem /etc/ldap/serverkey.pem
chmod 600 /etc/ldap/serverkey.pem

We now have all the files we need to enable LDAP encryption. Edit the LDAP daemon's configuration file, /etc/ldap/slapd.conf, and add the following values:

	TLSCACertificateFile /etc/ldap/cacert.pem
	TLSCertificateFile /etc/ldap/servercrt.pem
	TLSCertificateKeyFile /etc/ldap/serverkey.pem
	loglevel	256

This tells slapd where to find our certificates and key, and we added an option to enable more verbose logging. Next we need to start an LDAP daemon that listens on port 636. To test your setup and get immediate feedback, start a debugging slapd. Ensure no other instances of slapd are running and issue the following command as root:

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

This command starts a normal slapd running on port 389 and an SSL-only slapd running on port 636. If you messed up any of the above steps, slapd will refuse to start with a sometimes less-than-helpful error message.

Client encryption configuration

Once the server is running smoothly and listening on port 636, we can configure a client. While on the client machine, open /etc/ldap/ldap.conf and make the following changes:

	BASE    dc=example,dc=org
	URI     ldaps://example.org
	TLS_REQCERT allow

We changed the URI stanza to consult ldaps:// instead of the unencrypted ldap://. The TLS_REQCERT stanza allows the client to request the server's certificate, alleviating the need to place a copy of the certificate on each client machine.

Next we need to configure the client's authentication files to use our newly minted secure connection. First up is /etc/libnss-ldap.conf. Comment out any "host" lines and ensure only the following exists:

	base dc=example,dc=org
	uri ldaps://example.org
	ldap_version 3

Notice the change to "ldaps://" in the above lines. Next we will edit /etc/pam_ldap.conf and change it to use SSL. Open /etc/pam_ldap.conf and ensure the following exists:

	base dc=example,dc=org
	uri ldaps://example.org/
	ldap_version 3
	rootbinddn cn=admin,dc=example,dc=org
	pam_password exop

Note the mention here of ldaps://. Again, any "host" stanzas or any lines referring to an IP address rather than the CN of the server certificate will break your setup. SSL is extremely picky in this regard.

Since we have made some serious changes, we now need to restart the name service cache daemon (nscd). Issue the command:

/etc/init.d/nscd restart

Because we made the server run a slapd that listens to both insecure and secure connections, we can test normal and encrypted LDAP. First, test a normal LDAP connection:

ldapsearch -x -b dc=example,dc=org -H 'ldap://example.org'

And to test LDAP over SSL:

ldapsearch -x -b dc=example,dc=org -H 'ldaps://example.org'

If the second ldapsearch command worked, client logins will be encrypted. You can verify this by looking at the output on the server terminal you started slapd with. Log in as an LDAP user on your client machine. Congratulations, you've securely authenticated over LDAP.

To make LDAP over SSL the only option on your network, open /etc/default/slapd on the OpenLDAP server and change the SLAPD_SERVICES line to the following:

	SLAPD_SERVICES="ldaps:///"

Linux and LDAP play together nicely, and now we know how to make LDAP more flexible and secure. Making LDAP work with SSL is a sometimes tedious process that grinds to a halt if LDAP is not configured correctly. But the alternative of exchanging unencrypted user information is not an option. With what you now know, you should be able to make the connections work.

Click Here!