LDAP

This is an update of the LDAP part of my diskless client project, which is documented on my old site at http://www.xs4all.nl/~rjb/ . This is work in progress (updated 27042009)...

(to be merged for 9.04)

$ dpkg-reconfigure slapd
Omit OpenLDAP server configuration? No
DNS domain name: your_domain.com
Organization name: Your_organization
Database backend to use: HDB
Do you want the database to be removed when slapd is purged: Yes
Move old database: Yes
Administrator password:
Allow LDAPv2 protocol: No

/etc/phpldapadmin/config.php:

:1,$ s/dc=example,dc=com/dc=your_domain,dc=com/g

/etc/default/slapd:

SLAPD_SERVICES="ldaps:/// ldap://127.0.0.1/"
$ ldapmodify -x -D cn=admin,cn=config -W
(password)
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/slapd-cert.pem

dn: cn=config
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/slapd-cert.pem

dn: cn=config
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/slapd-key.pem

^D

(end of merge)

Reference: https://help.ubuntu.com/9.04/serverguide/C/openldap-server.html

Installing the software

Let's install the software:

aptitude install slapd ldap-utils libpam-ldap libnss-ldap migrationtools phpldapadmin

In case you're wondering what all of this does, simply said:

  • slapd is the LDAP server
  • ldap-utils contains LDAP clients, among other things.
  • libpam-ldap contains a plugin which is used for validating logins, changing passwords etc... It uses LDAP, so it is in fact also an LDAP client. Installing this will also install ldap-auth-config.
  • libnss-ldap, another LDAP client, is part of NSS, which is responsible for deciding where to lookup data like passwd, group, shadow, hosts, networks etc. which formerly only was available in /etc. Now, the user can specify in /etc/nsswitch.conf where to look. He/she can specify for userinfo to look in /etc/passwd first, then LDAP. This will have an effect on the output of, for example an ls -l command.
  • migrationtools contains scripts which can copy and convert data from files in /etc, like /etc/passwd to the LDAP server.
  • phpldapadmin is a webinterface for LDAP.

When installing slapd, the system will ask what password to use for the administrator. Just invent one and remember it. When installing ldap-auth-config, the system will ask for URI of the LDAP server, which in our case will look something like this:

ldaps://server_hostname/

Replace server_hostname by your server's hostname.

Please note that in Ubuntu 8.04 or later a hostname is required; an IP address will not work anymore for secure connections.

Using ldaps instead of ldap or ldapi, enables us to use encrypted connections over the network. So if you want to use an LDAP server on machine A for authenticating users on machine B, you can do that without sending plain-text passwords over the network.

It will also ask for the distinguished name of the search base. The what? :-) Let's say it's a bit like the search domain in DNS, which in our case would be mydomain.com, in LDAP written as:

dc=mydomain,dc=com

You will have to replace mydomain and com to suit your needs, but you need to keep the rest: it's the LDAP way of specifying things. Note that this has no relationship with DNS, so you don't need to keep the LDAP dc's in sync with FQDN's. You can just invent an other name for your LDAP setup.

Answer No when asked if you would like to create a local root database, and No to the option "Database requires logging in".

Running the LDAP server: slapd

(obsolete part to be removed)

The configuration file for slapd is /etc/ldap/slapd.conf. Edit it (only relevant lines shown):

include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema

pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd/slapd.args
loglevel        none
modulepath      /usr/lib/ldap
moduleload      back_hdb
sizelimit       500
tool-threads    1
backend         hdb

database        config
rootdn          "cn=admin,cn=config"
rootpw          {MD5}xxxxxxxxxxxxxxxxxxxxxxx

database        hdb
suffix          "dc=mydomain,dc=com"
directory       "/var/lib/ldap"
dbconfig        set_cachesize 0 2097152 0
dbconfig        set_lk_max_objects 1500
dbconfig        set_lk_max_locks 1500
dbconfig        set_lk_max_lockers 1500
index           objectClass eq
lastmod         on
checkpoint      512 30
password-hash   {md5}
TLSCertificateFile     /etc/ldap/slapd-cert.pem
TLSCertificateKeyFile  /etc/ldap/slapd-key.pem
TLSCACertificateFile   /etc/ldap/slapd-cert.pem
rootdn          "cn=Manager,dc=mydomain,dc=com"
rootpw          {MD5}xxxxxxxxxxxxxxxxxxxxxxxx

