For FreeBSD/Heimdal users who wish to use Kerberos to authenticate users with OpenLDAP, you've likely run into a big of a snag when using more recent (v1.0 or higher) version of Heimdal. This all stems from a security-related change that exists in lib/roken/issuid.c. The test is quite simple and basically detects whether or not the current process has been 'tainted' via uid/gid changes. According to the FreeBSD man page for issetugid(2), this specifically means:

A process is tainted if it was created as a result of an execve(2) system call which had either of the setuid or setgid bits set (and extra privileges were given as a result) or if it has changed any of its real, effective or saved user or group ID's since it began execution.

or, in other words, anything that was executed as root and later drops privs, like slapd. The reason this is problematic for us is that OpenLDAP relies on the environment variable KRB5_KTNAME to set which keytab to open. If a process was considered tainted, Heimdal will ignore this variable and use the system default.

I've seen various patches to the Heimdal libraries/OpenLDAP code that all workaround this issue, but I was interested in a more elegant solution and something that did not require me to maintain my own set of patches to deal with each time I went to upgrade code.

My solution was to simply utilize the chroot option with OpenLDAP. For FreeBSD users, you can simply do the following:

Change the default location of saslauthd's socket, build OpenLDAP with SASL support:

echo "SASLAUTHD_RUNPATH=/usr/home/ldap/var/run/saslauthd">>/etc/make.conf
echo "WANT_OPENLDAP_SASL=yes">>/etc/make.conf

You will need to rebuild openldap and/or saslauthd if the ports for these were already installed.

Create the required directory structure and copy some required files:

mkdir -p /usr/home/ldap/usr/local/etc/openldap /usr/home/ldap/dev /usr/home/ldap/lib /usr/home/ldap/usr/lib /usr/home/ldap/etc/gss /usr/home/ldap/var/run/openldap /usr/home/ldap/var/db/openldap-data /usr/home/ldap/usr/local/lib/sasl2 /usr/home/ldap/usr/local/libexec/openldap /usr/home/ldap/var/run/saslauthd
cp /etc/localtime /usr/home/ldap/etc;cp /etc/group /usr/home/ldap/etc

Update /etc/fstab by appending the required entries to /etc/fstab and mounting the new mounts:

cat /path/to/fstab-ldap >> /etc/fstab
mount -a

Create empty files in key locations to ensure that the ports framework does not delete these directories during upgrades. This is important as we will break our nullfs mounts if the original directories are removed:

touch /usr/local/lib/sasl2/.do_not_delete /usr/local/libexec/openldap/.do_not_delete /var/run/openldap/.do_not_delete

Copy over /etc/passwd and /etc/master.passwd to /usr/home/ldap/etc and update:

cp /etc/master.passwd /usr/home/ldap/etc; cp /etc/passwd /usr/home/ldap/etc; pwd_mkdb -d /usr/home/ldap/etc /usr/home/ldap/etc/passwd; vipw -d /usr/home/ldap/etc

$EDITOR will open and you should then delete any non-default users that aren't essential to OpenLDAP. (Make sure you leave the ldap user). The -d argument to vipw instructs vipw to work on the files in /usr/home/ldap/etc instead of the default (/etc)

Create a new krb5.conf inside the root with the required contents:

echo "[libdefaults]">/usr/home/ldap/etc/krb5.conf
echo "  default_keytab_name = FILE:/usr/local/etc/openldap/ldap.keytab">>/usr/home/ldap/etc/krb5.conf

You will likely want other customizations to this file. For example, specifying the default_realm option.

Copy your keytab for OpenLDAP to /usr/local/etc/openldap/ldap.keytab

Add the following to /etc/rc.conf:

syslogd_flags="-l /usr/home/ldap/var/run/log"
slapd_flags="-r /usr/home/ldap"

Start saslauthd/slapd and do some testing.