Distroname and release: Debian Wheezy

OpenLDAP Server, authenticate linux users

OpenLDAP is a very big topic, and very abstract. So for this reason, this is no-way in a dept guide til OpenLDAP, but just a little quick note, that hopefully can help you getting started.

In this example, we will setup LDAP to authenticate "local" users.

This will be updated, as I find or come across useful information.

I am using a similar setup, as a central authentication for several different machines.

LDAP	= Leight Weight Access Protocol
OU	= Organisational Unit
CN	= Common Name
DN	= Distinguish Name
RDN	= Relative Distinguish Name
DC	= Domain Component
L	= location
O	= Organisation
ST	= State
C	= County
dit	= Directory Information Tree
LDIF	= Ldap Data Interchange Format
OID	= Object Identifier
SN	= Surname
We will install the ldap-utils package which contains client utilities for administrering the OpenLDAP server and the package slapd, which is the OpenLDAP server itself.


apt-get install ldap-utils slapd

Automatically initial setup ("New PREFFERED" way) cn=config style

Debconf first asks for an password, so we will have to rerun the utility for the initial setup.
dpkg-reconfigure slapd
My answers.
Omit OpenLDAP server configuration: no
dns domain name: test.local
Organization name: MyTestOrg
password: XXXX

Initial Configuration

Create a basic LDIF file for the initial tree.
This is the most important step, so think about how you will design the DIT.
There are some good info on this site: http://www.zytrax.com/books/ldap/ch5/index.html

My DIT will look like this.
	 ______________/ \______________
	/				\
     ou=Users		     	    ou=Groups
Configuring the client config file, which sets default values for ldap client utilities like ldapsearch. This is needed to be done on the server, as well as clients which will use the LDAP server.
In example, if you have a client, that should auth against the LDAP server at login.
Edit the file, like below. Default port is 389.
Change dc and IP to your values.
BASE    dc=test,dc=local
URI     ldap://
Now from the client (which is STILL the server), lets see if this is working, the below command, should give you an output of the content on the LDAP server. Note the server could be the client in this case as well.

It should come with some information about our ldap server.
ldapsearch -x

OU and users, groups configuration

Now we will create the OUs, so it will match the DIT design above.
dn: ou=Users,dc=test,dc=local
objectClass: organizationalUnit
ou: Users
description: test.local users

dn: ou=Groups,dc=test,dc=local
objectClass: organizationalUnit
ou: Groups
description: test.local groups
Add data to ldap We will be using ldapadd from the openldap-clients package to create a simple structure.
ldapadd expects ldif input, so we will create a file which we will import.
ldapadd -x -W -D 'cn=admin,dc=test,dc=local' < usersgroupsOU.ldif 

Create a basic user

Again, we will use an ldif file, as an template to create a user, and a group with same name and id.
Create a "local" user, witch a matching group, which can logon, and authenticate. We will need to use an posix account.
{crypt}, will encrypt the userPassword field in the OpenLDAP database using the systems crypt function.
There are more information about OpenLDAP encryption types here: http://www.openldap.org/doc/admin24/security.html

Creating the password "test":
slappasswd -s testhest -h "{CRYPT}"
Creating the ldif file. We have to use the password generated above.
dn: uid=jdoe,ou=Users,dc=test,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
cn: John Doe
sn: Doe
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/jdoe
loginShell: /bin/bash
userPassword: {crypt}7X91DC.VmRVu6

dn: cn=jdoe,ou=Groups,dc=test,dc=local
objectClass: posixGroup
cn: jdoe
gidNumber: 10001
Now add the user "jdoe", and the group "jdoe".
ldapadd -x -W -D 'cn=admin,dc=test,dc=local' -f user.ldif

Setting up the clients for LDAP logons

Note that the clients are using cleartext username / passwords now, read the Adding encrypted security section for encrypted logons.

On the client install libnss-ldap,nscd and libpam-ldap.
The nsdc is a Name Service Caching Daemon, which caches NSS information. (user,group,hosts etc), and therefor NOT passwords.

It is possible to use libnss-ldapd and libpam-ldapd which uses nslcd instead of libnss-ldap and libpam-ldap. libnss-ldapd and libpam-ldapd, shares the same configuration file /etc/nslcd.conf which is also known in example CentOS.
libnss-ldapd and pibpam-ldapd should have better support for TLS/SSL.

Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=579647

