LDAP Authentication

Tony den Haan


Table of Contents
1. How, what and why?
1.1. Applications and services affected
1.2. Security
1.3. Don't forget
2. Client setup
2.1. Software to install
2.1.1. nss_ldap
2.1.2. pam_ldap ( http://www.padl.com/OSS/pam_ldap.html )
2.1.3. /etc/pam-ldap.conf
2.2. PAM
2.2.1. /etc/pam.d/passwd
2.2.2. /etc/pam.d/login
2.3. Openldap
2.4. /etc/security/access.conf
2.5. home directories
2.6. /etc/nsswitch.conf
2.7. Create user
3. Server setup
3.1. Installing the software
3.1.1. OpenLDAP
3.1.2. OpenLDAP-2.x
3.1.3. Linux-PAM
3.2. Configuration
3.2.1. slapd.conf
3.2.2. ldap tree
3.2.3. SSL/TLS configuration
3.3. LDAP classes
3.3.1. posixAccount
3.3.2. posixGroup
4. Migration
5. More reading
5.1. References
6. Notes
6.1. Things to test
6.2. Errors and solutions

Chapter 1. How, what and why?

1.1. Applications and services affected

Authenticatiion is needed for:

  • ssh

  • mail?

  • CVS

  • apache .htaccess etc

  • imap, NOTE: cyrus/imap needs SASL, which seems to be a bit of a pain

  • samba

  • ftp


1.2. Security

well, it's about authentication, so safety first.

  • client/server communication using: SSL/TLS

  • internal database will have to be protected.


1.3. Don't forget

  • change password....


Chapter 2. Client setup

2.1. Software to install

2.1.1. nss_ldap

build it using:

LDFLAGS="/usr/local/ssl/lib" ./configure --prefix=/ --enable-ssl -without-cyrus-sasl \
        --sysconfdir=/etc --with-ldap-conf-file=/etc/pam-ldap.conf

2.1.2. pam_ldap ( http://www.padl.com/OSS/pam_ldap.html )

build it using :

./configure --prefix=/ --enable-ssl --with-ldap-lib=openldap \ --sysconfdir=/etc --with-ldap-conf-file=/etc/pam-ldap.conf

./configure --prefix=/ --enable-ssl --with-ldap-lib=openldap \
--sysconfdir=/etc --with-ldap-conf-file=/etc/pam-ldap.conf

2.1.3. /etc/pam-ldap.conf

This is where pam_ldap looks for ldap.conf, this is not the general /etc/openldap/ldap.conf for ldap clients, to be used for different purposes.


# this file must be world readable (0644)
BASE       dc=example,dc=com

# FQDN of the LDAP server
HOST       authhost.example.com

# encryption used for storing passwords
#pam_crypt  

ldap_version 3

# bindpw is only needed if you want to allow root to change entries on
# this host.
# it's also better to keep the password in /etc/ldap.secret (0600) instead
#bindpw {crypt}4rKJLSLewr

# this one is to allow root to change entries
# it will require bindpw or password in /etc/ldap.secret
#rootbinddn cn=root,dc=example,dc=com

# this for group access
nss_base_group  ou=groups,dc=example,dc=com
pam_filter objectclass=posixAccount
pam_login_attribute uid

# OpenLDAP SSL options
# Require and verify server certificate (yes/no)
# TBD: where to put this certificate anyway?
# Default is "no"
# tls_checkpeer yes
tls_checkpeer no
ssl on
tls_ciphers  HIGH:MEDIUM:+SSLv2:RSA


2.2. PAM

2.2.1. /etc/pam.d/passwd

TBD


2.2.2. /etc/pam.d/passwd

TBD


2.2.3. /etc/pam.d/login


auth     required        pam_securetty.so
auth     required        pam_nologin.so
auth     sufficient      pam_ldap.so
auth     required        pam_unix_auth.so try_first_pass

account  sufficient      pam_ldap.so
account  required        pam_unix_acct.so

password required        pam_ldap.so

session  sufficient      pam_ldap.so
session  required        pam_unix_session.so


2.3. Openldap

a lost paragraph?


2.4. /etc/security/access.conf

Access per group, this to decided which ldap users actually are allowed to use this particular system. This makes use of LDAP class posixGroup


2.5. home directories

check pam_mkhomedir, ideally one would get NFS mounted homedirectory, how?


2.6. /etc/nsswitch.conf

This tells the system to first check ldap, and then files, for especially passwd, shadow and group.


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

(nisplus just for compatibility, not many linux systems end up using nisplus :-)


2.7. Create user

It would be very nice to be able to just use "useradd" for that, but that won't do. A script to add a user will have to:

  • verify if user exists already

  • find the first free uid, possibly in predefined range

  • encrypt the password

  • verify the username is not in /etc/passwd already



#!/bin/bash

SUFFIX="dc=example, dc=com"

name=$1

# verifiy user doesn't exist already
result=`ldapsearch 

case $# in
4)
HOME="/home/$1"
5)
HOME=$5
ldapadd -d cn=Manager,${SUFFIX} << EOF


EOF
;;
*)
echo "Add user to ldap, usage: $0 name password uid gid [homedir]" 


and password!


Chapter 3. Server setup

3.1. Installing the software

3.1.1. OpenLDAP

building openldap


./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
                --enable-ldap --enable-syslog --enable-dynamic \
                --disable-static --with-gnu-ld --with-tls



start with slapd -d1 -h "ldaps://0.0.0.0/" to listen to any address, with some debugging.


3.1.2. OpenLDAP-2.x

configure using:


./configure  --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-ldap --enable-syslog --enable-dynamic --with-gnu-ld --with-tls --disable-bdb --enable-ldbm




3.1.3. Linux-PAM

Tony's PAM page


3.2. Configuration

3.2.1. slapd.conf

# at least this one
include     /etc/openldap/schema/core.schema


access to dn=".*,dc=example,dc=com" attr=userpassword
        by dn="cn=Manager,dc=example,dc=com" write
        by self        write
        by      *       auth

access to dn=".*,dc=example,dc=com"
by self write
by *     auth


3.2.2. ldap tree

Create first entries:

  
ldapadd -D cn=Manager,dc=example,dc=com -H ldaps://authhost.example.com/ -W << EOF
dn: dc=example,dc=com
objectclass: dcObject
objectclass: organization
dc: example
o: MyOrg

dn: ou=users,dc=example,dc=com
objectclass: top
ou: people

dn: ou=groups,dc=example,dc=com
objectclass: top
ou: groups
EOF




3.2.3. SSL/TLS configuration

#These are used to authenticate client system.
#also config needed just to get ssl working at all
# create server keys, if not done yet
cd /etc/ssl
if [ ! -f ca.crt ];then
openssl req -new -x509 -keyout ./ca.key -out ./ca.crt -config openssl.cnf
fi

openssl req -new -x509 -keyout ./ldap.key -out ./ldap.crt -config openssl.cnf

openssl genrsa -out ldap.key -config openssl.cnf
openssl req -new -key ldap.key -out ldap.csr -config openssl.cnf

check /etc/ssl/openssl.conf


####################################################################                         
[ CA_default ] 
dir             = /etc/openssl          # Where everything is kept                
certs           = $dir            # 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     = $certs/ca.crt         # The CA certificate                                    
serial          = $dir/serial           # The current serial number                          
crl             = $dir/crl.pem          # The current CRL                                    
private_key     = $certs/ca.key         # The private key                    
RANDFILE        = $dir/private/.rand    # private random number file



create LDAP keys

#set serial to 1 (don't ask me why, please do tell)
echo 01 > /etc/ssl/serial
cd /etc/ssl
openssl ca -config openssl.cnf -out ldap.crt -infiles ./ldap.csr
#verify 
openssl x509 -text -in ldap.crt
#Check that the CN is set to the fqdn of your LDAP server! 



update slapd.conf:


#TLSCipherSuite HIGH:MEDIUM:+SSLv2:RSA                                                        
(doesn't get accepted by openssl2!)

TLSCertificateFile /etc/ssl/ldap.crt                                          
TLSCertificateKeyFile /etc/ssl/server.key    



another doc:

Here is a rough outline of the commands needed to do this:                                               
  /usr/bin/openssl req -newkey rsa:1024 -keyout tempfile1 -nodes -x509 -days 365 -out tempfile2                                                                                                      
  cat tempfile1 > ldap.pem                                                                                            
  echo "" >> ldap.pem                                                                                                 
  cat tempfile2 >> ldap.pem                                                                                           
  rm -f tempfile1 tempfile2              
(http://online.securityfocus.com/infocus/1428)


TLS trace: SSL_accept:error in SSLv3 read client certificate A



if you use OpenLDAP 2.0.x, compiled with TLS (OpenSSL), you can start the server using the command # slapd -h "ldap:/// ldaps:///"


3.3. LDAP classes

3.3.1. posixAccount

  • MUST:

  • cn

  • uid

  • uidNumber

  • homeDirectory

  • MAY:

  • userPassword

  • loginShell

  • gecos

  • description

  • organizationalPerson

  • objectclass: top

  • objectClass: mailRecipient


3.3.2. posixGroup

  • MUST:

  • cn (groupname)

  • gidNumber

  • MAY:

  • userPassword

  • memberUid

  • description

An entry can have more than on memberUid. To control access per group:


  account  required       pam_access.so

and then arrange access in/etc/security/access.conf


Chapter 4. Migration

The passwordfiles will have to be imported, tools at http://www.padl.com/download/MigrationTools.tgz


Chapter 5. More reading


Chapter 6. Notes

6.1. Things to test

ftp servers that use pam
cvs
mail
http access




6.2. Errors and solutions

Testing:

ftp?
cvs
mail?

        
PROBLEMS:
ay 23 11:50:38 major sshd[24528]: pam_ldap: error trying to bind as user "cn=tester,dc=example,dc=com" (Invalid credentials)
May 23 11:50:38 major sshd(pam_unix)[24528]: check pass; user unknown
means USERPASSWORD is not right!!

 remember /etc/secret!!... =======
Jul 10 10:04:48 geetwee sshd[18372]: pam_ldap: could not open secret file /etc/ldap.secret (No such file or directory)


    "I have no name!" means /etc/pam-ldap.conf is not world readable


pam_ldap: ldap_simple_bind Can't contact LDAP server
?



encrypt pass: 
userPassword=`perl -e "print crypt($pass,'az');"`