LDAP authentication under Linux/Mac OS X/FreeBSD


Index



This document assumes that you know what you are trying to achieve ie. authentication on Linux/MacOS X/FreeBSD using LDAP. It assumes you are using Debian as the server. This setup will work with other distributions and OSes however you will need to make certain adjustments ie. slapd.conf will be in /etc/openldap instead of /etc/ldap etc.

Creating Certificate Authority (CA) / SSL certificate

First of all we need to create set up our SSL certificates since we want our LDAP interactions to be as secure as possible. If you already have Certificate Authority setup and you know how to self-sign your certificates you can skip this whole section.

1. Create the certificate authority certificate and key. Make sure you remember the password you use. You will need to use it repeatedly.

mkdir -p /opt/certs/ca/newcerts
cd /opt/certs/ca
openssl req -new -x509 -keyout ./ca.key -out ./ca.crt
echo 01 >  /opt/certs/ca/serial
touch > /opt/certs/ca/index.txt

2. Creat the openssl.cf file in /opt/certs

####################################################################
[ ca ]
default_ca      = CA_default # The default ca section

####################################################################
[ CA_default ]

dir = /opt/certs/ca # Where everything is kept
certs           = $dir/certs # Where the issued certs are kept
crl_dir         = $dir/crl # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/ca.crt       # The CA certificate
serial          = $dir/serial           # The current serial number
crl  = $dir/crl.pem          # The current CRL
private_key     = $dir/ca.key           # The private key
RANDFILE        = $dir/private/.rand    # private random number file

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crl_extensions        = crl_ext

default_days    = 730      # how long to certify for
default_crl_days= 30       # how long before next CRL
default_md      = md5      # which md to use.
preserve        = no       # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy          = policy_anything

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName  = optional
stateOrProvinceName     = optional
localityName = optional
organizationName        = optional
organizationalUnitName  = optional
commonName = supplied
emailAddress = optional

3. Now let's generate a Certificate Signing Request

mkdir /opt/certs/server
cd /opt/certs/server
openssl genrsa -out hostname.key 1024
openssl req -new -key hostname.key -out hostname.csr

4. Now sign the hostname certificate with your certificate authority

openssl ca -config ./openssl.cf -out hostname.crt -infiles ./hostname.csr

As a result you now have hostname.crt and hostname.key that you will need to use with your SLAPD server.


LDAP Master setup

1. Find a suitable machine that can be a LDAP master host.

2. Install the OpenLDAP server and following packages

apt-get install libsasl-modules-plain slapd libsasl-gssapi-heimdal

3. By default on Debian slapd server will run as root. This is undesirable and therefore we want to add the slapd user and group that we can run the slapd daemon as so do following

useradd slapd
groupadd slapd

4. Let's configure slapd to use the slapd username

perl -pi -e "s/SLAPD_USER=/SLAPD_USER=slapd/g" /etc/default/slapd
perl -pi -e "s/SLAPD_GROUP=/SLAPD_USER=slapd/g" /etc/default/slapd
echo 'SLAPD_SERVICES="ldap:/// ldaps:///"' >> /etc/default/slapd

5. Now let's change permissions of the directories where slapd needs to write

chown -R slapd.slapd /var/run/slapd/
mkdir -p /var/lib/ldap
chown -R slapd.slapd /var/lib/ldap
chmod 0700 /var/lib/ldap

6. Create SLAPD admin password.  Use the slappasswd command to create the hash used for administration

$ /usr/sbin/slappasswd
New password:
Re-enter new password:
{SSHA}R1o7QiRVNBKBWLr2MIftiN5r5ovLQP3V

You will use the password hash in its entirety as the rootpw in slapd.conf.

7. Now let's create the slapd.conf

# Allow clients to connect using LDAP protocol 2. Required for Mozilla Mail
allow bind_v2

# Include schemas
include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
include         /etc/ldap/schema/misc.schema
include         /etc/ldap/schema/samba.schema
include         /etc/ldap/schema/apple.schema

# Let's use some security
TLSCipherSuite HIGH:MEDIUM:+SSLv2:RSA
# Here you need to insert certificate and key you created in Step 3 and 4 of SSL certificate creation
TLSCertificateFile /etc/ldap/certs/hostname.crt

TLSCertificateKeyFile /etc/ldap/certs/hostname.key

schemacheck     on

pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd.args

loglevel        0

modulepath      /usr/lib/ldap
moduleload      back_bdb
backend         bdb
database        bdb