access to attrs=userPassword
        by dn="uid=root,ou=People,dc=mydomain,dc=com" write
        by anonymous auth
        by self write
        by * none

access to *
        by dn="uid=root,ou=People,dc=mydomain,dc=com" write
        by * read

Note that the 3rd block is for converting the (obsolete) slapd.conf into the slapd.d directory structure.

The MD5 hash above needs to be replaced by the hash returned by the following command:

slappasswd -h {md5}

When asked for a password, you need to type the new password for the LDAP Manager, which is like the "root" user in Unix. Just invent a password and remember it.

When you are finished editing /etc/ldap/slapd.conf it is time to convert it to the slapd.d directory structure (Ubuntu / Kubuntu >= 8.10 only). Run these commands:

slaptest -f slapd.conf -F slapd.d
chown -R openldap:openldap slapd.d
chmod 600 slapd.conf
mv -i slapd.conf slapd.conf.bak

The last command will prevent slapd.conf from being used.

(end of obsolete part)

Configure slapd:

$ dpkg-reconfigure slapd
Omit OpenLDAP server configuration? No
DNS domain name: your_domain.com
Organization name: Your_organization
Database backend to use: HDB
Do you want the database to be removed when slapd is purged: Yes
Move old database: Yes
Administrator password:
Allow LDAPv2 protocol: No

The DNS domain name will be converted to a "distinguished name of the search base" mentioned earlier. Earlier we specified it for the clients, now we do the same for the server.

Create a self-signed certificate and key pair. Type:

cd /etc/ldap
openssl req -new -x509 -nodes \
   -out slapd-cert.pem -keyout slapd-key.pem -days 999999
chmod 644 slapd-cert.pem
chown openldap:openldap slapd-key.pem
chmod 400 slapd-key.pem

When asked for CommonName type the hostname of your LDAP-server.

Please note that in Ubuntu 8.04 or later a hostname is required; an IP address will not work anymore for secure connections.

Tell slapd about the certificate:

$ ldapmodify -x -D cn=admin,cn=config -W
(password)
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/slapd-cert.pem

dn: cn=config
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/slapd-cert.pem

dn: cn=config
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/slapd-key.pem

Hit Ctrl-D to end the input.

Edit /etc/default/slapd.

SLAPD_SERVICES="ldaps:/// ldap://127.0.0.1/"

Type:

/etc/init.d/slapd restart

If this fails, try to debug it using:

slapd -d -1 -g openldap -u openldap -F /etc/ldap/slapd.d

If you see something like:

main: TLS init def ctx failed: -64

check if the TLS paths in slapd.conf match the locations of the SSL certificate and key. Also check the permissions of these files.

(probably obsolete; it may have been merged in /etc/ldap.conf)

The configuration file for the LDAP clients in ldap-utils is /etc/ldap/ldap.conf. Edit it. It should look like this:

BASE            dc=mydomain,dc=com
URI             ldaps://your_hostname:636/
TLS_REQCERT     allow

(end of obsolete part)

Test the LDAP server:

ldapsearch -D "cn=admin,dc=mydomain,dc=com" -W -x
ldapsearch -H 'ldaps://your_hostname/' -D "cn=admin,dc=mydomain,dc=com" -W -x
ldapsearch -H 'ldap://127.0.0.1/' -D "cn=admin,dc=mydomain,dc=com" -W -x
ldapsearch -W -x

You need to type the LDAP manager password for the first 3 commands. At the last command just type enter: here we test the anonymous login. In Ubuntu 8.04 you really need the hostname in the second command instead of the IP address. If you see something like:

result: 32 No such object

that's ok.

If you see something like:

ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