Answer the debconf answers that matches your needs.
apt-get install libnss-ldap nscd libpam-ldap
Next configure libnss-ldap and libpam-ldap, so it can lookup the OpenLDAP directory.
Note A third slash have been removed from the URI section, so it is ldap:// and not ldap:/// or ldapi:///.

libnss-ldap answers:
I have added two ldap servers to the URI, so, if example the first server dies, i will request the second one. Requires replication!
LDAP server URI: ldap:// ldap://
Distinguished name of the search base: dc=test,dc=local
LDAP Version To Use: 3
libpam-ldap answers:
LDAP Account for root: cn=admin,dc=test,dc=local
LDAP root account password: LDAP_server_password
Allow LDAP admin account to behave like local root?: Yes
Does The LDAP Database Require Login: No
LDAP Administrative account: cn=admin,dc=test,dc=local
LDAP Administrative password: LDAP_server_password
The file for libnss-ldap can be manually editet in /etc/libnss-ldap.conf, or by running:
dpkg-reconfigure libnss-ldap
The file for libpam-ldap.conf can manually be editet in /etc/libpam-ldap.conf, or by running:
dpkg-reconfigure libpam-ldap
Setting up the NSSwitch file for ldap authentication, so we can login with an OpenLDAP user locally on the system.
Leave compat, so you still can login with the users that exists locally on the client, like example root!
putting ldap after compat, will first query local files, then LDAP, if no success
passwd:		compat	ldap
group:		compat	ldap
shadow:         compat  ldap

pam.d config files

The below files, must have configured the ldap module, for pam to be able to talk with the LDAP server.
In Debian Wheezy, the default files will work, and LDAP should be enabled by default, if not it is possible to reconfigure libpam-ldap, and under PAM profiles to enable select LDAP Authentication
If you have changed the files manually, you muse select "force overwrite" to enable ldap configurations in the files automatically! Then LDAP should be enabled in the below files.
  • /etc/pam.d/common-account
  • Verifies access. In example, account expiration
  • /etc/pam.d/common-auth Verifies the password request
  • /etc/pam.d/common-password
  • Change password
  • /etc/pam.d/common-session
  • Manages user sessions, in example mounting home directory
Disable nscd, doing test, so it is easier to test/troubleshoot the login. Remember to start it again, when testing is done.
/etc/init.d/nscd stop


Testing the login from the client, for our test users. It should prompt for informations about the user, if this is working.
id jdoe
uid=10001(jdoe) gid=10001(jdoe) groups=10001(jdoe)
getent passwd jdoe
jdoe:*:10001:10001:John Joe:/home/jdoe:/bin/bash
ldapwhoami -h -x -D "uid=jdoe,ou=Users,dc=test,dc=local" -W
Enter LDAP Password: 

Home directories

Since homedirectories, are not existing on machines that should logon to the OpenLDAP server, we will make sure that these homedirectories, are autocreated for the users at first logon, if they do not exist.

Insert the following line into /etc/pam.d/common-session
session    required   pam_mkhomedir.so skel=/etc/skel/ umask=0027
All done! You should now be able to login, from the local machine to the ldap server.
If this fails check /var/log/auth.log on the local machine.

If the above tests, where sucessfull, and you are unable to login, I would check the libpam-ldap configuration!

Rembember to start the nsdc, when the test is OK.
/etc/init.d/nscd start

Adding SSL/TLS encryption

LDAPS is deprecated! I am to lazy, to do a rewrite of this.. BUT...
You should use StartTLS instead of LDAPS. StartTLS listens on 389, so listener ldaps:// should NOT be added to /etc/default/slapd.
This also means, that you HAVE to set "ssl start_tls" in your nslcd.conf/libnss-ldap.conf/pam_ldap.conf files to initiate SSL on the default port 389.
Or else it, is basically the same as below....

For enhanced security we will use TLS, so we get the usernames and passwords encrypted. It is debatable whether to go with TLS or kerberos, read the link for info.:http://www.faqs.org/faqs/kerberos-faq/general/section-31.html

