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 squeeze

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 6.0 (squeeze). 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 -sU -sT -p U:88,464,T:464,749 kdc1.example.com

Starting Nmap 5.00 ( http://nmap.org ) at 2010-11-23 20:05 CET
Interesting ports on kdc1.example.com (192.168.2.36):
PORT    STATE         SERVICE
464/tcp open          kpasswd5
749/tcp open          kerberos-adm
88/udp  open|filtered kerberos-sec
464/udp open|filtered kpasswd5
MAC Address: 08:00:27:AB:13:C1 (Cadmus Computer Systems)

Nmap done: 1 IP address (1 host up) scanned in 1.42 seconds
~# _

The Kerberos password-change daemon is available on both TCP port 464 and UDP port 464, the Kerberos administration server is on TCP port 749. Most importantly, the Kerberos Key Distribution Center (KDC) is found on UDP port 88. Note that the state of all of these ports is open, which means that the services are available. If in reality this is not the case, fix that problem first. If they are all open, continue by installing these three packages:

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

A total of three packages are installed as a result with no dependencies:

krb5-config           2.2                            Configuration files for Kerberos Version 5
krb5-user             1.8.3+dfsg-4                   Basic programs to authenticate using MIT Kerberos
libpam-krb5           4.3-1                          PAM module for MIT Kerberos

During the installation, krb5-config will require that a few questions be answered:

Default Kerberos version 5 realm: EXAMPLE.COM
Kerberos servers for your realm: kdc1.example.com kdc2.example.com
Administrative server for your Kerberos realm: krb.example.com

These settings are saved in the Kerberos realm configuration file /etc/krb5.conf. Mostly, it contains information about the realms of a number of other organizations and options regarding Kerberos 4, all of which is unnecessary in this case. The entire contents could be replaced with:

[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
        }

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 KDC entries in /etc/krb5.conf and instead rely on DNS SRV resource records to do the same job. See DNS discovery for MIT Kerberos V for information on how to do that.

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 to avoid having to use 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.


2. OpenLDAP install

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

~# apt-get install slapd ldap-utils

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

ldap-utils              2.4.23-7                   OpenLDAP utilities
libltdl7                2.2.6b-2                   A system independent dlopen wrapper for GNU libtool
libperl5.10             5.10.1-16                  shared Perl library
libslp1                 1.2.1-7.8                  OpenSLP libraries
odbcinst                2.2.14p2-1                 Helper program for accessing odbc ini files
odbcinst1debian2        2.2.14p2-1                 Support library for accessing odbc ini files
slapd                   2.4.23-7                   OpenLDAP server (slapd)
unixodbc                2.2.14p2-1                 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 -p 389 localhost

Starting Nmap 5.00 ( http://nmap.org ) at 2010-11-23 22:29 CET
Warning: Hostname localhost resolves to 2 IPs. Using 127.0.0.1.
Interesting ports on localhost (127.0.0.1):
PORT    STATE SERVICE
389/tcp open  ldap

Nmap done: 1 IP address (1 host up) scanned in 0.09 seconds
~# _

The ldap service is made available on port 389 by the Standalone LDAP Daemon (slapd). Note that the state of the port is open. To be sure, the LDAP v3 technical specification (RFC-3377) does not mention anything about a backend solution in which to store the database; it is only a description of the network protocol itself. The daemon, slapd, the way it stores its data and the various utilities it comes with are all unique to OpenLDAP.

Perform a quick test by generating an LDAP Data Interchange Format (LDIF) dump of the contents of a the database:

~# slapcat
hdb_db_open: database "dc=example,dc=com": unclean shutdown detected; 
attempting recovery.
hdb_db_open: database "dc=example,dc=com": recovery skipped in read-only 
mode. Run manual recovery if errors are encountered.
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example
structuralObjectClass: organization
entryUUID: 2cabf1ae-8c26-102f-8e97-45e092b2309a
creatorsName: cn=admin,dc=example,dc=com
createTimestamp: 20101124145216Z
entryCSN: 20101124145216.651229Z#000000#000#000000
modifiersName: cn=admin,dc=example,dc=com
modifyTimestamp: 20101124145216Z

dn: cn=admin,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9aFdRdHhldk00VDdTMUFMZVgwelExNll3Y0UwL0JRQXE=
structuralObjectClass: organizationalRole
entryUUID: 2caca734-8c26-102f-8e98-45e092b2309a
creatorsName: cn=admin,dc=example,dc=com
createTimestamp: 20101124145216Z
entryCSN: 20101124145216.655915Z#000000#000#000000
modifiersName: cn=admin,dc=example,dc=com
modifyTimestamp: 20101124145216Z

~# _

Note that the new DIT consists of only two objects: the base, or root of the tree, dc=example,dc=com, and the administrative user, cn=admin.

Edit /etc/ldap/ldap.conf and add these two lines to the end of the file:

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

This configuration file sets local, system-wide defaults for LDAP clients.


3. cn=config

A number of general modifications need to be made to the OpenLDAP runtime configuration directory regarding two existing entries. First consider the current state of these objects:

~# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config \
"(|(cn=config)(olcDatabase={1}hdb))"
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1

dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=example,dc=com
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymou
 s auth by dn="cn=admin,dc=example,dc=com" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=example,dc=com" write by *
  read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=example,dc=com
olcRootPW: {SSHA}hWQtxevM4T7S1ALeX0zQ16YwcE0/BQAq
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq

~# _

Here is a description of the changes that will be made to the cn=config DIT:

1. For the root object, cn=config, the value for olcLogLevel is currently set to none (the Debian default). This prevents slapd from writing almost anything to the syslog. This is okay for production environments, but less desirable for educational purposes, so it is going to be changed to stats (the value recommended by the OpenLDAP project). This way, slapd will log more about what it does to /var/log/syslog.
2.1.x. For the database definition, olcDatabase={1}hdb,cn=config, all three of the current ACLs, each one a value of an olcAccess attribute, will be deleted. For the sake of clarity, this will be done in reverse order, or else the index numbers used would all have to be zero.
2.2.1. The first new olcAccess attribute (index 0) will prevent any access to password information stored in the DIT.
2.2.2. The second ACL (index 1) will allow everyone to change their own shell settings, which are included in the LDAP schema for the posixAccount object class.
2.2.3. The third ACL (index 2) is will allow read access to the base of the tree for things like supportedSASLMechanisms.
2.2.4. The fourth and last ACL (index 3) will allow only authenticated users to have read access to everything else in the LDAP database. Anonymous users will have no access.
2.3. An extra equality (eq) index will be added for User ID (uid) objects. olcDbIndex directives are used to specify the attributes on which slapd should maintain indices to optimize directory searches. This new equality index will speed up searches for entries based on exact matches of the uid attribute. At the moment it is not really necessary to add any extra indices, since the dc=example,dc=com directory contains almost no data. However, it is recommended to add an eq index for uid entries, because these are used for storing user account names and later on, as the DIT grows in size, this index can significantly decrease the time it takes for users to log in. This eq will also prevent "bdb_equality_candidates" errors...
2.4. An equality index will also be set for Common Name (cn) objects to prevent "bdb_equality_candidates" errors from appearing in the log file, /var/log/syslog. One such error will otherwise appear in the log for every search for an entry of this type.
2.5. Idem for Organizational Unit (ou) objects.
2.6. Idem for Domain Component (dc) objects.

To make both of the above changes to the cn=config DIT, first create an LDIF file, called ~/olc-mod1.ldif, with the following contents:

# 1.
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats

# 2.1.1.
dn: olcDatabase={1}hdb,cn=config
changetype: modify
delete: olcAccess
olcAccess: {2}to *
  by self write
  by dn="cn=admin,dc=example,dc=com" write
  by * read
-
# 2.1.2.
delete: olcAccess
olcAccess: {1}to dn.base=""
  by * read
-
# 2.1.3.
delete: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange
  by self write
  by anonymous auth
  by dn="cn=admin,dc=example,dc=com" write
  by * none
-
# 2.2.1.
add: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange
  by * none
-
# 2.2.2.
add: olcAccess
olcAccess: {1}to attrs=loginShell
  by self write
  by users read
  by * none
-
# 2.2.3.
add: olcAccess
olcAccess: {2}to dn.base=""
  by * read
-
# 2.2.4.
add: olcAccess
olcAccess: {3}to *
  by users read
  by * none
-
# 2.3.
add: olcDbIndex
olcDbIndex: uid eq
-
# 2.4.
add: olcDbIndex
olcDbIndex: cn eq
-
# 2.5.
add: olcDbIndex
olcDbIndex: ou eq
-
# 2.6.
add: olcDbIndex
olcDbIndex: dc eq

After the file has been saved, apply all of the above changes with this command:

~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/olc-mod1.ldif
modifying entry "cn=config"

modifying entry "olcDatabase={1}hdb,cn=config"

~# _

Rerun the previous ldapsearch command to verify that all of the changes have been made successfully.

During the initial setup, an administrative account, cn=admin, was created that will soon be a security risk. The aim here is to create a secure service with all credentials stored exclusively in the Kerberos database, so now that all references to it have been removed from the cn=config DIT, this account can be deleted:

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

This does not actually remove administrative access to the DIT, because this name and its matching password still exist as attributes of the database definition in the slapd runtime configuration. The difference is that now they cannot be used from anywhere else − only on this server. If it ever becomes necessary, or desirable, for the admin account to also have full read/write access to the DIT from elsewhere on the network, the ACLs above should be altered to once again include write access for the admin account. However, that should be done at some later point, because in this example the DN for the admin account will soon be changed.

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

~# slapcat
hdb_db_open: database "dc=example,dc=com": unclean shutdown detected; 
attempting recovery.
hdb_db_open: database "dc=example,dc=com": recovery skipped in read-only 
mode. Run manual recovery if errors are encountered.
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: example.com
dc: example
structuralObjectClass: organization
entryUUID: 2cabf1ae-8c26-102f-8e97-45e092b2309a
creatorsName: cn=admin,dc=example,dc=com
createTimestamp: 20101124145216Z
entryCSN: 20101124145216.651229Z#000000#000#000000
modifiersName: cn=admin,dc=example,dc=com
modifyTimestamp: 20101124145216Z

~# _

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


4. 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.23.dfsg1-6              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, uid=admin,cn=example.com,cn=gssapi,cn=auth would be the GSSAPI-format name of the Kerberos admin account. The key is to match and replace these names with ones that can be found in the DIT. To do this, a couple of organizational units will be necessary. These will contain user and group objects. Create a file, ~/people-groups.ldif, with the following contents:

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 DIT with the ldapadd command:

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

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

~# _

The slapd runtime configuration directory will also have to be modified again. Two objects need to be altered that at the moment look like this:

~# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config \
"(|(cn=config)(olcDatabase={1}hdb))"
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1
olcLogLevel: stats

dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=example,dc=com
olcLastMod: TRUE
olcRootDN: cn=admin,dc=example,dc=com
olcRootPW: {SSHA}hWQtxevM4T7S1ALeX0zQ16YwcE0/BQAq
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcDbIndex: uid eq
olcDbIndex: cn eq
olcDbIndex: ou eq
olcDbIndex: dc eq
olcAccess: {0}to attrs=userPassword,shadowLastChange by * none
olcAccess: {1}to attrs=loginShell by self write by users read by * none
olcAccess: {2}to dn.base="" by * read
olcAccess: {3}to * by users read by * none

~# _

Here is a description of the changes that will be made to the configuration directory to complete the kerberization of the slapd provider server:

1.1. For the root object, cn=config, add an olcAuthzRegexp attribute, the value of which consists of a match string and a replace string. The match string will be a regular expression to match the simple user names provided by the SASL subsystem. The replace string will then convert them to an LDAP DN format.
1.2. An olcSaslRealm attribute will be added to specify the SASL realm, in this case a Kerberos realm.
2.1. For the database definition, olcDatabase={1}hdb,cn=config, the olcRootPW attribute will be deleted. This will remove the hard-coded password that gives administrative access to the DIT. Not doing so would leave a hole in the system's security.
2.2. The DN for the administrative user will be moved to to ou=people. After this point, the password of the LDAP administrator will be the same as the one used for the Kerberos admin account: Lampropeltis.

To make the above changes to the cn=config DIT, create an LDIF file, called ~/olc-mod2.ldif, with the following contents:

# 1.1.
dn: cn=config
changetype: modify
add: olcAuthzRegexp
olcAuthzRegexp: uid=([^,]+),cn=example.com,cn=gssapi,cn=auth
  uid=$1,ou=people,dc=example,dc=com
-
# 1.2.
add: olcSaslRealm
olcSaslRealm: EXAMPLE.COM

# 2.1.
dn: olcDatabase={1}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: uid=admin,ou=people,dc=example,dc=com
-
# 2.2
delete: olcRootPW

The value for the olcAuthzRegexp directive shown here includes two parts: a search pattern to match all GSSAPI-format user names from Kerberos, and a replacement pattern to change them to LDAP names found in the ou=people,dc=example,dc=com organizational unit.

The olcAuthzRegexp statement used above is an example of a direct mapping. This 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 olcRootDN attribute 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 other solutions are possible. For instance, since it is a multi-valued attribute, several olcAuthzRegexp statements with direct mappings can be used, and/or search-based mappings can be used with LDAP URLs. As an example of the latter, consider the following olcAuthzRegexp statement:

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

NB: LDAP search URLs must always be written on a single line and without any extra spacing, unlike the format shown above for the sake of clarity.

In the example above, 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 for that would be to either move the admin entry to ou=people, or to add an extra olcAuthzRegexp statement to specifically match the current DN of the admin entry:

olcAuthzRegexp: uid=admin,cn=example.com,cn=gssapi,cn=auth
  uid=admin,dc=example,dc=com

This particular directive could have been used in the final configuration described in this article, except that it was instead decided to change the name of the entry for the administrative user to one that is be matched by the existing olcAuthzRegexp statement. Either way, the result is the same.

Anyway, apply changes in the LDIF file with this command:

~# ldapmodify -QY EXTERNAL -H ldapi:/// -f ~/olc-mod2.ldif
modifying entry "cn=config"

modifying entry "olcDatabase={1}hdb,cn=config"

~# _

Rerun the previous ldapsearch command to verify that all of the changes have been made successfully.

Because of the new software that has been added and the changes that have also been made outside of the slapd server, it must be restarted before they will all have the desired effect:

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

5. Authentication test

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

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

Since the default ACL applied in step 5, modification 2.2.4, grants no access to unauthenticated users, this should result in no objects being found. The previously used SIMPLE bind for the admin user, using either its old or new name, does not work either:

~# ldapsearch -xWLLL -D cn=admin,dc=example,dc=com ou=people
Enter LDAP Password: piscivorus
ldap_bind: Invalid credentials (49)
~# ldapsearch -xWLLL -D uid=admin,ou=people,dc=example,dc=com ou=people
Enter LDAP Password: piscivorus
ldap_bind: Invalid credentials (49)
~#

That is because its plain-text password − the olcRootPW attribute − no longer exists. 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)
	additional info: SASL(-1): generic failure: GSSAPI Error: 
Unspecified GSS failure.  Minor code may provide more information 
(Credentials cache file '/tmp/krb5cc_0' not found)
~# _

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
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: admin@EXAMPLE.COM

Valid starting     Expires            Service principal
11/25/10 12:31:46  11/26/10 12:31:41  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
~# _

As stated before, authentication is necessary for all LDAP commands, but thanks to Kerberos' single-sign-on technology, this is no longer in any way inconvenient.


6. Adding a new user

The last thing to do is to test the system by adding a new user. Each account must consist of a Kerberos principal, a matching user ID object in ou=people, and a matching common name object in ou=groups. Start by using kadmin to create an account for a user ccolumbus with password NewWorld:

~# kadmin -p admin
Authenticating as principal admin with password.
Password for admin@EXAMPLE.COM: Lampropeltis
kadmin:  addprinc ccolumbus
WARNING: no policy specified for ccolumbus@EXAMPLE.COM; defaulting 
to no policy
Enter password for principal "ccolumbus@EXAMPLE.COM": NewWorld
Re-enter password for principal "ccolumbus@EXAMPLE.COM": NewWorld
Principal "ccolumbus@EXAMPLE.COM" created.
kadmin: q
~# _

Having completed that, the matching LDAP user objects are next. First, create a file, called ~/ccolumbus.ldif, with the following contents:

dn: cn=ccolumbus,ou=groups,dc=example,dc=com
cn: ccolumbus
gidNumber: 20001
objectClass: top
objectClass: posixGroup

dn: uid=ccolumbus,ou=people,dc=example,dc=com
uid: ccolumbus
uidNumber: 20001
gidNumber: 20001
cn: Christopher
sn: Columbus
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
loginShell: /bin/bash
homeDirectory: /home/ccolumbus
userPassword: {CRYPT}*

The value for the userPassword attribute is an invalid hashed version of a password. The password cannot simply be omitted, because it is a required attribute.

Then apply this change with the ldapadd command:

~# ldapadd -Qf ~/ccolumbus.ldif
adding new entry "cn=ccolumbus,ou=groups,dc=example,dc=com"

adding new entry "uid=ccolumbus,ou=people,dc=example,dc=com"

~# _

Now test if the new account works. First destroy the admin user's Kerberos ticket (not strictly necessary) and authenticate as the new user:

~# kdestroy
~# kinit ccolumbus
Password for ccolumbus@EXAMPLE.COM: NewWorld
~# _

Display the name of the Kerberos principal and tickets held in the credentials cache to confirm that authentication was successful:

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

Valid starting     Expires            Service principal
01/05/11 02:51:20  01/06/11 02:51:16  krbtgt/EXAMPLE.COM@EXAMPLE.COM
~# _

Finally, confirm that the new user has the correct LDAP identity:

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

This account is now ready to be used for logging into suitably configured clients.


7. See also
8. 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.

9. Sources
  • Carter G. 2003. LDAP System Administration. O'Reilly & Associates, Inc. ISBN 1-56592-491-6. 294 pp.
  • Massachusetts Institute of Technology. 1985-2010. 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: 2017-08-02, 17:50

©2003-2020 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.