RJ Systems
Linux System Administration
Home Tech Linux Links Consulting







Valid XHTML 1.0!

Valid CSS!

IPv6 test

OpenLDAP provider with MIT Kerberos V on Debian lenny

Introduction

This page describes how to set up an OpenLDAP provider server with MIT Kerberos V support for authentication and encryption. It depends on a previously installed MIT Kerberos V master server, kdc1.example.com. Another Kerberos server, kdc2.example.com, a slave KDC, is also mentioned in the configuration, but does not have to be available for this procedure.

It is assumed that the reader is familiar with the concepts involved in the installation and configuration of an OpenLDAP provider. However, as opposed to that configuration, this OpenLDAP server will only store Unix user account information for authorization; the task of authentication will be performed by Kerberos, with all username and password combinations being stored in the Kerberos database.

In this example, OpenLDAP is installed on a host running Debian 5.0 (lenny). If followed properly, the step-by-step process should produce a provider server with a new DIT. But, before the interesting parts can begin, it will first be necessary to install the operating system on a new host called ldapks1.example.com. A DNS server must also be available on the network with a zone file to which forward and reverse mappings can be added for this host, as well as an alias for it called ldapks.example.com. After the initial installation of the operating system, make sure these packages are installed on the system as well:

~# apt-get install ntp ntpdate nmap

Afterwards, edit /etc/ntp.conf so that the machine synchronizes to a common NTP server (preferably a local one) and edit /etc/default/ntpdate to use the same host also. Now the installation of the new server can begin.


1. Kerberos client

First, run the following command to test if the MIT Kerberos V server installed previously is available on the network:

~# nmap kdc1.example.com

This should be among the results:

PORT    STATE SERVICE
749/tcp open  kerberos-adm
754/tcp open  krb_prop

If there is a problem, fix it first. If not, continue by installing these three packages:

~# apt-get install krb5-{config,user} libpam-krb5

A total of four packages are installed as a result, including one dependency:

krb5-config           1.22                           Configuration files for Kerberos Version 5
krb5-user             1.6.dfsg.4~beta1-5lenny2       Basic programs to authenticate using MIT Kerberos
libkadm55             1.6.dfsg.4~beta1-5lenny2       MIT Kerberos administration runtime libraries
libpam-krb5           3.11-4                         PAM module for MIT Kerberos

During the installation, the krb5-config package will automatically have the default realm set to EXAMPLE.COM, but a few questions have to be answered for it as well:

Kerberos servers for your realm: kdc1.example.com kdc2.example.com
Administrative server for your Kerberos realm: krb.example.com

These settings, along with the default realm, are saved in /etc/krb5.conf.


2. Realm config file

Edit the Kerberos realm configuration file, /etc/krb5.conf. This file is initially created by the Debian installer and contains information about the realms of a number of famous institutions, but none of that is necessary in this case. Instead, replace its contents with this:

[libdefaults]
        default_realm = EXAMPLE.COM
        forwardable = true
        proxiable = true

[realms]
        EXAMPLE.COM = {
                kdc = kdc1.example.com
                kdc = kdc2.example.com
                admin_server = krb.example.com
        }

[domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM

See this section for a more detailed explanation of this file.

Regarding the list of KDCs that are specified here, it is often recommended to use a predetermined set of DNS hostname aliases (CNAME records) to refer to the Kerberos servers on a network. However, it is also possible to omit the mention of any KDCs here and instead rely on the relatively new SRV DNS resource record type. See the article DNS discovery for MIT Kerberos V for information on how to do that.


3. Service princ & keytab

Use kadmin to create a Kerberos principal for the LDAP service and a matching keytab file by issuing a few commands:

~# kadmin -p admin
Authenticating as principal admin with password.
Password for admin@EXAMPLE.COM: Lampropeltis
kadmin:  addprinc -randkey ldap/ldapks1.example.com
WARNING: no policy specified for ldap/ldapks1.example.com@EXAMPLE.COM; 
defaulting to no policy
Principal "ldap/ldapks1.example.com@EXAMPLE.COM" created.
kadmin:  ktadd ldap/ldapks1.example.com
Entry for principal ldap/ldapks1.example.com with kvno 3, encryption type 
AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab 
WRFILE:/etc/krb5.keytab.
Entry for principal ldap/ldapks1.example.com with kvno 3, encryption type 
ArcFour with HMAC/md5 added to keytab 
WRFILE:/etc/krb5.keytab.
Entry for principal ldap/ldapks1.example.com with kvno 3, encryption type 
Triple DES cbc mode with HMAC/sha1 added to keytab 
WRFILE:/etc/krb5.keytab.
Entry for principal ldap/ldapks1.example.com with kvno 3, encryption type 
DES cbc mode with CRC-32 added to keytab 
WRFILE:/etc/krb5.keytab.
kadmin:  q
~# _

The -randkey switch is used because a machine cannot enter a password. To list the keys in /etc/krb5.keytab, use the klist -ke command. A host (or service) principal and a keytab file should be created for and saved on all of the various client machines that are part of a Kerberos realm.


4. OpenLDAP install

On the new host, ldaps1.example.com, start by installing these two packages:

~# apt-get install slapd ldap-utils

A total of ten packages are installed as a result, including eight dependencies:

ldap-utils                2.4.11-1+lenny1             OpenLDAP utilities
libdb4.2                  4.2.52+dfsg-5               Berkeley v4.2 Database Libraries [runtime]
libltdl3                  1.5.26-4+lenny1             A system independent dlopen wrapper for GNU libtool
libperl5.10               5.10.0-19lenny2             Shared Perl library
libsasl2-modules          2.1.22.dfsg1-23+lenny1      Cyrus SASL - pluggable authentication modules
libslp1                   1.2.1-7.5                   OpenSLP libraries
odbcinst1debian1          2.2.11-16                   Support library and helper program for accessing odbc ini file
psmisc                    22.6-1                      Utilities that use the proc filesystem
slapd                     2.4.11-1+lenny1             OpenLDAP server (slapd)
unixodbc                  2.2.11-16                   ODBC tools libraries

During the install process, an administrator password will be requested for slapd. Use piscivorus:

Administrator password: piscivorus
Confirm password: piscivorus

Run the following command to test if the OpenLDAP server is actually running:

~# nmap ldapks1.example.com

This should be among the results:

PORT    STATE SERVICE
389/tcp open  ldap

Perform a quick test by generating an LDIF dump of the contents of a the database:

~# slapcat
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example
structuralObjectClass: organization
entryUUID: 6d22e2e8-6e30-102e-9761-05effbdceeba
creatorsName:
createTimestamp: 20091125170507Z
entryCSN: 20091125170507.217451Z#000000#000#000000
modifiersName:
modifyTimestamp: 20091125170507Z

dn: cn=admin,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e2NyeXB0fU1TVXFoNlFiZlp0MXM=
structuralObjectClass: organizationalRole
entryUUID: 6d237c58-6e30-102e-9762-05effbdceeba
creatorsName:
createTimestamp: 20091125170507Z
entryCSN: 20091125170507.221751Z#000000#000#000000
modifiersName:
modifyTimestamp: 20091125170507Z

~# _

5. admin → rootdn

During the initial setup, an account was created that will soon be be more of a security risk. Since the object here is to create a more secure sevice by storing all credentials in the Kerberos database exclusively, it would be considered a security weakness if it were left in the LDAP database. Therefore, in this step it will be deleted after hard-coding a new name and password for administrative access. To do this it will be necessary to edit /etc/ldap/slapd.conf, but the opportunity will also be taken to make a few other changes to this file. Starting at the top, comment out the logging option, which will return it to its default value (256):

#loglevel "none"

Next, the important part, insert these rootdn and rootpw directives:

# rootdn          "cn=admin,dc=example,dc=com"

rootdn          cn=admin,dc=example,dc=com
rootpw          piscivorus

Then modify the ACLs to look like this:

access to attrs=userPassword,shadowLastChange
        by * none

access to attrs=loginShell
        by self write
        by users read
        by * none

access to dn.base=""
	by * read

access to *
        by users read
        by * none

Respectively, this is 1.) to prevent any access to password information, 2.) to allow everyone to change their own shell settings, which are included in the LDAP schema for posixAccount, and 3.) to ensure read access to the base of the tree for things like supportedSASLMechanisms, 4.) otherwise to only allow authenticated users to have read access to everything else in the LDAP database.

Having committed the above changes, restart the LDAP service:

~# /etc/init.d/slapd restart
Stopping OpenLDAP: slapd.
Starting OpenLDAP: slapd.
~# _

At this point it is safe to delete the admin account from the directory:

~# ldapdelete -x -h localhost -D cn=admin,dc=example,dc=com \
   -w piscivorus cn=admin,dc=example,dc=com
~# _

Perform a quick test by generating an LDIF dump of the contents of a the database:

~# slapcat
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example
structuralObjectClass: organization
entryUUID: 2244f4f4-83f3-102e-9a45-0554836ee547
creatorsName:
createTimestamp: 20091223094147Z
entryCSN: 20091223094147.892297Z#000000#000#000000
modifiersName:
modifyTimestamp: 20091223094147Z

~# _

The results should look like the above, showing that only the entry for the organization object, dc=example,dc=com, is left.


6. ldap.conf

Edit /etc/ldap/ldap.conf and use these two lines:

BASE    dc=example,dc=com
URI     ldap://ldapks1.example.com/

This configuration file is used to set system-wide defaults for LDAP clients.


7. Basic tree

Create a basic tree structure. First create a file, ~/tree.ldif, with the following content:

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups

Add this information to the LDAP database using the ldapadd command:

~# ldapadd -xWD cn=admin,dc=example,dc=com -f ~/tree.ldif
Enter LDAP Password: piscivorus
adding new entry "ou=people,dc=example,dc=com"

adding new entry "ou=groups,dc=example,dc=com"

~# _

A quick ldapsearch should show the new objects:

~# ldapsearch -xLLL
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups

~#

8. Slapd kerberization

To kerberize slapd, start by installing this package:

~# apt-get install libsasl2-modules-gssapi-mit

Only one package is installed as a result:

libsasl2-modules-gssapi-mit      2.1.22.dfsg1-23+lenny1      Cyrus SASL - pluggable authentication modules (GSSAPI)

GSSAPI stands for Generic Security Service API. Defined in RFC-2743, it provides a common interface for accessing different security services, one of the most popular of which is Kerberos V. The way that GSSAPI services can be used for SASL authentication and the establishment of a security layer is described in RFC-2222 (Simple Authentication and Security Layer).

Change the permissions and ownership of the Kerberos keytab file to make sure that slapd can access it:

~# chmod 640 /etc/krb5.keytab
~# chown root.openldap /etc/krb5.keytab
~# _

Edit /etc/default/slapd and uncomment a line near the end of the file that will export the location of the Kerberos system keytab file as a variable:

export KRB5_KTNAME=/etc/krb5.keytab

Edit /etc/ldap/ldap.conf and add the following line to the end of the file to specify the authentication mechanism:

SASL_MECH GSSAPI

Now to configure the link that maps GSSAPI-format user names to LDAP names. Once users have been authenticated by Kerberos and have valid Kerberos tickets, the SASL layer redirects them to the GSSAPI mechanism. This results in distinguished names that consist of four parts:

  1. uid=user_name
  2. cn=realm_name
  3. cn=gssapi
  4. cn=auth

For instance, the Kerberos admin account becomes uid=admin,cn=example.com,cn=gssapi,cn=auth. The key is to match these GSSAPI-format names to ones that can be used together with the LDAP DIT. This is done by adding the authz-regexp directive to /etc/ldap/slapd.conf, which includes a regular expression. Modify this file by adding the following stanza to the end of the Global section:

tool-threads 1

authz-regexp
     uid=([^,]+),cn=example.com,cn=gssapi,cn=auth
     uid=$1,ou=people,dc=example,dc=com

The authz-regexp directive shown here is followed by two options: a search pattern that matches all of the GSSAPI-format user names from Kerberos, and a replacement pattern that changes them to names found in the ou=people,dc=example,dc=com organizational unit. This is an example of a direct mapping and is the generally recommended approach, since it not only avoids the expense of searching for user DNs, but also allows mapping to DNs that refer to entries not found on the same server (or even in the entire DIT, such as with the admin user, which is only significant because of the rootdn directive on the provider server).

The drawback of direct mapping is that it only maps users to a single organizational unit. If it becomes necessary or desirable to organize users into more than one organizational unit, then solutions are possible using multiple authz-regexp statements with direct mappings and/or search-based mappings with LDAP URLs. As an example of the latter, consider the following authz-regexp statement:

authz-regexp
	uid=([^,]+),cn=example.com,cn=gssapi,cn=auth
	ldap:///dc=example,dc=com??sub?
	   (&
	      (|
	         (entryDN:dnSubtreeMatch:=ou=people,dc=example,dc=com)
	         (entryDN:dnSubtreeMatch:=ou=robots,dc=example,dc=com)
	      )
	      (&
		 (uid=$1)
	         (objectclass=person)
	      )
	   )

LDAP search URLs must always be written on a single line and without any of the extra spacing, unlike the format shown here for the sake of clarity. In this example, the search pattern matches all GSSAPI-format names as before, but the replacement pattern searches two organizational units, people and robots, for matching LDAP user names. The disadvantages of this solution are that it is slower than direct mapping, and that GSSAPI names are not mapped if no matching LDAP counterparts are found for them. The admin entry, for instance, would not be found. A solution to the latter problem would be to either move the admin entry to ou=people, or to add an extra authz-regexp statement to specifically match the current DN of the admin entry:

authz-regexp
     uid=admin,cn=example.com,cn=gssapi,cn=auth
     uid=admin,dc=example,dc=com

Anyway, still editing /etc/ldap/slapd.conf, add this directive, which specifies the Kerberos realm, to the end of the Global section, just below the new authz-regexp statement:

authz-regexp
     uid=([^,]+),cn=example.com,cn=gssapi,cn=auth
     uid=$1,ou=people,dc=example,dc=com

sasl-realm EXAMPLE.COM

This is important, because without it the authz-regexp mechanism will not work.

The last change to /etc/ldap/slapd.conf is due to the implementation of the authz-regexp statement. It is now necessary to modify the rootdn and desirable to comment out the rootpw:

rootdn          uid=admin,ou=people,dc=example,dc=com
#rootpw          piscivorus

Note that this moves the admin user to ou=people! If this is neglected, the previously described problem will occur and the LDAP admin account will no longer be resolved. Regarding the rootpw, from this point on the LDAP administrator's password will be the one used for the Kerberos admin account: Lampropeltis.

Having saved the above changes, restart the LDAP service:

~# /etc/init.d/slapd restart
Stopping OpenLDAP: slapd.
Starting OpenLDAP: slapd.
~# _

9. Testing

Run some tests. First try a simple unauthenticated (-x) LDAP query:

~# ldapsearch -xLLL
No such object (32)
~# _

Since the last ACL applied in step 5 grants "access to * by * none," this should result in no objects being found. However, the authenticated version of this query, which is its default operational mode, will give an error:

~# ldapsearch -LLL
SASL/GSSAPI authentication started
ldap_sasl_interactive_bind_s: Local error (-2)
~# _

The solution is to first acquire a Kerberos ticket for the admin user (password Lampropeltis):

~# kinit admin
Password for admin@EXAMPLE.COM: Lampropeltis
~# _

A verification of the ticket should show a success:

~# klist -5
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@EXAMPLE.COM

Valid starting     Expires            Service principal
12/23/09 19:38:48  12/24/09 19:38:45  krbtgt/EXAMPLE.COM@EXAMPLE.COM
~# _

Now the previously attempted authenticated query should work:

~# ldapsearch -LLL
SASL/GSSAPI authentication started
SASL username: admin@EXAMPLE.COM
SASL SSF: 56
SASL data security layer installed.
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people

dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups

~# _

Also, under these circumstances the ldapwhoami command behaves more like whoami:

~# whoami
root
~# ldapwhoami
SASL/GSSAPI authentication started
SASL username: admin@EXAMPLE.COM
SASL SSF: 56
SASL data security layer installed.
dn:uid=admin,ou=people,dc=example,dc=com
~# _

Make no mistake: except when anonymous access is requested (and granted), authentication is necessary for every individual LDAP command. However, in this case Kerberos takes care of authentication in the background, significantly increasing ease of use. Single sign-on in action!


10. See also
11. Further reading
  • Eastlake D, Panitz A. 1999. RFC2606 − Reserved Top Level DNS Names. The Internet Society. HTML at the Internet FAQ Archives.
  • Hodges J, Morgan R. 2002. RFC3377 − Lightweight Directory Access Protocol (v3): Technical Specification. The Internet Society. HTML at the Internet FAQ Archives.
  • Kohl J, Neuman C. 1993. RFC1510 − The Kerberos Network Authentication Service (V5). HTML at the Internet FAQ Archives.
  • Linn J. 2000. RFC2743 − Generic Security Service Application Program Interface Version 2, Update 1. The Internet Society. HTML at the Internet FAQ Archives.
  • Myers J. 1997. RFC2222 − Simple Authentication and Security Layer (SASL). The Internet Society. HTML at the Internet FAQ Archives.
  • Wahl M, Howes T, Kille S. 1997. RFC2251 − Lightweight Directory Access Protocol (v3). The Internet Society. HTML at the Internet FAQ Archives.
  • Wray J. 2000. RFC2744 − Generic Security Service API Version 2 : C-bindings. The Internet Society. HTML at the Internet FAQ Archives.
  • Yeong W, Howes T, Kille S. 1993. RFC1487 − X.500 Lightweight Directory Access Protocol. The Internet Society. HTML at the Internet FAQ Archives.

12. Sources
  • Carter G. 2003. LDAP System Administration. O'Reilly & Associates, Inc. ISBN 1-56592-491-6. 294 pp.
  • Massachusetts Institute of Technology. 1985-2007. Kerberos V5 System Administrator's Guide. HTML at the Massachusetts Institute of Technology (MIT).
  • Milicchio F, Gehrke WA. 2007. Distributed Services with OpenAFS. Springer-Verlag. ISBN-13 978-3-540-36633-1. 395 pp.
  • OpenLDAP Project. 2009. OpenLDAP Software 2.4 Administrator's Guide. HTML at OpenLDAP.


Last modified: 2012-08-24, 18:26

©2003-2014 RJ Systems. Permission is granted to copy, distribute and/or modify the
content of this page under the terms of the OpenContent License, version 1.0.