This will change the running default port from 389 to 636, so if required, you might have to open firewall ports.
Another option, is to use StartTLS/StartSSL which will make encrypted connections on the default port 389. I will not go through this step here, but is easy configurable.

On the OpenLDAP server change listening ports of the server in /etc/default/slapd, with this setup both SSL/TLS and unencryptet traffic will work.
Add ldaps:// to /etc/default/slapd on the server.
It is also possible to remove the default port 389 (ldap:///), if you do not want to listen to this port.
It will still though be possible to use NON-TLS on the TLS port (636), unless you directly configure the OpenLDAP server to require a certificate!
SLAPD_SERVICES=SLAPD_SERVICES="ldap:/// ldapi:/// ldaps://"
And restart the OpenLDAP server
/etc/init.d/slapd restart
I asume you already have an working CA, if not, create one, because I will use my own CA in this example.

Server certificate

Create the CSR, OR just the certificate!
openssl req -new -key ca.key -out ldap01.test.local.csr
req -new -x509 -days 365 -nodes -out ldap01.test.local.crt -key ca.key
Fill the info. It is important, that "Common Name (eg, YOUR name) []:" is set correctly, so i matches the server you are connecting to on the OpenLDAP server.
"ldap01.test.local" must resolve to the IP of the running the OpenLDAP server!
Common Name (eg, YOUR name) []:ldap01.test.local
Next sign, the certificate, if you created an CSR, or skip if you just created the certificate!
./sign.sh openldap.csr
Now copy the CA certificate, CA key and the newly signed certificate to a folder where slapd can read the files, chown and set correct rights.
mkdir /etc/ldap/certs/
cp openldap.crt ca.crt ca.key  /etc/ldap/certs
chown openldap:openldap /etc/ldap/certs/ldap01.test.local.crt /etc/ldap/certs/ca.crt /etc/ldap/certs/ca.key
chmod 400 /etc/ldap/certs/ldap01.test.local.crt /etc/ldap/certs/ca.crt /etc/ldap/certs/ca.key

Adding TLS to the OpenLDAP Server

Next create an ldif file, which will add the certificate sections to our OpenLDAP server.
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/certs/ca.crt
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/certs/insecure_ca.key
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/certs/ldap01.test.local.crt
Add the ldif file
ldapmodify -Y EXTERNAL -H ldapi:// -f ldaps.ldif
Now test, if the ldif is added.
ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config -s base | grep -i tls
Should output something like this.
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
olcTLSCACertificateFile: /etc/ldap/certs.d/ca.crt
olcTLSCertificateKeyFile: /etc/ldap/certs/insecure_ca.key
olcTLSCertificateFile: /etc/ldap/certs/ldap01.test.local.crt

Adding TLS to the Clients

Now we must change our clients to use TLS/SSL instead!
The certificate ca.crt MUST be readable from at least the service, or else you will get into trouble (make it world readable)
I have set mine to:
base dc=test,dc=local
uri ldaps://ldap01.test.local
ldap_version 3
rootbinddn cn=admin,dc=test,dc=local
tls_checkpeer yes
tls_cacertfile /etc/ssl/ca.crt
The certificate ca.crt MUST be readable from at least the service, or else you will get into trouble (make it world readable)
base dc=test,dc=local
uri ldaps://ldap01.test.local
ldap_version 3
rootbinddn cn=admin,dc=test,dc=local
pam_password crypt
tls_checkpeer yes
tls_cacertfile /etc/ssl/ca.crt
And if ldap-utils is installed on the client, change default values.
The certificate ca.crt MUST be readable from at least the service, or else you will get into trouble (make it world readable)
BASE	dc=test,dc=local
URI	ldaps://ldap01.test.local

TLS_CACERT	/etc/ssl/ca.crt
If you have issues, you can try to make the TLS connection less "critical".
For /etc/ldap/ldap.conf, you can try to set "TLS_REQCERT never" instead of demand, and for pam_ldap.conf and libnss-ldap.conf "tls_checkpeer no"!
Remember to read the documentation!

Backup and Restore

While the system is running, it is possible to use slapcat. Remember if something is added while the backup is running, it is likely that it is not backed up.
It is therefor recommended if possible, that slapd is stopped while running backup, but not required, or that you are completely sure that nothing is being changed in the database. It would be possible to stop a slave database and then backup of from here..
Doing so, will make the OpenLDAP server unavailable in this timeframe. Most likely just a couple of seconds.
/etc/init.d/slapd stop
#backup the configurtaion.
slapcat -n 0 -w slapdConfig.ldif
#backup the database itself.
slapcat -n 1 -w slapdDb.ldif

#remove current database(s).
rm /var/lib/ldap/*

#import the data
slapadd -n 0 -l slapdConfig.ldif 
slapadd -n 1 -l slapdDb.ldif 

#fix rights
chown openldap:openldap /var/lib/ldap/*

/etc/init.d/slapd start

Nice to have stuff, issues and fixes

Allow user to change password

If you want an user to allow to change passwords on the OpenLDAP Server, using the passwd command, you must remove use_authtok from /etc/pam.d/common-password.
use_authtok disables the password prompt.
#password        [success=1 user_unknown=ignore default=die]     pam_ldap.so use_authtok try_first_pass
password        [success=1 user_unknown=ignore default=die]     pam_ldap.so try_first_pass

Allow binding to config section

Normally, it is only possible to access the config section using ldapi://.
Creating a password for the config section of Openldap, allows binding to it, and using ldapmodify.
In this example, the password will be "test", created by slappasswd.
slappasswd -s test
Ldif file.
dn: cn=config
changetype: modify

dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}e8b47PmRK3AeKLISgJkB3y6bdaXSvkZ2
Add it to the OpenLDAP server.
ldapmodify -Y EXTERNAL -H ldapi:// -f 0ldapconf.ldif
Now it is possible to bind to the config section, in this example using StartTLS.
ldapmodify -ZZH ldap://ldap01.test.local -D "cn=admin,cn=config" -W

Forcing TLS / StartTLS serverside

Create an simple LDIF file.
dn: cn=config
changetype:  modify
add: olcSecurity
olcSecurity: tls=1
Adding the LDIF content to the server.
ldapmodify -Y EXTERNAL -H ldapi:// -f forcetls.ldif
ldapseach, should now show something like this, unless ldaps:// is specified in ldap.conf
ldapsearch -x
ldap_bind: Confidentiality required (13)
	additional info: TLS confidentiality required
To force StartTLS ONLY, make sure that ldaps:// is removed from the slapd.conf file.
Requires tls=1 on the OpenLDAP server, as described above.
SLAPD_SERVICES="ldapi:/// ldap://"

Forcing an complete sync

Quite simple, stop, delete, start. :)
/etc/init.d/slapd stop
rm /var/lib/ldap/*
/etc/init.d/slapd start

OpenLDAP commands

Nice to know commands

Changing own password using ldapasswd command. (-ZZ forces StartTLS, despite whats in ldap.conf)
ldappasswd -h ldap01.test.local -D "uid=jdoe,ou=Users,dc=test,dc=local" -W -S -ZZ
Changing another users password as root / admin. (-ZZ forces StartTLS, despite whats in ldap.conf)
ldappasswd -h ldap01.test.local -D "cn=admin,dc=test,dc=local" "uid=jdoe,ou=Users,dc=test,dc=local" -W -S -ZZ
search and show all for specific users starting with jdoe
ldapsearch -h ldap01.test.local -D "cn=admin,dc=test,dc=local" "(uid=jdoe*)" -W
Deleting an entry
ldapdelete -h ldap01.test.local -x -D "cn=admin,dc=test,dc=local" "cn=jdoe,ou=Groups,dc=test,dc=local" -W
ldapdelete -H ldap://ldap01 -D "cn=admin,dc=test,dc=local" "uid=jdoe24,ou=Users,dc=test,dc=local" -W
Testing TLS, if the default ldap.conf is not set for this!
ldapsearch -h ldap01.test.local -Z -x -D 'cn=admin,dc=test,dc=local' -W 'objectclass=*' -v
Checking replication status. Must be done on all hosts, example on one host.
ldapsearch -x -H ldap://ldap2 -s base contextCSN -LLL
contextCSN: 20150901182759.319689Z#000000#001#000000
contextCSN: 20150901182641.152254Z#000000#002#000000
Happy LDAP'ing :)
Copyright LinuxLasse.net 2009 - 2017 All Rights Reserved.

Valid HTML 4.01 Strict Valid CSS!