check if slapd is running, and if not, try to debug it using the command mentioned earlier (calling slapd directly, and using option -d -1). Also check out /etc/defaults/slapd, in particular the SLAPD_SERVICES option. It should look similar as the example mentioned earlier. No hash sign (#) should appear at the beginning of that line. If you are using Jaunty (9.04), there may be a bug which prevents the 2nd command (using ldaps) from working.

Migrating the files in /etc to LDAP

Next task is to convert /etc/passwd, /etc/shadow and /etc/group to LDAP. Go to /usr/share/migrationtools and edit migrate_common.ph. In Ubuntu 8.04 this file has been moved to /usr/share/perl5.

# $DEFAULT_MAIL_DOMAIN = "padl.com";
$DEFAULT_BASE = "dc=mydomain,dc=com";
# $DEFAULT_MAIL_HOST = "mail.padl.com";
$EXTENDED_SCHEMA = 1;

Type:

./migrate_base.pl > /tmp/base.ldif
./migrate_passwd.pl /etc/passwd /tmp/passwd.ldif
./migrate_group.pl /etc/group /tmp/group.ldif
ldapadd -D "cn=Manager,dc=mydomain,dc=com" -W -x -f /tmp/base.ldif
ldapadd -D "cn=Manager,dc=mydomain,dc=com" -W -x -f /tmp/passwd.ldif
ldapadd -D "cn=Manager,dc=mydomain,dc=com" -W -x -f /tmp/group.ldif
rm /tmp/base.ldif /tmp/passwd.ldif /tmp/group.ldif

Note that ldapadd has an option -c to continue after errors (instead of aborting).

A web GUI for LDAP: phpldapadmin

Edit the following lines in /usr/share/phpldapadmin/config/config.php:

$config->custom->session['blowfish'] = 'some random string';
$ldapservers->SetValue($i,'server','name','My LDAP Server');
$ldapservers->SetValue($i,'server','host','ldap://127.0.0.1/');
$ldapservers->SetValue($i,'server','port','389');
$ldapservers->SetValue($i,'server','base',array('dc=mydomain,dc=com'));
$ldapservers->SetValue($i,'server','auth_type','session');
$ldapservers->SetValue($i,'login','dn','');
$ldapservers->SetValue($i,'login','pass','');
$ldapservers->SetValue($i,'server','tls',false);
$ldapservers->SetValue($i,'server','low_bandwidth',false);
$ldapservers->SetValue($i,'appearance','password_hash','md5');
$ldapservers->SetValue($i,'login','attr','dn');

Replace some random string to something really random :-) Keep the IP 127.0.0.1 as-is (localhost).

Assuming you already have Apache, PHP and a webbrowser installed, startup a webbrowser and go to https://localhost/phpldapadmin/. Login as cn=Manager,dc=mydomain,dc=com. You can also login anonymously, but then you cannot see the password hashes and you cannot change anything.

This is a perfect moment to cleanup the LDAP. Remove everything, except Group and People.

Configuring the system to use LDAP

Edit /etc/ldap.conf:

  • Remove the 1st line containing ###DEBCONF### to prevent the system from overwriting this file
  • Comment out these lines, by placing a # at the beginning of each line:
    host 192.168.1.2
    base dc=mydomain,dc=com
    
  • Add this line:
    uri ldaps://your_hostname/
    
  • Uncomment the following line, by removing the #:
    #pam_password exop
    
    and make sure other pam_password lines start with a #

These changes are needed for security by using ldaps:// (with encryption) instead of ldap:// (without encryption).

Edit /etc/nsswitch.conf, changing these 3 lines:

passwd:         files ldap
group:          files ldap
shadow:         files ldap

Check if LDAP works with NSS:

getent passwd | grep 0:0

You should see 2 identical lines, one coming from /etc and one coming from LDAP.

Setting up PAM to work with LDAP

Edit /etc/pam.d/common-auth:

auth     sufficient   pam_unix.so nullok_secure
auth     requisite    pam_ldap.so use_first_pass

Edit /etc/pam.d/common-account:

account   sufficient   pam_unix.so
account   required     pam_ldap.so

Edit /etc/pam.d/common-password:

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

Edit /etc/pam.d/common-session:

session   required   pam_env.so readenv=1
session   required   pam_unix.so
session   optional   pam_ldap.so
session   required   pam_mkhomedir.so skel=/etc/skel/ umask=077
session   optional   pam_foreground.so

The first line has nothing to do with LDAP. It's there to read /etc/environment even when logging in using KDM. The home directory will be created automatically if it does not exist.

In order to turn off the caching of hosts, edit this line in /etc/nscd.conf:

enable-cache            hosts           no

Check if LDAP works with PAM. When you change a password, the corresponding password hash in the LDAP should also change, and you should be able to use this new password anywhere.

Recovering from a crash

If you cannot start slapd after a crash, you may be able to recover the database by installing the db4.2-util package and running the following command:

db4.2_recover -c -h -v /var/lib/ldap

After that, slapd should be able to run again.

Diskless client hangs during boot when using LDAP

If the client hangs at: Starting kernel log, then set the bind_policy to soft in /etc/ldap.conf.