suffix           "dc=cs,dc=school,dc=edu"
rootdn          "uid=root,cn=users,dc=cs,dc=school,dc=edu"
rootpw          {SSHA}R1o7QiRVNBKBWLr2MIftiN5r5ovLQP3V
directory       "/var/lib/ldap"

index           cn,sn,uid  pres,eq,approx,sub
index           uidNumber,gidNumber     eq
index           memberUid  eq
index           objectClass  eq

lastmod         on

replogfile      /var/lib/ldap/replog

# This is the slave server that we are replicating to.
replica      host=ldap2.cs.school.edu:389

   binddn=uid=admin,cn=users,dc=cs,dc=school,dc=edu
   tls=yes bindmethod=simple credentials=secret

include /etc/ldap/slapd.access.conf

8. Set up slapd.access.conf file. This file defines the permissions

access to dn=".*,dc=cs,dc=school,dc=edu" attr=mail
        by dn="uid=root,cn=users,dc=cs,dc=school,dc=edu" write
        by self write
        by * read

access to attribute=userPassword
        by dn="uid=root,cn=users,dc=cs,dc=school,dc=edu" write
        by anonymous auth
        by self write
        by * none

access to dn.base="" by * read

access to *
        by dn="uid=root,cn=users,dc=cs,dc=school,dc=edu" write
        by * read

9. Make sure schema and slapd.conf files are readable by slapd user

