This page describes how to set up an OpenLDAP consumer server and an MIT Kerberos V slave server on the
same host so that Kerberos uses LDAP as it back-end database. It depends on a previously installed
Kerberos-OpenLDAP provider server, kls1.example.com. The system also relies heavily on timestamps, so reasonably
accurate time synchronization among all participating hosts is essential.

In this example, OpenLDAP and MIT Kerberos V are installed on a host running Debian 6.0 (squeeze). If followed
properly, the step-by-step process should produce an OpenLDAP provider server with a new DIT, followed
by a Kerberos master server that stores its database in that same DIT.

But, before the interesting parts can begin, it will first be necessary to install the operating system
on a new host called kls2.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. After the
initial installation of the operating system, make sure these packages are installed on the system as
well:

~# apt-get install ssh 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. Patching the source

Because of a bug in the current version of slapd, 2.4.23-7, the source code must
first be patched. Without it, slapd will return errors regarding the
olcDbURI attribute (necessary for the chaining configuration) and even
refuse to (re)start if it is configured that way. So, prepare the new host for a package build by
installing the following packages on the new host, kls2:

~# apt-get install dpkg-dev devscripts

This will result in 100 new packages being installed. Next, obtain the source:

~# cd /usr/src
~# apt-get source openldap

Three files will be downloaded and a directory, ./openldap-2.4.23/, will be
created that contains the source code. Soon, seven Debian packages will be built from it, but first
the various dependencies for these package must be downloaded and installed:

~# apt-get build-dep openldap

70 new packages will be installed as a result. Next, download and apply the patch:

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.

3. OpenLDAP install

Before starting the install process, run the following command to test if the previously installed
OpenLDAP provider server is actually available on the network:

This is because the realm, or rather the database for it, has not yet been created. However, this issue
will be dealt with later.

For now, edit /etc/krb5kdc/kdc.conf and modify these two lines − the same as
the Kerberos master server is configured:

max_life = 1d 0h 0m 0s
max_renewable_life = 90d 0h 0m 0s

Since the idea is for Kerberos to use OpenLDAP as its back-end database, see to it that the Kerberos KDC
service starts up after slapd and stops before it. To do this, edit
/etc/init.d/krb5-kdc and modify it as follows:

Prepair the OpenLDAP server to function as a back-end database for a Kerberos KDC. To do this, the
Kerberos schema file, installed in the previous step, needs to be converted to LDIF format. However,
since that task was already completed on kls1, save some time by simply copying
that file over to this server:

Besides the addition of the Kerberos schema, a number of other modifications need to be made to the
OpenLDAP configuration directory on kls2 regarding two existing entries. First
consider the current state of these objects:

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

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.

−

For the database definition, olcDatabase={1}hdb,cn=config, the
value for the olcRootDN attribute, which indicates the
administrative account for the database, will be changed to something completely
arbitrary. That is because there is no need for it to be part of the directory. However,
setting a value for this attribute is still mandatory for an OpenLDAP consumer in order
to allow it to store anything in the database that it receives, regardless of how the
ACLs are set.

2.2.

−

Since the administrative account is no longer part of the
dc=example,dc=com DIT, the olcRootPW
attribute will be deleted.

2.3.x.

−

All three of the current ACLs, each one being a value of an
olcAccess attribute, will be deleted. For clarity, this will be
done in reverse order, or else the index numbers would all have to be zero.

2.4.1.

−

The first new olcAccess attribute will determine access to
password information stored in the DIT. The OpenLDAP admin account will have read
access, anonymous users will have auth access and all other users will have no access.
This type of authentication may seem like a security issue, but since only IPC
connections (i.e. Unix domain sockets) will be used for this − no network connections −
there is nothing to worry about.

2.4.2.

−

The second new olcAccess attribute will determine access to the
ou=krb5 subtree, which will contain the Kerberos database. The
OpenLDAP admin user and the entry for the Kerberos administration server will have read
access to it, while the future entry for the Kerberos KDC will have read access.

2.4.3.

−

The fourth new olcAccess attribute will allow read access to the
base of the tree for things like supportedSASLMechanisms. This
allows clients to discover which SASL mechanisms an LDAP server supports.

2.4.4.

−

The fifth and last new olcAccess attribute is the default ACL that
will determines access to everything else in the tree. The OpenLDAP admin user will have
read access, authenticated users will have read access and anonymous users will have no
access.

2.5.

−

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 new directory tree 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. The same eq will also
prevent "bdb_equality_candidates" errors...

2.6.

−

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.7.