chown -R root.slapd /etc/ldap/*
chmod 440 /etc/ldap/schema/*.schema
chmod 640 /etc/ldap/slapd*.conf

10. Start the slapd server

/etc/init.d/slapd start

11. Now we need to populate our LDAP server with the settings from the NIS server ie. migration.

Migration

1. Good set of scripts to use is PADL's Migration Tools.

http://www.padl.com/OSS/MigrationTools.html

2. Download it and unpack. It will create a directory ie. MigrationTools-45

3. You need modify migrate_common.ph to suit your needs ie.

$DEFAULT_MAIL_DOMAIN = "cs.school.edu";
$DEFAULT_BASE = "dc=cs,dc=school,dc=edu";

4. Create a base LDIF and load it up  ie.

./migrate_base.pl > base.ldif
cat base.ldif | ldapadd -h ldap1.school.edu -ZZ -x -W -D 'uid=root,cn=users,dc=cs,dc=school,dc=edu'

4. Migrate passwords and groups ie.

ypcat passwd > nis.passwd
ypcat group > nis.group
./migrate_passwd.pl > passwd.ldif
./migrate_group.pl > group.ldif
cat passwd.ldif group.ldif | ldapadd -h ldap1.school.edu -ZZ -x -W -D 'uid=root,cn=users,dc=cs,dc=school,dc=edu'

5. Migrate Netgroups (if you are using them)

ypcat -k netgroup > nis.netgroup
./migrate_netgroup.pl nis.netgroup netgroup.ldif

6. You could alernatively just execute and follow directions

sh migrate_all_nis_online.sh

7. Last but not least we need to create an entry for the user that will replicate data to the slave server so that we are not using ie. uid=admin.

First create the password. I suggest choosing a password that is different than root's. Remember the password since you will have to use it for replication. To create password hash do

$ /usr/sbin/slappasswd
New password:
Re-enter new password:
{SSHA}R1o7QiRVNBKBWLr2MIftiN5r5ovLQP3V

Put the password hash in the userPassword field and create an entry like this and add it to the LDAP database

dn: uid=admin,cn=users,dc=cs,dc=school,dc=edu
uid: admin
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: apple-user
objectClass: extensibleObject
objectClass: organizationalPerson
objectClass: top
objectClass: person
userPassword:
{SSHA}R1o7QiRVNBKBWLr2MIftiN5r5ovLQP3V
homeDirectory: /tmp
sn: admin
loginShell: /bin/bash
gidNumber: 20
cn: admin
uidNumber: 202

8. Make sure you know put the password you created for uid=admin in the /etc/ldap/slapd.conf under the replica section ie. secret=adminpassword.

9. Now you can either go to the client setup or go directly into the slave setup.


Slave setup

Slave needs to have pretty much identical set up to the Master server so please follow steps 2. through 8. from the Master setup. Then follow slave specific setup

1. Go to the master host. Stop slapd and dump the LDAP database into a file ie.

/etc/init.d/slapd stop
slapcat -f dump.ldif
/etc/init.d/slapd stop

2. Go to the slave server. Copy the dump.ldif from the master host and run

slapadd -f dump.ldif
slapindex

3. Modify slapd.access.conf to say

access to *
        by dn="uid=root,cn=users,dc=cs,dc=school,dc=edu" write
        by dn="uid=admin,cn=users,dc=cs,dc=school,dc=edu" write
        by * read

instead of

access to *
        by dn="uid=root,cn=users,dc=cs,dc=school,dc=edu" write
        by * read

This will allow uid=admin to update the slave replica.

4. Add following to slapd.conf

updatedn        "uid=admin,cn=users,dc=cs,dc=school,dc=edu"
updateref       ldap://ldap1.cs.school.edu

This specifies which username is allowed to update the replica and also tells any clients if they need to make a change to a record ie. user needs to change the password they will need to talk to the master LDAP server.

5. Start the slapd server

/etc/init.d/slapd start

6. You are done. Now set up clients to use LDAP.

Client setup

Fedora/RedHat

Client setup under Fedora/RedHat is trivial. You need to run following command

authconfig --enableshadow --enablemd5 --enableldap --ldapserver=ldap1.cs.school.edu \  --ldapbasedn="dc=cs,dc=school,dc=edu" --enableldapauth --enableldaptls --enablecache --kickstart --disablenis

Authconfig will do it's magic behind the scenes. You could also launch authconfig-gtk which is the GUI version of it.

There is one other step that needs to be done. You will need to copy your Certificate Authority Certificate ie. ca.crt
into ie. /etc/openldap and point nss_ldap to use it e.g.

cp /repository/ca.crt /etc/openldap
echo "TLS_CACERT /etc/openldap/ca.crt" >> /etc/ldap.conf
echo "TLS_CACERT /etc/openldap/ca.crt" >> /etc/openldap/ldap.conf

Now if you type this on the machine

id <some_known_user>

and you get correct output you are done :-).

Debian

1. Install the PAM-LDAP and NSS-LDAP packages

apt-get install libpam-ldap libnss-ldap

2. Edit /etc/ldap/ldap.conf and insert following entries

uri ldap://ldap1.cs.school.edu/ ldap://ldap2.cs.school.edu
base dc=cs,dc=school,dc=edu
ldap_version 3
ssl start_tls
TLS_CACERT /etc/ldap/csca.crt

nss_base_netgroup      cn=netgroup,dc=cs,dc=school,dc=edu?one

3. Now let's have a single LDAP config file. No need for multiple ones with similar settings ie.

rm -f /etc/libnss-ldap.conf
rm -f /etc/pam_ldap.conf
ln -s /etc/ldap/ldap.conf /etc/libnss-ldap.conf
ln -s /etc/ldap/ldap.conf /etc/pam_ldap.conf

4. Type

ldapsearch -ZZ -x 'uid=someknowusername'

You should get username's LDIF record. If not something is wrong

5. If previous step worked now it's time to edit the nsswitch and PAM configuration ie. in /etc/nsswitch.conf modify password, group and shadow entries to say

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

netgroup:      files ldap

6. Modify PAM files to look like these

/etc/pam.d/common-auth

auth     sufficient     /lib/security/pam_ldap.so
auth    required        pam_unix.so use_first_pass

/etc/pam.d/common-account

account  sufficient /lib/security/pam_ldap.so
account required        pam_unix.so

/etc/pam.d/common-password

password sufficient /lib/security/pam_ldap.so
password        required        pam_unix.so md5 use_first_pass

7. Last but not least add

UsePAM yes

to /etc/ssh/sshd_config. Restart the SSH daemon ie.

/etc/init.d/ssh restart

8. That should be it. Try logging in.


Administration

Changing passwords

ldappasswd -D "uid=testuser,cn=users,dc=cs,dc=school,dc=edu" -S -h ldap1.cs.unm.edu -W -x


Troubleshooting

1. I am getting the Error: ldap_modify_s failed modifying "Insufficient access": uid=jdoe,cn=users,dc=cs,dc=school,dc=edu when slurpd runs

If updatedn doesn't have the write access to * you will get this error message. Please see Slave Server setup step 3.

2.  Replica ldap2.cs.school.edu:389, skip repl record for uid=jdoe,cn=users,dc=cs,dc=school,dc=edu (not mine)
Replica ldap2.cs.school.edu:389, skip repl record for uid=janedoe,cn=users,dc=cs,dc=school,dc=edu (not mine)
 
You are likely running as root instead of slapd

3. Generic problems

If you ever encounter problems first thing you should try is run slapd in the debug mode. Debug mode 3 works pretty good ie.

/usr/sbin/slapd -d 3