−

Idem for Organizational Unit (ou) objects.

2.8.

−

Idem for Domain Component (dc) objects.

2.9.

−

Idem for the uidNumber attribute.

2.10.

−

Idem for the gidNumber attribute.

2.11.

−

Idem for the memberUid attribute.

2.12.

−

Idem for the uniqueMember attribute.

2.13.

−

An equality, presence and substring index will be set for the
krbPrincipalName attribute.

2.14.

−

An equality index will be set for the krbPwdPolicyReference
attribute.

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

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

7. krb5.conf

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:

Note the absence of the ldap_servers statement from the list of
openldap_ldapconf options. This is possible because the Kerberos daemons use IPC
(Unix domain sockets) to connect to the LDAP back-end by default.

After /etc/krb5.conf has been saved, create the Kerberos log directory:

~# mkdir /var/log/krb5
~# _

To prevent the log file from growing too large, create a logrotate configuration file. Edit
/etc/logrotate.d/krb5-kdc and give it the following contents:

The various password stashes that were created previously on the provider − for the KDC database
master key, the KDC service (for cn=kdc-srv) and the Kerberos administration
server (cn=adm-srv) − are also required on this host. However, instead of
creating them from scratch as was done before, simply copy them from the provider:

Two files will be copied as a result: stash contains the KDC database master key,
while service.keyfile contains the two service passwords.

8. Provider modifications

Switch over to the provider server, kls1.example.com, to make some changes
there. Start by creating a new LDAP entry that will be used to represent and authorize
kls2 to read the entire DIT. Start by creating a file,
~/kls2.ldif, with the following contents:

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

1.1.

−

For the root object, cn=config, a statement needs to be added to
map LDAP service principals from their SASL/GSSAPI names to their matching Common Name
objects in ou=consumers. However, to position it before the
default mapping, ou=people, the latter must first be deleted.

1.2.1.

−

Then the statement to map LDAP service principals from their SASL/GSSAPI names to their
matching Common Name objects in ou=consumers is added.

1.2.2.

−

Then the default mapping for ou=people is restored unchange, but
importantly still positioned last.

2.1.

−

For the database definition, olcDatabase={1}hdb,cn=config,
an equality index is set for the entryUUID attribute. That is
because, with syncrepl replication, this attribute is added to all
entries in the database. Use of the olcSpSessionlog option (see
description below) requires searching for this attribute, so it is recommended (but not
required) to set an equality index for it. Doing so on the provider server can improve
session log performance considerably.

2.2.

−

Similarly, it is recommended to add an eq index for the entryCSN
attribute when making use of the olcSpCheckpoint option.

2.3.x.

−

All five 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 to match them would all have to be zero.

2.4.1.

−

The first ACL, for accessing password information stored in the DIT, will be restored,
but with added read access for all members of ou=consumers.

2.4.2.

−

The second ACL, for access to the ou=krb5 subtree, will be
restored, but with added read access for all members of
ou=consumers.

2.4.3.

−

The third ACL, for access to the loginShell attribute, will be
restored unchanged.

2.4.4.

−

The fourth ACL, to allow read access to the base of the tree for everyone, will be
restored unchanged.

2.4.5.

−

The fifth ACL − the default − will also be restored unchanged.

3.

−

For the cn=module{0} entry, an extra
olcModuleLoad attribute will be added to load the
syncprov module into the slapd process. This
is because it was not compiled statically into /usr/sbin/slapd.

4.

−

A new entry, olcOverlay={0}syncprov, will be added to the
cn=config DIT to activate and configure the
syncprov module.

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

Rerun the previous ldapsearch command to verify that all of the changes have been
made successfully. Note that index numbers have been added automatically to the RDNs for the
syncprov overlay, as well as to the various olcAuthzRegexp
and olcAccess attributes.

For some reason, despite the runtime configuration, the provider still has to be restarted at this
point, or later on it will not properly map SASL-GSSAPI service principals to
ou=consumers and consequently not allow the entire DIT (including the
ou=krb5 subtree) to be replicated:

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

9. Kstart

Return to kls2. To keep its copy of the LDAP database in sync, the consumer must
contact the provider and authenticate itself just like any other client. It has previously been shown
how to do this with a simple bind and a password, but in this case Kerberos will be used to take care of
both slapd consumer authentication to the provider and encryption of the
entire replication process. To make this possible, an initial Kerberos ticket (a TGT) must be obtained
automatically on behalf of the openldap user, which owns the
slapd process, and it must be renewed regularly. One way to do this is to run
kinit -k with a cron job, but a better solution is to use a modified version of
kinit, called k5start. Install it with:

~# apt-get install kstart

This is the only package that gets installed as a result:

kstart 3.16-3 Kerberos kinit supporting AFS and ticket refreshing

To configure it, just add this one line to the end of the /etc/inittab file to
start running k5start in the background soon after the system boots up:

Determine the principal to authenticate based on the first entry in the Kerberos
keytab file. Must be used with the -f option.

-f /etc/krb5.keytab

−

Specifies the full path of the Kerberos keytab file.

-K 10

−

Reawaken the daemon every 10 minutes to check if the ticket needs to be renewed.

-l 24h

−

Set the ticket lifetime to 24 hours (to match the actual ticket lifetime used in this
example).

-k /tmp/krb5cc_105

−

Use the file /tmp/krb5cc_105 as the ticket cache. The number at the end of the file name
*must match* the UID (105 in this example) of the user on behalf of whom
the ticket is maintained (see option -o). Otherwise this slapd
server will not authenticate properly and the result will be a
ldap_sasl_interactive_bind_s failed (-2) error.

-o openldap

−

The name of the user account that is to become the owner of the ticket cache file (see
option -k).

After saving this modification to /etc/inittab, start
k5start for the first time by forcing init to reload its
configuration file:

~# kill -HUP 1

A new ticket cache file, /tmp/krb5cc_105, should be created almost immediately as
a consequence.

10. Slapd kerberization

Just as kls1 has already been configured to require Kerberos authentication for
all LDAP communication over the network, so the same must now be done for kls2. A
number of requirements have already been met, but there are still a few things left to do. First,
install this one package:

What follows is a list of changes that will be made to the LDAP runtime configuration on
kls2:

1.1.

−

For the root object, cn=config, an
olcAuthzRegexp attribute will be added to act as a default,
mapping the SASL-GSSAPI names of all authenticated users to names in
ou=people, whether matching LDAP entries exist there or not.

1.2.

−

An olcSaslRealm attribute will be added to specify the SASL realm,
in this case a Kerberos realm.

To make the above changes to the slapd runtime configuration on
kls2, create an LDIF file, called ~/olc-mod2.ldif, with
the following contents:

All of the above changes have already been made to the LDAP runtime configuration on
kls1, except that this server will not have an
olcAuthzRegexp mapping for ou=consumers to support incoming
connections from other servers.

Only three changes will be made to the slapd database definition on
kls2:

1.1.

−

With syncrepl replication, the entryUUID
attribute is added to all entries in the database. Use of the
olcSpSessionlog option (see description below) requires searching
for this attribute, so it is recommended (but not required) to set an equality index for
it. Doing so on the provider server can improve session log performance considerably.

1.2.

−

Similarly, it is recommended to add an eq index for the entryCSN
attribute when making use of the olcSpCheckpoint option.

1.3.

−

The olcSyncrepl attribute will be added to configure the LDAP Sync
Replication engine using SASL and GSSAPI.

To make the above changes to the slapd runtime configuration on
kls2, create an LDIF file, called ~/olc-mod3.ldif, with
the following contents:

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

At this point, the consumer will already have synchronized its database with the provider. A quick
slapcat will confirm this. However, the two copies of the database are not really
in sync: the domain component and the admin user object (with password somalica) have not been
replaced with their alter egos from the provider. To fix this, the consumer's database must
resynchronized with the provider:

This will stop the LDAP service on kls2, delete its copy of the database and
restart the service, at which point it will fetch a fresh copy from the provider. Run
slapcat once more to see the difference.

12. Kerberos server start

Start the Kerberos slave KDC server for the first time:

~# /etc/init.d/krb5-kdc start
~# _

If there are no errors, run the following command to verify that the new MIT Kerberos V master server is
indeed available on the network:

LDAP Sync Replication does present one important problem for LDAP clients: the database containing the
DIT on a consumer server is always read-only. To allow clients to make modifications to the DIT anyway,
the consumer must either refer its clients on to the provider, or proxy their requests. Both of these
options will be arranged by modifying two existing entries in the consumer server's configuration DIT
and adding two new ones. The following search command on kls2 will verify their
current status/absence:

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

1.

−

For the olcDatabase={1}hdb entry, the
olcUpdateref attribute will be added with a URL for the provider
server. This referral will then be passed directly on to clients whenever they ask
slapd to modify the read-only replica, e.g. to change their shell
type. Unfortunately, although this is the preferred method, not all LDAP clients
understand referrals. Therefore, it is a good idea to also configure the
chain overlay, which allows automatic referral chasing, i.e. for
the consumer to act as a proxy.

2.

−

For the cn=module{0} entry, an additional
olcModuleLoad attribute will be added to load the
back_ldap (LDAP backend database) module into the
slapd process. This will make the chain
overlay available, which happens to be built into the back_ldap
module.

3.

−

A new entry, olcOverlay={0}chain, will be added to activate and
configure the chain overlay. This will allow
slapd to act as a proxy, automatically chasing referrals on behalf
of clients. Although this overlay has very few directives of its own, those belonging to
the LDAP backend assume a special meaning when used in conjunction with it.

4.

−

Another new entry, olcDatabase={0}ldap, will be added to configure
the LDAP backend database. This is not an actual database, but provides basic proxying
functionality, in this case for the chain overlay, including configuration
directives necessary for it to contact the provider server. Some of its details are
explained below.

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

Here, the olcDbIDAssertBind directive defines the parameters of the authentication
method used by kls2 to authorize connections from authenticated users. It has a
number of different options, a few of which are used here:

bindmethod

−

The method with which the consumer server authenticates to the provider. Here, the
sasl authentication method is used, in which case the saslmech attribute
is also required.

saslmech

−

This option, for SASL mechanisms, can have any of a number of different values,
depending on the authentication mechanism used. Here, gssapi is specified.

mode

−

When the mode self is used, the client's identity will be asserted when a
request is proxied.

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

15. Proxy authorization

Before the chaining configuration can work, more changes first have to be made to the OpenLDAP provider
server, kls1.example.com. What is required is something called SASL proxy
authorization. With this mechanism it is possible to allow an authenticated user, such as the
consumer server in this example, to assume the identity of other users and use that to relay their write
requests on to the provider server. The ability to assume another user's identity is important, as it
would otherwise not be possible to enforce existing access rules.

Two changes are needed to enable proxy authorization. First, the cn=kls2 LDAP
object must be modified to include two authzTo attributes, which will allow it
to act as an authorization proxy for certain users. Second, an olcAuthzPolicy
directive must be added to the cn=config DIT.

Start by creating an LDIF file on kls1, called
~/kls2-mod.ldif, with the following contents:

The authzTo attribute is a source rules that determines which user identities a
consumer server is allowed to assume. In this case its value is a regular expression that matches all
uid objects in the ou=people,dc=example,dc=com container.

This statement enables proxy authorization using rules associated with the authzTo
attribute of the authentication DN (in this case cn=kls2). Without this, the
authzTo attribute that was added to the cn=kls2 entry would
be ignored.

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

16. Proxy auth test

This last step will test whether the proxy authorization actually works. This is easily done on the
consumer server using the ldapadd command. This exercise will also be used as an
excuse to create a new user account. Start by using kadmin to create an account
for a user bbeamon with password longjump:

Having completed that, the object is now to test the proxy authentication configuration by creating a
matching LDAP user account for bbeamon. If this works, the changes will be
immediately available on the consumer server (or within five minutes if refreshOnly replication
is used). First, create a file, called ~/bbeamon.ldif, with the following
contents:

This confirms that kls2 is using its Kerberos ID,
ldap/kls2.example.com@EXAMPLE.COM, which is then translated by the
olcAuthzRegexp statement on kls1 to
cn=kls2,ou=consumers,dc=example,dc=com, which is then authorized to act as a proxy
for uid=admin,ou=people,dc=example,dc=com, which in turn is allowed to add
the new cn=bbeamon,ou=people,dc=example,dc=com entry.

For another confirmation of success, a search for uid=bbeamon should show that
this entry has indeed been added to the DIT:

Note that the password is not visible. The admin user may be authorized to add new user objects,
passwords included, from kls2, but has no special priviliges on that host to view
all of their contents. If the admin account is used to execute the same command on
kls1, then the password will be shown.

17. Bug warning

Unfortunately, there is another bug in the current version of slapd for which
there is, as yet, no patch. It only affects proxy authorization when using SASL binds together with the
GSSAPI mechanism − replication is unaffected. With version 2.4.23-7, it may be possible to install
the provider and a consumer and complete the above test successfully, but this good behavior is likely
to cease later on, such as after rebooting one or both systems.

The problem is that, when the consumer authenticates to the provider, it inexplicably does so with a
SIMPLE bind (method=128), instead of with SASL-GSSAPI (method=163). Consequently, no new objects can be
added to the DIT from the consumer and the client returns with an error: