Author

LDAPv3

Last updated

Turbo Fredriksson


Monday, August 7, 2017



I wrote this HOWTO around 2000 and rewrote it in book form in 2001. For many years, I sold this from this page (and managed to seel 216 copies, which I don't think is to bad considering) and accepted PayPal transfers for it.

As of August 7, 2017 I now sell it through Amazon. Currently only a Kindle version is available, but I'm working on getting a paperback publishing working at the moment.
Please see Implementing LDAPv3 by Turbo Fredriksson for the book on Amazon.

Preface

These are my notes about how I got OpenLDAP (v2.0.7), OpenSSL (v0.9.5a), SASL (v1.5.24) and MIT KerberosV (v1.2.2) to work together. This combination (according to some RFC I can't remember the number of) is what's called LDAPv3.

I have since I initially wrote this HOWTO, upgraded some packages. The information about this can be found in the Updates section. At the time of this writing (Sunday, August 19, 2001) I have not successfully compiled and installed OpenLDAP v2.0.11! I'm still working heavily on this, it is at the top of my todo list, since I really (!!) need to upgrade because of a resent security alert.

You might want to read the section LDAPv3, why bother to see the reasoning for this quite complicated issue. It deals with all the discussed systems, such as SSL/TLS, SASL, LDAP and Kerberos, and why we should run such a complicated system in the first place.

Required knowledge

Reading and following this documentation will require a knowledge of LDAP in general, knowing how to create and install software 'from scratch' (i.e. building from source/tar balls) and also how to configure OpenLDAP and also how to administer it... This issue (LDAPv3) is not for the beginner, and I will usually not answer any questions in the format of 'I get this when i try to configure/make/install this-or-that-software'! In short, you will be required to 'read between the lines' of this document, and draw you own (correct! :) conclutions. That being said, it's not as difficult as it might seem. If you belong to the group of people that I here call 'beginner', I recommend installing the software while reading the OpenLDAP web page on OpenLDAP administration.

Note about building software

I'm running Debian GNU/Linux on all my machines, both on the Intel platform and the Sun SPARC, and prefer to use the Debian package system as much as I can. Since I'm also a Debian developer, I have a fairly good know-how about making a Debian package. In my pursuit of getting this to work, I had to modify some of the default packages since they lacked some features that is necessary. I will try to guide you through the process of rebuilding you package, if you to are running Debian GNU/Linux. If you are not, I will at least tell you which parameters to configure etc. the Debian package are using, giving you at least SOME hint on getting all this software compiled and installed :). Also, the progress and fast moving target that the Internet and the OpenSource movement are, the versions I have described here are most likely already out of date. Two weeks after I started with this HOWTO, Cyrus-SASL had released version 1.5.26, that fixed the problem described in the section Bugs in Cyrus SASL, v1.5.24. But I'm deploying this any day now on a live server, so I won't be able to test if it indeed fixes the problem.

Note about text notation:

Wherever you see the <> (in bold) part, it means that that's where you input your own information. So for example, when you see

<YOUR KERBEROS REALM>

It means that you should put your realm in there, like this:

BAYOUR.COM

Note, that you should NOT include the characters < and >!.

Also, I assume in this document that the configuration for OpenLDAP2 is installed into /etc./ldap. If you haven't installed it there, please remember to exchange that path to your path.

Disclamer

Please don't send any 'please help me' mails directly to me. Direct it to the appropriate mailing lists for help instead, you stand a much better chance of getting a reply if you do. I just don't have the time (or knowledge) to help anyone/everyone in private.

Any mails sent to me about any of this will be replied to on a public list.

Table of Contents – Core software

BerkeleyDB

BerkeleyDB from SleepyCAT is, from what I have read/tried a better database back-end than gdbm, ndbm and db. It is used by OpenLDAP to store the database on disk. Your call, you don't have to use it, but I like it and have been using it all the time.

Building and installing Berkeley DB

OpenSSL

This is the software that will give us TLS and SSL enabled LDAP (secure and encrypted communication). It have nothing to do with AUTHENTICATING a user, it just gives us a way to encrypt traffic to/from the LDAP server.

Build OpenSSL

Creating SSL certificate

MIT Kerberos V

This is what we will use to store password in. It will, as a bonus, also give us a 'single-sign-on' system (that is, you enter your passphrase/password once, and the 'ticket' that is returned, will be used for login authentication).

Building MIT Kerberos V

Bugs in MIT Kerberos V, v1.2.1

Bugs in MIT Kerberos V, v1.2.2

Installing MIT Kerberos V

Configure Kerberos

Preparing the DNS for KerberosV

Kerberos config file

Create KerberosV realm

Setting up KerberosV access rights

Testing MIT Kerberos V

Cyrus SASL

This is the layer between OpenLDAP and Kerberos. It gives you a secure way of AUTHENTICATING access to the LDAP server. It will not encrypt the actual traffic (even though the authentication session is encrypted).

Building Cyrus SASL

Bugs in Cyrus SASL, v1.5.24

Build the Cyrus SASL packages

Installing Cyrus SASL

Testing Cyrus SASL

OpenLDAP

Well, we all know what this is, don't we? It's a free LDAP server. A very (VERY) good one to, in my opinion (even though I don't have much experience in other LDAP server :).

Building OpenLDAP v2

Bugs in OpenLDAP, v2.0.7

Installing OpenLDAP v2

Configuring OpenLDAP v2

Configure OpenLDAP to use the new SSL certificate

Changes to the OpenLDAP config file

Changes to the OpenLDAP startup script

The OpenLDAP config file

The OpenLDAP access file

Creating a LDAP service key

Populate the database to allow simple bind as user

Modify the LDAP database to allow simple bind as user.

Notes about 'userPassword: {KERBEROS}'

Testing OpenLDAP v2

Testing OpenLDAP, simple/anonymous bind

Testing OpenLDAP, simple/anonymous bind, with SSL/TLS

Testing OpenLDAP, using your Kerberos ticket

Testing OpenLDAP, using your Kerberos ticket, with SSL/TLS

Testing OpenLDAP, simple user bind, with SSL/TLS

Setting up secure replication

Replication configuration, slave server

Replication configuration, master server

Creating a replication principal

Automatically getting a ticket before starting slurpd

Keeping replication ticket updated

Give the replicator access to the database

Table of Contents – Miscellaneous software

Some software to ease administration and migration to LDAP/Kerberos are these softwares. I'm not going to go in to how to get this configured and installed. That's an exercise for the reader :). They have no real relevance for getting LDAPv3 to work, but I thought I'd plug for them anyway, because I have found them invaluable in using and administrating LDAP in general.

LibNSS-LDAP/LibPAM-LDAP

The LDAP name service switch (NSS) module is an Open Source project to integrate LDAP as a native name service under Linux, Solaris, and other operating systems. The LDAP pluggable authentication module (PAM) is an Open Source project to integrate LDAP authentication into operating systems supporting the PAM API, such as Linux, Solaris, and HP-UX.

Building and installation

Downloading source

Building packages

Install the newly made packages

Concurrent Version System

Not related with OpenLDAP really, but I'm going to show you a little how to get CVS linked and compiled with GSSAPI so that we can use our Kerberos key for authentication to the cvs server.

Building CVS

Configure options

With Krb4 option

Creating a CVS service key

Cyrus IMAP/POP3

Quite naturally we would like the IMAP and POP3 server to authenticate directly with SASL to the Kerberos database as well.

Building Cyrus IMAP and POP3 server

Configure Cyrus IMAP and POP3 server

Creating a IMAP/POP3 service key

OpenAFS

From the project page:

AFS is a distributed filesystem product, pioneered at Carnegie Mellon University and supported and developed as a product by Transarc Corporation (now IBM Pittsburgh Labs). It offers a client-server architecture for file sharing, providing location independence, scalability and transparent migration capabilities for data.

Kind'a like NFS with Kerberos authentication. Although AFS is a (network) file system and have don't have anything to do with LDAPv3, it is 'essential' for a distributed (and load balanced) server cluster.

OpenAFS

Building OpenAFS

Build OpenAFS kernel module

Installing OpenAFS

OpenAFS KerberosV support software

Building OpenAFS KerberosV support software

Installing OpenAFS KerberosV support software

Configure OpenAFS KerberosV support software

OpenAFS PAM module

Building and Installing the OpenAFS PAM module

Configure OpenAFS PAM module

Configure OpenAFS

Creating a AFS service key

Putting the AFS service key into the AFS KeyFile

Mount the AFS volume

Create the new cell

Setup the cell configuration files

Getting a Kerberos ticket and a AFS token

Setting up root volumes

Testing the OpenAFS softwares

Testing OpenAFS KerberosV support software

Testing OpenAFS PAM module

Samba

The idea here is to make a Windows 2000 server out of our Linux/UNIX box. In theory (at least from what I have understood from mails on the openldap-software list) this should be possible if using Krb5, SASL, LDAP and Samba. I'm currently investigating this issue.

Check back every now and then to see how far I have got with this.

Building Samba/Samba-TNG

Compile options

Make string

Directory Administrator

From the project page:

Designed with the only focus of being a tool to easily manage UNIX users and groups in an LDAP directory, corporate information, access controls, and LDAP mail routing.

I'm currently writing a patch for this, to allow it to add the principal to the KDC as well as adding the user stuff in the LDAP server. Also in progress are SASL and SSL/TLS binds to the LDAP server.

PAM/Kerberos migration module

I haven't gotten this to work yet, but I'm working on it. From the source code README:

pam_krb5_migrate is a stackable authentication module (for PAM) that takes a user name and password from an earlier module (such as pam_ldap or pam_unix) in the stack, and attempts to transparently add them to a Kerberos realm using the Kerberos 5 kadmin service. The module can be used to ease the administrative burdens of migrating a large installed user base from pre-existing authentication methods to a Kerberos based setup.

Looks nice to me, if I just could get it to work!

Have a look at Migrating existing users for more information about migrating existing users.

QMAIL with LDAP patches

It is possible to have QMAIL look in a LDAP database for it's email addresses, and to have QMAIL's pop/imap server authenticate the users from a LDAP database.

Sendmail and LDAP

I'm not using Sendmail, in fact, I dislike sendmail quite heavily. In my opinion it's the most insecure piece of software you can install on a UNIX (like) platform. But, granted, it's the only (mail) server that can cope with hundred of thousands (and above) of mails. I'll see if I can dig up some information about this, and add this to this HOWTO/FAQ.

In the mean time, have a look at the URL: http://www.stanford.edu/~bbense/Inst.html.

Miscellaneous information

Here you can find some reference material, and copies of my configurations discussed in this document

Updates

Most things in the Open Source movement change quite fast, and software naturally gets updated. Instead of adding a 'updates' section under each software product, I have gathered them here instead, sorted by the latest version at the time of writing.

BerkeleyDB

v3.3.11







OpenSSL

v0.9.6a

v0.9.6b






OpenLDAP

v2.0.10

v2.0.11

v2.0.14

v2.0.18

v2.0.21

v2.0.22

v2.0.23

CyrusSASL

v1.5.27







MIT KerberosV

v1.2.4







My configuration files

These are copies on all my configuration files. They are documented here in the document, but just a preventive measure, I thought that I'd include the actual files as well.

Master LDAP server

Slave LDAP server

PAM/LDAP files

Misc files

Reference material

This are some misc information about where to find more information about RFC's and Internet drafts etc.

Patches

LDAP

LDAPv2

LDAPv3

Authentication

SASL

Kerberos

Other

Problems that can occur

After getting all this software configured, compiled and installed, it will need to work independent of the other. That is, each piece needs to work before we can start gluing them together. There's always something that can go wrong. Here's examples and solutions for some of (the most common?) ones.

Problems when the KVNO don't match up.

No such attribute error

No such object error

Local error

Problems with ACL's

SLAPADD problems/messages

Attribute type undefined

Attribute not allowed

Missing required attribute

Shortcuts

For the lazy ones, why not take a look at this section.

No guaranties though!

APT configuration

These are the packages that are available for installations

KerberosV server

KerberosV client

KerberosV services

PAM/NSS

Miscellaneous

OpenSSL

Cyrus SASL

OpenLDAP2

OpenAFS

PostgreSQL

Migrating existing users

Some notes about migrating an existing user database, be it the old fashioned /etc/passwd approach, NIS/NIS++ etc.

Thanx to

I would like to thank the following people, in no special order(!), for giving me input on this document. I apologize if I forgot someone (I started this thank you part quite late in the process :).

Johann Botha

For noting that we have to start the SLAPD server on port 636 aswell

Allan Streib

For the patch to Cyrus SASL, v1.5.27

Jorge Santos

For pointing out that Berkeley DB 3.2.9 is in Debian GNU/Linux under the name libdb3/libdb3-dev. Also found a missing '-exec' in a find command (in the Building Packages subsection of the libpam-ldap and libnss-ldap section).

John Rodger

Which had a one month newer version than the file I had in my backup when I lost the whole page because of user error :)

Keith R Lally

For finding the latest version of the lost document.

Jasper Möller

For some question and remarks about the DNS setup, migration of existing users, SSL certificates etc.

Kim Holburn

Replication configuration and setup

Thanx for all the support and input

Building required software

OpenSSL

Installing the Debian GNU/Linux package

This package I just installed right of the Debian GNU/Linux non-US FTP site, using apt-get install libssl09 libssl09-dev openssl. The development package are needed later when building OpenLDAP v2.

Building OpenSSL from scratch

For those of you that don't use Debian, this are the configure command line:

./Configure shared --prefix=/usr --openssldir=/usr/lib/ssl

Then build the package by issuing this command:

make -f Makefile.ssl all

Install newly built OpenSSL software

To install OpenSSL after executing make, issue this command:

make -f Makefile.ssl  install.

That's about it about OpenSSL I think, but as I said, I just installed the Debian packages, and where done with it :)

Creating SSL certificate

To create the certificate that OpenLDAP will use, we issue the command openssl like this:

openssl req -new -x509 -nodes -out server.pem -keyout server.pem -days 365

This is what the command will output when I do it. The first line might be different in your installation, and some of the wordings might have changed if you are using a different version than me. The important information you should input is on the last seven lines (starting with Country Name and ending with Email Address. Parts in bold+underline is my responses:

Using configuration from /usr/lib/ssl/openssl.cnf
Generating a 1024 bit RSA private key
.....++++++
.................................................++++++
writing new private key to 'server.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:SE
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:Gothenburg
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:egeria.bayour.com
Email Address []:turbo@bayour.com

It is very important that you don't give localhost for the Common Name. It should be your hosts FQDN (Fully Qualified Domain Name). That is, what's your IP address, and what name does the DNS tell you belong to this IP address?

NOTE: I can not stress this enough! 99% of all the "SSL/TLS don't work" mails on the openldap-software list is due to the fact that someone have not used a correct Common Name in the SSL certificate! An IP address won't work either. It can however be used to get your common name from the DNS. Find your IP address and issue the command

host <YOUR IP ADDRESS HERE>

The first line that reads Name: is what you should use as your common name!

Keep the file server.pem created here handy, we will need it later when setting up secure replication below.

Also, remember that since you're specifying the host name in the certificate (which is required), you must have one certificate for each of your LDAP server (if you're doing replication to other machines).

BerkeleyDB

Building and installing Berkeley DB

This software don't exists as Debian packages, so I had to make and install it my self. To do this, I just downloaded the tarball from the sleepycat website. I got version 3.0.55, and I see that the version on there site is now 3.2.9. I can't guarantee that that will work, but be my guest to try it. If it shouldn't work, you can get SleepyCAT v3.0.55 at my site. This is how to build the software after unpacking it in your favourite source directory.

cd build_unix
../dist/configure
make
make install

That's about all I have to say on the issue of installing Berkeley DB mostly because there's not much more to it! :).

UPDATE: With Debian GNU/Linux 2.3 (aka Woody) and later, BerkeleyDB 3.2.9 is availible in the libdb3 and libdb3-dev packages, so you won't really need to download and install BerkeleyDB from source. Just execute

apt-get install libdb3 libdb3-dev

and off you go...

MIT Kerberos V

Building MIT Kerberos V

Now, as promised I will here give you the configure parameters that the Debian packages are using:

--prefix=/usr
--enable-shared 
--with-ccopts="-g -O2 -D_REENTRANT"
--localstatedir=/etc
--mandir=/usr/share/man
--without-tcl

Then, just make all is executed.

Bugs in MIT Kerberos V, v1.2.1

NOTE1: As said above, there is a bug in all Kerberos implementations deriving from MIT KerberosIV (yes, that spells out 4, it's a very old bug!). The bug is that it have a temporary files race condition. For those that have a version lower than 1.2.2 and don't want to/can't upgrade, there's a patch to be found at the MIT Kerberos advisories site. For you that run Debian, please see the Building Cyrus SASL example how to make a Debian package with this patch.

NOTE2: Also, there have been discovered a buffer overflow vulnerability in the telnetd that is distributed with Kerberos 5, v1.2.2. See the URL http://www.securityfocus.com/bid/3064 for more information about this vulnerability. A patch for this bug can be found at the URL http://web.mit.edu/kerberos/www/advisories/telnetd_122_patch.txt.

NOTE3: Debian are now distributing MIT Kerberos v1.2.2 in it's unstable distribution, so just execute

apt-get update && apt-get upgrade

(if you are getting your packages from Internet, and not from CD that is). It should be installed into the testing and then the stable tree after a couple of weeks (if there isn't any serious bugs against the packages)...

Bugs in MIT Kerberos V, v1.2.2

NOTE1: A buffer overflow bug have been found in wu-ftpd (and therefor gssftpd which is the origin of part of the wu-ftpd). Have a look at the advisory at http://web.mit.edu/Kerberos/www/advisories/ftpbuf.txt. The patch is also located without the advisory text on the URL: http://web.mit.edu/Kerberos/www/advisories/ftpbuf_122_patch.txt.

Installing MIT Kerberos V

To prepare the Kerberos installation, one should read the Kerberos FAQ. This FAQ was a very good guide for me to learn (or at least give me a rough understanding of Kerberos :). Basically nothing in there needs to be done when using the Debian GNU/Linux packages. I just used the default ones, even though the version I installed first had a /tmp race condition bug. I have now upgraded to version 1.2.2-1 (the -1 is the Debian patch version). The installation is very straight forward, just answer the questions correctly :). However, there are some stuff that needs to be done before (or after if you like) the installation begins. You will need a working DNS system. And the KDC/KAdmin. server should really be on a separate machine, but I didn't have that luxury, so I installed it on the main system (I'll make a separate KDC/KAdmin/LDAP server later, but not now).

Configure Kerberos

Preparing the DNS for KerberosV

The DNS should be setup like follows to get full Kerberos network support. However, it seems like very few programs (OpenLDAP doesn't seem to) actually use the SRV entries, which is 'Server Location' entries. So if you don't want to/can't change the DNS, it is not required...

NOTE: I upgraded my Kerberos server (from 1.2.2 to 1.2.4) the other day, and I got the question if my DNS was listing the location of my KDC's (which it does) so maybe Kerberos is now using the SRV entries. I haven't verified what's the case here, it doesn't matter that much to me at the moment... :)

; IP addresses to the Kerberos/LDAP servers...
kerberos                IN      A       <IP ADDRESS OF YOUR 1st KERBEROS SERVER>
kerberos-1              IN      A       <IP ADDRESS OF YOUR 2nd KERBEROS SERVER>
kerberos-2              IN      A       <IP ADDRESS OF YOUR 3rd KERBEROS SERVER>
ldap                    IN      A       <IP ADDRESS OF YOUR 1st LDAP SERVER>
ldap-1                  IN      A       <IP ADDRESS OF YOUR 2nd LDAP SERVER>
ldap-2                  IN      A       <IP ADDRESS OF YOUR 3rd LDAP SERVER>
;
; Master setup
_kerberos               IN      TXT     "<YOUR KERBEROS REALM>"
_kerberos-master._udp   IN      SRV     0 0 88 kerberos
_kerberos-adm._tcp      IN      SRV     0 0 749 kerberos
_kpasswd._udp           IN      SRV     0 0 464 Kerberos
;
; Round-robin setup
_kerberos._udp          IN      SRV     0 0 88 kerberos
                        IN      SRV     0 0 88 kerberos-1
                        IN      SRV     0 0 88 kerberos-2
_ldap._tcp.<DOMAINNAME> IN      SRV     0 0 389 ldap
                        IN      SRV     0 0 389 ldap-1
                        IN      SRV     0 0 389 ldap-2

Don't forget to make sure that the revers look-up works. Much of my problems where that the KDC couldn't (wouldn't?) find my FQDN (Fully Qualified Domain Name => Host name + Domain name) for my IP address, or the other way around.

And what's this SRV stuff doing in there? That's kind'a cool feature in the BIND DNS server. See the page about specifying the location of services RFC for more about this.

The main KerberosV packages we will have to install on the KDC (Kerberos server), are the following packages.

krb5-kdc
krb5-admin-server
libkrb5-dev

To do this, all you have to do is execute (as root of course :) the command line

apt-get install krb5-kdc krb5-admin-server libkrb5-dev

and this will install and configure a KDC and Kerberos admin server. We will need the development package later on when we build SASL. Since I'm running Debian GNU/Linux, I just installed these default Debian packages, which also configured the stuff for me. What is also good to have is these packages (just add those you want at the end of the apt-get line. These packages should be installed on the Kerberos client. In my case, the KDC lives on my main server, so I installed these packages on the same system as the packages above. This is not recommended, but I had no choise.

krb5-doc
krb5-user
krb5-clients

If you like to offer Kerberos secured services like ftp, rsh, telnet etc, these are the packages you will also need to install (I did):

krb5-ftpd
krb5-rsh-server
krb5-telnetd

Now, apt is so very clever that it will download and install any packages that the above packages are dependent on. So, for example, if you are running with an older libc6 than the krb5 packages needs, apt will download and install (!) those for you to.

Kerberos config file

Now, there seems to be something wrong in some install script or other, because sometimes when I installed Kerberos, the file /etc/krb5.conf wasn't created correctly. I installed, unistalled back and fourth to try to figure out how to get this to work. I will here include the file I have, and it should work for most cases. As said, this seems to be a random problem, and I have not been able to successfully duplicate the problem, so double check the file for accuracy first.

<libdefaults>
        default_realm = <YOUR KERBEROS REALM>
        default_tgs_enctypes = des3-hmac-sha1 des-cbc-crc des-cbc-md5
        default_tkt_enctypes = des3-hmac-sha1 des-cbc-crc des-cbc-md5
        permitted_enctypes = des3-hmac-sha1 des-cbc-crc des-cbc-md5
        krb4_config = /etc/krb.conf
        krb4_realms = /etc/krb.realms
        kdc_timesync = 1
        ccache_type = 4
        forwardable = true
        proxiable = true

<realms>
        <YOUR KERBEROS REALM> = {
                kdc = kerberos.<YOUR DOMAINNAME>:88
                admin_server = kerberos.<YOUR DOMAINNAME>:749
                default_domain = <YOUR DOMAINNAME>
        }

<domain_realm>
        .<YOUR DOMAINNAME> = <YOUR KERBEROS REALM>

<logging>
        kdc = FILE:/var/log/kerberos/krb5kdc.log
        admin_server = FILE:/var/log/kerberos/kadmin.log
        default = FILE:/var/log/kerberos/krb5lib.log

<login>
        krb4_convert = false
        krb4_get_tickets = false

Create KerberosV realm

When the DNS is prepared and the packages installed, we need to create the realm data in the KDC. You will be notified by this by the Debian installer scripts. The command that needs to be executed are krb5_newrealm. It will create the stash file for you, and also create some service keys. This is what the script does (for those of you that aren't running Debian):

kdb5_util create -s
kadmin.local -q "ktadd -k /etc/krb5kdc/kadm5.keytab kadmin/admin"
kadmin.local -q "ktadd -k /etc/krb5kdc/kadm5.keytab kadmin/changepw"
/etc/init.d/krb5-kdc start || true
/etc/init.d/krb5-admin-server start ||true

The last two lines are however a little premature. We need some form of administrator user in the KDC to, so execute this line

kadmin.local -q "addprinc krbadm@<YOUR KERBEROS REALM>"

Also, while we are creating administrators, we will create a LDAP administrator principal. This principal will have full access to the LDAP database. For those of you that are migrating from OpenLDAP1 or OpenLDAP2 without SASL etc (or basically any other LDAP server I guess) will recognise this as the AdminDN (or rootdn as it's called sometimes).

kadmin.local -q "addprinc ldapadm@<YOUR KERBEROS REALM>"

Setting up KerberosV access rights

Also, some access lists should be installed/configured. In the file /etc/krb5kdc/kadm5.acl you should enter these lines:

kadmin/admin@<YOUR KERBEROS REALM>     *
<YOUR USERNAME>@<YOUR KERBEROS REALM>  *
krbadm@<YOUR KERBEROS REALM>           *
*/*@<YOUR KERBEROS REALM>              i

For me, the second line reads turbo@BAYOUR.COM * and that gives me full access to the database as my ordinary login. Might not be a good thing, but then you don't have to give out the kadmin/admin password to all of those that you want to have (full or partial) access to your kerberos system. See the Kerberos V5 Installation Guide:ACL file for other values you can have besides * and i.

As you can see in this ACL file, we have not listed the ldapadm principal we created above, only the krbadm. That's because we will separate the Kerberos administration from the LDAP administration. Even if you are running this system on only one machine, and you are alone in administrating this (and will be in a foreseeable future), I still recommend that you to separate the functions. Have you read the section LDAPv3, why bother. Remember the discussion about security? Let's not allow things to slip through the cracks in such a minor detail as two separate principals...

The default keytab depends on your installation, but for Debian GNU/Linux it is /etc/krb5.keytab. This file have to be (securely) copied to the LDAP server before being able to authenticate with SASL. I had a number of problems with a faulty keytab. The kvno didn't matchup for some reason. Most likely because I'm not (or at least wasn't) very good at Kerberos administration. See the section about Problems when the KVNO don't match up for ways of fixing/preventing this.

This about raps' up the Kerberos installation/configuration, now we can (re)start the KDC and Kerberos admin server.

Testing MIT Kerberos V

[I haven't written this part yet, please contribute!]

I can't really remember how I tested it, but if ktelnet/kftp/krsh/ksu works to/from you machine, it works. If not, take a look at the Kerberos FAQ.

Cyrus SASL

Building Cyrus SASL

This is the first package that we will have to modify, since the default's isn't good enough (we need GSSAPI). To get the full source code (inclusive the patches applied by the Debian maintainer etc), there's the tool apt-get. With the parameter source, it downloads the latest source code and unpacks it in the current directory. So, the source package for Cyrus-SASL is, you guessed it cyrus-sasl (Debian have lowercased package names over the board, that eases things). To double check, the command line is:

apt-get source cyrus-sasl

This is the second part. This one we need to modify a little from the default Debian GNU/Linux packages. The changes are the following, please edit the file debian/rules.

--enable-gssapi instead of --disable-gssapi

And all the option, for those of you that aren't running Debian GNU/Linux, are:

--prefix=/usr
--enable-static
--enable-login
--without-des
--without-rc4
--enable-gssapi
--disable-krb4
--mandir=/usr/share/man
--infodir=/usr/share/info

Bugs in Cyrus SASL, v1.5.24

There is a bug in the version 1.5.24 that makes interactive bind from ldapsearch fail if trying to connect with SSL/TLS. If you execute this command line (exchanging the <YOUR BASE DN>) after running kinit to get a Kerberos ticket:

ldapsearch -I -b "<YOUR BASE DN>" -H ldaps:///

If you then get the following error, you need the patch below.

ldap_sasl_interactive_bind_s: Unknown authentication method

NOTE: According to a message on the openldap-software mailing list, this was fixed some time ago in the CVS version of Cyrus SASL. So make sure that you need the patch before applying it! The version of the file plugins/gssapi.c in the cyrus-sasl source directory should be greater than 1.39, that's when it was fixed. So if you have a version higher than 1.39 you don't need to patch Cyrus-SASL. If you got the tarball from the FTP site, then you will need both these patches. Another thing, if you can't find a version number in the file noted above, then you're most likely not running the CVS version, so the patch is needed.

This is the patch you will have to apply:

diff -ur cyrus-sasl-1.5.24.orig/plugins/gssapi.c cyrus-sasl-1.5.24/plugins/gssapi.c
--- cyrus-sasl-1.5.24.orig/plugins/gssapi.c.orig        Wed Mar  7 19:42:31 2001
+++ cyrus-sasl-1.5.24/plugins/gssapi.c  Wed Mar  7 19:43:35 2001
@@ -1243,7 +1243,7 @@
 
        /* need bits of layer */
        allowed = secprops.max_ssf - external;
-       need = secprops.min_ssf - external;
+       need = secprops.min_ssf < external ? 0 : secprops.min_ssf - external;
        serverhas = ((char *)output_token->value)[0];
 
        /* if client didn't set use strongest layer available */

Also, there is a problem with the Debian GNU/Linux (and according to information on the OpenLDAP-Software list, in any place where you use pre-built binaries) that makes SASL 'forget' about the realm part in the login. The way to test this is by running slapd with options -d -1 and try a sasl bind. Then check the output from slapd. To save all the output that slapd is spewing out, use the command tee like this:

slapd -d -1 2>&1 | tee /tmp/output.txt

Then search in the file /tmp/output.txt for the parts that read:

slap_sasl_bind: username="u:[YOUR USER ID]" realm="[YOUR KERBEROS REALM]" ssf=[SOME NUMBER]
<== slap_sasl_bind: authzdn: "uid=[YOUR USER ID] + realm=[YOUR KERBEROS REALM]"

If you have the text realm=<YOUR KERBEROS REALM> in there, all is well, and you don't need the patch. If however, the realm is not listed there, then please apply this patch that I got from the mailing list:

diff -ur cyrus-sasl-1.5.24.orig/plugins/gssapi.c cyrus-sasl-1.5.24/plugins/gssapi.c
--- cyrus-sasl-1.5.24.orig/plugins/gssapi.c.orig        Fri Jul 21 04:06:52 2000
+++ cyrus-sasl-1.5.24/plugins/gssapi.c  Sun Dec 17 15:19:31 2000
@@ -592,6 +594,7 @@
        gss_buffer_desc name_without_realm;
        gss_name_t without = NULL;
        int equal;
+       char *realm = NULL;
 
        name_token.value = NULL;
        name_without_realm.value = NULL;
@@ -625,7 +623,8 @@
           without the realm and see if it's the same id (i.e. 
           tmartin == tmartin@ANDREW.CMU.EDU. If this is the case we just want
           to return the id (i.e. just "tmartin: */
-       if (strchr((char *)name_token.value, (int) '@')!=NULL)
+       realm = strchr((char *)name_token.value, (int) '@');
+       if (realm != NULL)
        {
            name_without_realm.value = (char *) params->utils->malloc(strlen(name_token.value)+1);
            if (name_without_realm.value == NULL) return SASL_NOMEM;
@@ -687,6 +686,14 @@
            strcpy(oparams->authid, name_token.value);
        }
 
+       if (realm != NULL)
+       {
+           realm++; /* skip '@' */
+           oparams->realm = (char *) params->utils->malloc(strlen(realm)+1);
+           if (oparams->realm == NULL) return SASL_NOMEM;
+           strcpy(oparams->realm, realm);
+       }
+
        if (name_token.value)
            params->utils->free(name_token.value);
        if (name_without_realm.value)

Applying this patch(-es) can be done by using patch. For example, the patch is saved in the file /tmp/gssapi1.patch. You would then use the following command (in the top directory of the cyrus sasl source).

patch -p1 < /tmp/gssapi1.patch

The patch can also be found at my site, GSSAPI patch 1 and GSSAPI patch 2. The author of the first patch comes originally from Nalin Dahyabhai <nalin@redhat.com>. Again, only do this if your plugins/gssapi.c version is lower than 1.39 (or if you're trying to compile SASL from the official tarball)!

Build the Cyrus SASL packages

Now you can start building the packages by executing the command line

debuild -uc -us -rfakeroot

Debuild is in the package devscripts, so just install that package by executing the command line

apt-get install devscripts

before building the package. To build the packages if you are not running Debian, you just execute make to build the software.

Installing Cyrus SASL

To make sure that the packages you just build don't get automatically upgraded when using the command

apt-get update && apt-get upgrade

etc, make sure to put the packages on hold. Easiest way to do that, is to go into dselect and press = on the line of the package. Another way to do this is to execute

echo <PACKAGENAME> hold | dpkg --set-selections

Do this after you have installed the packages :). Please also see the section about Bumping the Debian GNU/Linux package version on another way to avoid automatic upgrades of the newly made packages.

But before we install the SASL packages, you have to make sure that some libraries etc. that these libraries depend on is installed. To do this, first install these packages

libgdbmg1
libpam0g
libcomerr2
libkrb53

Then you can continue with installation of the SASL packages below

libsasl7
libsasl-modules
libsasl-bin

You do this by executing the command

dpkg -i libsasl7*.deb libsasl-modules*.deb libsasl-bin*.deb

To install the software if you are not running Debian, you execute the command make install. See the package libkrb53? Now you know why I asked you to install the Kerberos development packages. SASL must find krb5 on the system to allow you to use Kerberos V!

Testing Cyrus SASL

You will need to have a working Kerberos V system running. See the section Testing MIT Kerberos V for more about this. What you will have to do is get yourself two shells. Execute kinit in both and then in shell number one type

su -c ./sample-server -s ldap -p /usr/lib/sasl

And in the other one

./sample-client -s ldap -n <FQDN> -u <USERNAME> -p /usr/lib/sasl

Other than that, please follow the information outlined in the file testing.txt distributed with cyrus-sasl. You can find the file at this URL to, Testing the CMU SASL Library with the included sample applications if you prefer to have it through you favourite web browser.

OpenLDAP

Building OpenLDAP v2

This package have also been slightly modified to suite my needs. First the changes in the configure command line, please edit the file debian/rules.

--disable-cleartext instead of --enable-cleartext
--disable-rlookups  instead of --enable-rlookups
--with-tls          instead of --without-tls
--enable-kpasswd

To build against the Berkeley DB we built before, add these two lines before the configure line.

CPPFLAGS="-I/usr/local/BerkeleyDB.3.0/include" \
LDFLAGS="-L/usr/local/BerkeleyDB.3.0/lib" 

And all the options, for those of you that aren't running Debian GNU/Linux, are the following. These are the important ones you should have

--with-cyrus-sasl
--enable-slapd
--enable-crypt
--enable-spasswd
--with-tls
--enable-kpasswd

These are also some (optional) values you should add. Remove the options that you know that you definitely don't want. For example, the enable-ipv6 might be a bad idea sometimes...

--enable-debug
--enable-syslog
--enable-proctitle
--enable-cache
--enable-referrals
--enable-ipv6
--enable-local
--with-readline
--with-threads
--disable-cleartext
--enable-multimaster
--enable-phonetic
--disable-rlookups
--enable-wrappers
--enable-dynamic
--enable-dnssrv
--enable-ldap
--enable-ldbm
--enable-passwd
--enable-shell
--enable-sql
--enable-slurpd
--enable-shared

Bugs in OpenLDAP, v2.0.7

There might also bee needed to patch the file libraries/libldap/open.c from the openldap2 source directory. Read all about the reasoning behind this at the OpenLDAP ITS, bug 889. There's also a patch there for you that don't use Debian. If you however are using Debian, and you want the changes in the rules file and the discussed patch, you can apply this patch instead of doing it all by yourself. To apply this patch, see the Cyrus SASL bugs above or read the manual page for patch. This patch might not be needed on the OpenLDAP source you have, so verify that you need it before use! One way of doing this, is compile/install without it, and if ldapsearch, ldapadd, ldapmodify segfaults when trying to use the parameter -H, then you need it!

NOTE: These bugs have been fixed around 2.0.9 or so. At any rate, the latest version (at the time of this writing, 2.0.21) have it fixed, so there is no need to patch the files! Please have a look at the Updates section for more information.

diff -urN debian.orig/patches/004_libldap-open debian/patches/004_libldap-open
--- debian.orig/patches/004_libldap-open        Thu Jan  1 01:00:00 1970
+++ debian/patches/004_libldap-open     Wed Mar 14 22:13:52 2001
@@ -0,0 +1,19 @@
+diff -ur OPENLDAP_HEAD/libraries/libldap/open.c libraries/libldap/open.c
+--- OPENLDAP_HEAD/libraries/libldap/open.c     Wed Oct 18 11:53:53 2000
++++ ./libraries/libldap/open.c Tue Nov 21 20:37:04 2000
+@@ -329,8 +329,15 @@
+       if (ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
+               strcmp( srv->lud_scheme, "ldaps" ) == 0 )
+       {
++              LDAPConn        *savedefconn = ld->ld_defconn;
++              ++conn->lconn_refcnt;   /* avoid premature free */
++              ld->ld_defconn = conn;
++
+               rc = ldap_pvt_tls_start( ld, conn->lconn_sb,
+                       ld->ld_options.ldo_tls_ctx );
++
++              ld->ld_defconn = savedefconn;
++              --conn->lconn_refcnt;
+ 
+               if (rc != LDAP_SUCCESS) {
+                       return -1;
diff -urN debian.orig/rules debian/rules
--- debian.orig/rules   Wed Mar 14 22:10:41 2001
+++ debian/rules        Wed Mar 14 22:10:33 2001
@@ -34,11 +34,11 @@
 configure_args := --enable-debug --enable-syslog --enable-proctitle \
 --enable-cache --enable-referrals --enable-ipv6 --enable-local \
 --with-cyrus-sasl --with-readline --with-threads \
---enable-slapd --enable-cleartext --enable-crypt --enable-spasswd \
---enable-multimaster --enable-phonetic --enable-rlookups --enable-wrappers \
+--enable-slapd --disable-cleartext --enable-crypt --enable-spasswd \
+--enable-multimaster --enable-phonetic --disable-rlookups --enable-wrappers \
 --enable-dynamic --enable-dnssrv --enable-ldap --enable-ldbm \
 --enable-passwd --enable-shell --enable-sql --enable-slurpd --enable-shared \
---without-tls
+--with-tls --enable-kpasswd
 
 # FHS options
 configure_args += --prefix=/usr --localstatedir=/var --sysconfdir=/etc \
@@ -52,6 +52,8 @@
 $(STAMP_DIR)/pre-build-stamp: $(unpacked) $(patched)
        dh_testdir
        cd $(BUILD_TREE) && CFLAGS="$(CFLAGS)" \
+               CPPFLAGS="-I/usr/local/BerkeleyDB.3.0/include" \
+               LDFLAGS="-L/usr/local/BerkeleyDB.3.0/lib" \
                ./configure $(configure_args) --host=$(DEB_BUILD_GNU_TYPE)
        $(MAKE) depend -C $(BUILD_TREE)
        touch $(STAMP_DIR)/pre-build-stamp

You can also get the OpenLDAP v2 patch on papadoc.

When the possible patching is done, we will build the packages. Do this by executing the command

debuild -uc -us -rfakeroot

For those that aren't running Debian, execute the commands

make depend
make

Installing OpenLDAP v2

The packages you should install are the following:

libldap2
ldap-utils
slapd

You do this by executing the command

dpkg -i libldap2*.deb ldap-utils*.deb slapd*.deb

But before you can do this, you have to make sure that some libraries etc. that these libraries depend on is installed. To do this, execute the line

apt-get install libiodbc2

To install the software if you are not running Debian, you just execute the command

make install

For more information (in case of trouble building and installing OpenLDAP2 etc.), please see the OpenLDAP web site and/or the OpenLDAP FAQ-O-Matic:Quick Start Guide.

Configuring OpenLDAP v2

The Debian GNU/Linux installation script will guide you through most of the scripts and will also create the administration DN referred to in these files. This DN is mostly for backward compatibility with older clients, than can't do SASL/Kerberos binds.

Configure OpenLDAP to use the new SSL certificate

Changes to the OpenLDAP config file

Then it's just a matter of copying this file, server.pem to /etc/ldap and modify The OpenLDAP config file with these options:

TLSCertificateFile      /etc/ldap/server.pem
TLSCertificateKeyFile   /etc/ldap/server.pem
TLSCACertificateFile    /etc/ldap/server.pem
Changes to the OpenLDAP startup script

We have to make sure that slapd (the actual LDAP daemon/server) listens to port 636 which is the actual LDAP over SSL/TLS port. In the Debian GNU/Linux original startup script, we make this change:

--- slapd.orig  Fri Jul 27 08:53:39 2001
+++ slapd       Fri Jul 27 08:53:11 2001
@@ -21,7 +21,7 @@
     echo -n "Starting ldap server(s):"
     echo -n " slapd"
     start-stop-daemon --start --quiet --pidfile "$pidfile" \
-               --exec $DAEMON
+               --exec $DAEMON -- -h "ldap://0.0.0.0:$PORT/ ldaps://0.0.0.0/"
     replicas=`grep ^replica /etc/ldap/slapd.conf`
     test -z "$replicas" || (echo -n " slurpd" && start-stop-daemon --start \
                --quiet --name slurpd --exec $SLURPD)

That is, we have to make sure that SLAPD listens to ldaps (which is port 636). The PORT variable is set earlier in the script (at least in the Debian GNU/Linux version).You should have a line that read something like:

PORT=389

If you don't have this, either replace the $PORT part above with 389, or add the PORT=389 line above the slapd start lines...

The OpenLDAP config file

This could be a FAQ all on it's own, let's just include my config file, shall we?

# This is the main ldapd configuration file. See slapd.conf(5) for more
# info on the configuration options.

# Schema and objectClass definitions
include                 /etc/ldap/schema/core.schema
include                 /etc/ldap/schema/cosine.schema
include                 /etc/ldap/schema/inetorgperson.schema
include                 /etc/ldap/schema/nis.schema
include                 /etc/ldap/schema/krb5-kdc.schema
include                 /etc/ldap/schema/qmail.schema
include                 /etc/ldap/schema/qmailControl.schema
include                 /etc/ldap/schema/netscape-profile.schema
include                 /etc/ldap/schema/trust.schema
include                 /etc/ldap/schema/turbo.schema
# Some are extra schema's that I found on the 'Net...
# Want them? They can be found at http://www.bayour.com/openldap/schemas/

# Schema check allows for forcing entries to
# match schemas for their objectClasses's
schemacheck             on

# Where the pid file is put. The init.d script
# will not stop the server if you change this.
pidfile                 /var/run/slapd.pid

# List of arguments that were passed to the server
argsfile                /var/run/slapd.args

# Read slapd.conf(5) for possible values
loglevel                2048  # Only entry parsing errors

sasl-realm              <YOUR KERBEROS REALM>
sasl-host               <FQDN OF LDAP SERVER>
#sasl-secprops          none

#######################################################################
# ldbm database definitions
#######################################################################

# The backend type, ldbm, is the default standard
database                ldbm

# The base of your directory
suffix                  "<YOUR BASEDN>"

# Where the database file are physically stored
directory               "/var/lib/ldap"

# Save the time that the entry gets modified
lastmod                 on

# Indexes
index                   default pres,eq
index                   objectClass,uid,uidnumber,gidnumber,cn
index                   mail,mailalternateaddress,mailforwardingaddress eq

# Include the access lists
include                 /etc/ldap/slapd.access

# End of ldapd configuration file

In this file you will notice the option sasl-host. Remember the DNS setup? This is the host name and domain name of the host that your LDAP server is running on. It is not the FQDN of the kerberos server as I've stated in previous versions of this document. Sorry about that. In my case, this is egeria.bayour.com, because that was what I was entering into the SSL certificate. Don't forget the SSL/TLS certificate file options, which I showed you in Creating SSL certificate.

The OpenLDAP access file

I have all my access lists (ACL's) in a separate file (/etc/ldap/slapd.access). I'm still working on getting this to work properly so it's not perfect, but there you go.

# For Netscape Roaming  support, each user gets a  roaming profile for
# which they have write access to
access to dn=".*,ou=Roaming,dc=.*"
        by dn="<YOUR ADMIN DN>" write
        by dn="uid=ldapadm.+\+realm=<YOUR KERBEROS REALM>" write
        by dnattr=owner write
        by * none

# Some things should be editable by the owner, and viewable by anyone...
access to attr=cn,givenName,sn,krbName,krb5PrincipalName,gecos
        by dn="<YOUR ADMIN DN>" write
        by dn="uid=ldapadm.+\+realm=<YOUR KERBEROS REALM>" write
        by self write
        by users read

access to attr=loginShell,gecos
        by dn="<YOUR ADMIN DN>" write
        by dn="uid=ldapadm.+\+realm=<<YOUR KERBEROS REALM>" write
        by self write
        by * read

# Since we're using {KERBEROS}<PRINCIPAL>, we can't allow the user
# to change the password. They have to use the Kerberos 'kpasswd' to
# do this... But the admin can change (if need be).
# Please see krb5 userPassword attribute
access to attr=userPassword
        by dn="cn=admin,ou=People,dc=papadoc,dc=bayour,dc=com" write
        by dn="uid=ldapadm.+\+realm=<YOUR KERBEROS REALM>" write
        by anonymous auth
        by * none

# The  mail and mailAlternateAddress  should only  be readable  if you
# authenticate!
access to attr=mail,mailAlternateAddress,mailHost
        by dn="<YOUR ADMIN DN>" write
        by dn="uid=ldapadm.+\+realm=<YOUR KERBEROS REALM>" write
        by users read
        by * none

# Should not be readable to anyone, and only editable by admin...
access to attr=mailQuota,trustModel,accessTo
        by dn="<YOUR ADMIN DN>" write
        by dn="uid=ldapadm.+\+realm=<YOUR KERBEROS REALM>" write
        by self read
        by * none

# The admin dn has full write access
access to *
        by dn="<YOUR ADMIN DN>" write
        by dn="uid=ldapadm.+\+realm=<YOUR KERBEROS REALM>" write
        by * read

Notice the

by dn="uid=ldapadm.+\+realm=<YOUR REALM>" write

That's the Kerberos principal you want write access to the database as. This principal was created in the Create KerberosV realm section.

But there seems to be another bug in the Debian SASL packages. According to information on the openldap-software mailing list, the problem don't exist in the tarball from Cyrus home page. See the section about the SASL patch - Realm for more about this.

One important note about the by dn entries above. They use regexp, so make sure that you protect any dots in the realm, like this

access to * by dn="uid=ldapadm.+\+realm=BAYOUR\.COM" write

or

access to * by dn="uid=ldapadm.+\+(realm=BAYOUR\.COM)" write

Creating a LDAP service key

To let OpenLDAP/SASL connect to the KDC, we need to add a LDAP service key into the KDC. To do this, use the command kadmin or kadmin.local like this:

kadmin.local -q "addprinc -randkey ldap/<FQDN>@<YOUR KERBEROS REALM>"
kadmin.local -q "ktadd ldap/<FQDN>"

Populate the database to allow simple bind as user

If you starting out fresh with this project, you will have to read up on how to create a database on the openldap database creation and maintenance tools page. When you understand this, it's time to specify the special object classes and attributes that makes this whole LDAPv3 thing tick. The object class krb5Principal specify that the attribute krb5PrincipalName is a must and that the cn and krb5PrincipalRealm attributes is optional. What this means, is that we use the following LDIF snippet on each of our users:

objectClass: krb5Principal
krb5PrincipalName: turbo@<MY KERBEROS REALM>
cn: Turbo Fredriksson

The cn means Common Name, and in this case it's my full name (yes, my name really IS turbo! :).

These attributes and object classes are defined in the krb5-kdc.schema file distributed with OpenLDAP2. The other object classes (krb5KDCEntry and krb5Realm) are not used in this context, so ignore them :).

Modify the LDAP database to allow simple bind as user.

If you already have a database, but are using some other means of storing the passwords, you will have to do some minor modifications to the database. For example, my production server, which is a version 1.2.11 have the passwords in the LDAP database as '{crypt}CRYPTEDPW', and is using libpam-ldap (and for migration purposes libpam-krb5 which is NOT to recommend in a shared network environment since it binds in clear text) to authenticate the users on all services (ssh/imap/pop/ftp etc). Now, Quite naturally I wanted to use that database, so I first did a dump of the original database with ldbmcat (to convert it into an LDIF file) and then on the new server, slapadd to create the database. This was a big problem, since OpenLDAP2 is much more strict about the existence of a proper schema for the objectClasses etc. See LDAP schemas on Papadoc for the schema's that I have (I found most of them on the Internet so don't blame me if they are a little out of date :).

Before loading the database into the new server, I had to change all the userPassword attributes. This is where the --enable-kpasswd comes into play. The password should be {KERBEROS}<USERS PRINCIPAL> like this (my entry):

dn: uid=turbo,ou=People,<MY BASEDN>
replace: userPassword
userPassword: {KERBEROS}turbo@<MY KERBEROS REALM>

This have to be done for all the users to allow them to authenticate! This only works if you have compiled OpenLDAP2 with the configure option --with-kpasswd, and what that do is making slapd ask the Kerberos server if the password corresponds with the password for the Kerberos principal turbo@<MY KERBEROS REALM>. What this do, is it's telling the OpenLDAP2 server (slapd) to check the password in the Kerberos server. Since there is no password in the LDAP database any more, we have to make sure that the user can't change there password with either ldappasswd or via PAM. Therer for, please have a look at the The OpenLDAP access file again (especially the 'access to attr=userPassword' section.

Now, just to clarify some things (because it will look a little strange). If you do the modifications above, and then do a search (ie, retrieving) the userPassword value from the database, it will look a little garbled:

userPassword:: e2NyeXB0fUlNRDR0cmxiaUdFVVU=

This is nothing to worry about. It's simply base 64 encoded (this reads {KERBEROS}turbo@BAYOUR.COM after decoding).

Notes about 'userPassword: {KERBEROS}'

The reason for using userPassword: {KERBEROS}PRINCIPAL is so that we can allow simple binds with the password in the Kerberos database. This should not really be done, since if we do a simple bind without SSL/TLS, we're opening up the Kerberos database. We're using Kerberos so that we get a secure system, remember?!.

So simple binds would only be allow if it's protected with SSL or TLS. If you have no interest in allowing simple binds (note, this is not SASL bind!), then don't use the userPassword entry at all. If you only have interest in allowing SASL binds, this entry can be left out completely. If, for some reason, you have clients that can't do SASL binds (Qmail-LDAP comes to mind), then don't have the password in the Kerberos database, but in LDAP with either {CRYPT} or even better {SSHA}. Using the command slappasswd, you can create a scheme to be inserted into the database. This way, you won't accidentally compromise your Kerberos database security.

Testing OpenLDAP v2

In the ldapsearch commands below, I use localhost for the name of the LDAP server. I got one mail from Will Day on the OpenLDAP-Software mailing list, saying that this didn't work for him. He had to exchange localhost to the FQDN of the LDAP server instead. The reason for this is most likely because it can't get a ticket for ldap/localhost@<KERBEROS REALM>. To avoid that, just enter a ldap/localhost@<KERBEROS REALM> service key as well as the ldap/<FQDN>@<KERBEROS REALM>. Have a look at Creating a LDAP service key below how to do that. So, if the commands don't work as shown here, please try that.

Also, I'm specifying port 389 here. You might not need that at all, since that's the default port of the LDAP server. I only list that here, because while setting all this up for the very first time, I ran a OpenLDAP1 server on port 389, and my new OpenLDAP2 server on port 3389. This server is now my main LDAP database.

Testing OpenLDAP, simple/anonymous bind

The first thing is probably to check if a non SASL/SSL/TLS (that is, a simple bind) works

ldapsearch -h localhost -p 389 -x -b "" -s base -LLL supportedSASLMechanisms

You should get something like this

supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: ANONYMOUS
supportedSASLMechanisms: GSSAPI

The important stuff here is the last line! If you don't have GSSAPI listed (the other ones doesn't really matter for us at this moment, although you should have ANONYMOUS in addition to GSSAPI), something is wrong, and you should go back to Building OpenLDAP v2 (or maybe you need to go back to Building Cyrus SASL) and do it right this time. On my production server, I have now disabled some of these mechanisms, so the only one I get is GSSAPI. This is perfectly ok, since I only want/need SASL (GSSAPI) binds.

Testing OpenLDAP, simple/anonymous bind, with SSL/TLS

If the search for supported SASL mechanisms went well, let's continue with the next step. Let's try to do a simple bind, but with SSL and TLS. The first command tests TLS, and the second one SSL (notice the parameter -ZZ in the first command and ldaps:/// in the second?).

ldapsearch -H ldap://<FQDN OF LDAP SERVER>/ -p 389 -x -b "" -s base -LLL -ZZ supportedSASLMechanisms
ldapsearch -H ldaps://<FQDN OF LDAP SERVER>/ -x -b "" -s base -LLL supportedSASLMechanisms

You should get the same stuff as above back, only this time it is sent to you encrypted from the LDAP server. You can double check this by using a packet sniffer. The reason we have to enter the full name of our LDAP server for these two commands (instead of just ldap:/// or ldaps:///) is because in newer OpenLDAP, the certificate verifications is much stronger. It requires the FQDN one connects to matches the one in the certificate. In my example (see the section about Creating SSL certificate) the commands would look like:

ldapsearch -H ldap://egeria.bayour.com/ -p 389 -x -b "" -s base -LLL -ZZ supportedSASLMechanisms
ldapsearch -H ldaps://egeria.bayour.com/ -x -b "" -s base -LLL supportedSASLMechanisms

Testing OpenLDAP, using your Kerberos ticket

Now let's try out a SASL bind. Exchange the -x above to -I (uppercase i) like below. Just press enter when you get the prompt Please enter your authorisation name:.

ldapsearch -H ldaps:/// -I -b "" -s base -LLL supportedSASLMechanisms

Anything? Nope, you should get back:

ldap_sasl_interactive_bind_s: Local error

This is a bug (or maybe more correctly, 'missing feature' :) in SASL (it doesn't return the correct error codes). There is no known fix for this yet. To get around it, execute the command kinit and try again. The lines above, with -x replaced with -I should return something like:

SASL SSF: 56
SASL installing layers
dn:
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: ANONYMOUS
supportedSASLMechanisms: GSSAPI

Here DES (56 bit key lengh for symmetric cryptography) is used to encrypt the data stream. That is, the transfer of the information to you isn't encrypted, but the actual bind (the password and user/authorisation name) is. Hmm, wonder if this is true... I've heard 'rumors' on some lists that SASL actually ARE encrypting all communication between you and the LDAP server. Ah, well. Better safe than sorry, use -H or -Z.

Testing OpenLDAP, using your Kerberos ticket, with SSL/TLS

Please verify that a SSL and TLS works with SASL to by using -ZZ and -H parameters to the above ldapsearch command line. The difference between -Z and -ZZ is that the later requires the operation to be successful.

Testing OpenLDAP, simple user bind, with SSL/TLS

Now, if all the changes to the database (see how to populate the database and/or modify the LDAP database) have been done and all the above tests work, let's try to search the database as yourself again, but this time doing it with a simple bind (-x to ldapsearch). To make absolutely sure that it doesn't try to use the Kerberos ticket you got with kinit above, execute kdestroy. Just to be on the safe side when testing here, mind you :). Here we go, all in one line:

ldapsearch -x -D 'uid=turbo,ou=People,<MY BASEDN>' -W -b "" -s base -LLL -H \
ldaps://<FQDN OF LDAP SERVER>/ supportedSASLMechanisms

Enter the password when prompted. This command should return the same thing as the previous commands. Remember, you should enter the password for your KerberosV principal. If it didn't take the Kerberos password, you would get this back:

Enter LDAP Password: 
ldap_bind: Invalid credentials

I worked for quite some time (about 4-5 days) to get this part to work. I had no luck. Then, all of a sudden it worked, and I'm not quite sure why. I am however quite sure that it have something to do with the order the ACL's for userPassword is arranged. OpenLDAP v2.0 is a LOT more picky about the order of the ACL's than the 1.3 version(s) where (where my config/access file originates from). See my OpenLDAP access file of how it looks when it works. Take a extra look at the section that starts with:

access to attr=userPassword

NOTE: The parameters -D, -W and -w is not used when using SASL (unless you want a simple bind, which you normally wouldn't). You use -I (uppercase i), -U and -X to use SASL bind. For anonymous and/or simple binds, one have to use the option -x.

If all the above searches work, you might want to try searching for data under your base DN, and also do modifications etc, just to double check that everything works as it's supposed to. The biggest problems I had with all this, must be the ACL's! Have a second look at The OpenLDAP access file.

Setting up secure replication

One of the main points (for me at least) by using SASL, Kerberos and SSL/TLS is so that we can have a secure/encrypted authentication and communication between the master and slave LDAP server(s). To try this out, I will demonstrate how you can (and should?) have a slave server running on localhost. The reason we want to do this, is so that when doing backups of the LDAP database, we don't need to take down the master database, only the read-only replica, which means that we don't have any downtime on the LDAP server.

Replication configuration, slave server

The first thing we do, is we create the config file for the slave server. This is basically the exact same config file as The OpenLDAP config file. The differences though, is that the database is located in another directory. Preferably we should set the database to read only, but it doesn't seem to work. We will instead use ACL's to limit the access (as much as I can, with the limited knowledge of OpenLDAP2's ACL structure :).

directory       "/var/lib/ldap.backup"
include         /etc/ldap/slapd.access.backup
updatedn        "uid=replicator + realm=<YOUR REALM>"

It is important that the updatedn directive is after any database directives. This usually means at the very bottom of the file. Also, the updatedn is not a regexp, so it have to be specified as is.

To make sure that any modification to a slave server isn't possible but instead redirected to the master, the configuration directive updateref is used.

updateref ldaps://master.domain.com

Note though, that it's important to only add this after everything works as expected, because all changes will be redirected to the master LDAP server.

Other than that, we will run the slave server on other ports than the master. That's since we are running both on the same machine, and we can't bind both of them on the same port (unless you make it bind to different IP addresses, but that's nothing I will go into here). There for we add some more options to the command line. You can use the master's start script, modify it by running slapd like this:

PORT=3391 /usr/sbin/slapd \
     -h "ldap://0.0.0.0:$PORT/ ldaps://0.0.0.0:`expr $PORT + 1`/" \
     -f /etc/ldap/slapd.conf.backup

That will start the non-SSL/TLS port on 3391, and the SSL/TLS port on 3392.

Replication configuration, master server

The modifications to the master database's configuration, is the location of the slave. This is what we will add to the database definition in The OpenLDAP config file:

replica         host=localhost:3391
                tls=yes
                bindmethod=sasl
                saslmech=GSSAPI
replogfile      /var/lib/ldap/replog

It is important that this replication setup is entered after any database directives. This usually means at the very bottom of the file.

Please see the OpenLDAP 2.0 Administrator's Guide:Replication and the manual page for slapd.conf for more about this.

Creating a replication principal

To be able to use GSSAPI/Kerberos V with replication, we will need to create a service key that we will use for authentication and extract that into a keyfile. The principal I have chosen here is replicator, but you can essentially choose any principal you like, as long as use use the same principal in the access list on both the master and the slave server. To create such a principal, we execute the following commands:

kadmin.local -q "addprinc -randkey replicator@<YOUR KERBEROS REALM>"
kadmin.local -q "ktadd -k /etc/krb5.keytab.slurpd replicator"

Make sure that the keytab file (/etc/krb5.keytab.slurpd in this example) is secure. That is, transfer it safely to the slave and master LDAP server (using for example scp or kscp). Also make sure it is not readable for anyone else than the user slapd is running as.

If this file is compromised (obtained by any arbitrary user), then your whole LDAP database will have to be considered compromised!


Automatically getting a ticket before starting slurpd

Since we are using SASL/KerberosV to do the replication authentication, we must ensure that slurpd have a Kerberos ticket before starting. We must also 'remember' the location of the ticket file, so that it can be removed when shutting down slurpd. To do this, we use the LDAP service key we created above, like this:

kinit -r 7d -k -t /etc/krb5.keytab.slurpd replicator@<YOUR KERBEROS REALM>

This line will have to be inserted into the slapd/slurpd start script, just before slurpd is started. To make sure that the ticket gets removed/destroyed when no longer needed (ie, when slurpd is shutdown), we issue the command kdestroy just after slurpd have been stopped.

This results in the following start scripts (for starting slurpd):

replicas=`grep ^replica /etc/ldap/slapd.conf`
if [ ! -z "$replicas" ]; then
    KRB5CCNAME=FILE:/var/run/slapd.krbenv
    echo -n "Getting ticket for replicator: "
    kinit -k -t /etc/krb5.keytab.slurpd replicator@<YOUR KERBEROS REALM>
    echo "done."

    echo -n "Starting LDAP replication daemon: "
    /usr/sbin/slurpd
    echo "done."
fi

This is the stopping part:

replicas=`grep ^replica /etc/ldap/slapd.conf`
if [ ! -z "$replicas" ]; then
    echo -n "Stopping LDAP replication daemon: "
    killall slurpd > /dev/null 2>&1
    echo "done."

    KRB5CCNAME=FILE:/var/run/slapd.krbenv
    echo -n "Removing Kerberos ticket: "
    kdestroy && rm /var/run/slapd.krbenv
    echo "done."
fi

Keeping replication ticket updated

To make sure that there always is a ticket for the replicator, we will have to execute the kinit line above every now and then from cron. How often this should happen, depends on how long-lived the ticket is. To find that out, we issue the command kadmin (or kadmin.local) like this:

kadmin.local -q "getprinc replicator" | grep "^Maximum ticket life:"

In my case, it will return:

Maximum ticket life: 0 days 10:00:00

So I will have to renew the ticket at least every ten hours. To be on the safe side, I'll do it every nine hours. The entry we will put into /etc/crontab is:

# Making sure that the LDAP replication have a valid ticket
KRB5CCNAME=FILE:/var/run/slapd.krbenv
0 */9 * * * root test -e /var/run/slapd.krbenv && kinit -R

You can read more about running and getting tickets in shell scripts untended at the Kerberos FAQ:Shell scripts.

There is a way to specify a longer life time when creating the principal (-maxlife) but I haven't figured out exactly how to specify the time. I keep getting Invalid date specification all the time.

UPDATE: The maximum lifetime of a ticket can, in kadmin or kadmin.local be specified like

-maxlife "4 days"
-maxlife "4 hours"

etc...

Give the replicator access to the database

We must give the replicator principal access to write to the database. To do this, we create this access file instead of The OpenLDAP access file we had for the master server (this file is named /etc/ldap/slapd.access.backup in the slave server replication configuration above). The reason it's much simpler is because it's read-only, and should contain a online backup of the database, therefor there is no need for anyone else than replicator to be able to read/write to the slave.

access to attr=cn,givenName,sn,krbName,krb5PrincipalName,loginShell,gecos,mail,
        mailAlternateAddress,mailHost,mailQuota,uidNumber,gidNumber,homeDirectory
        by dn="uid=replicator.+\+realm=<YOUR KERBEROS REALM>" write
        by users read
        by * none

access to attr=userPassword,ldapPassword,clearTextPassword
        by dn="uid=replicator.+\+realm=<YOUR KERBEROS REALM>" write
        by * none

access to *
        by dn="uid=replicator.+\+realm=<YOUR KERBEROS REALM>" write
        by * read

We should really not have read access at all (by users read and by * read), but for some reason (which elude me) it doesn't work otherwise...

Building miscellaneous software

Concurrent Version System

Building CVS

The version I did this with was v1.11-0.1. One can now authenticate and encrypt using the GSSAPI network security interface. For details, see the Cederqvist's description of specifying :gserver: in CVSROOT, and the -a global option.

Configure options

To do this, we need to build with the following options to configure:

--with-gssapi=value     GSSAPI directory
--enable-encryption     enable encryption support

For non-Debian systems, these are the full configure opions:

--prefix=/usr
--mandir=/usr/share/man
--infodir=/usr/share/info
--with-gssapi
--enable-encryption

How to build and install? Haven't you paid attention? :) Please go back to the Building Cyrus SASL section again...

With Krb4 option

There's the --with-krb4=value to configure in this case, but as you can see that is for Kerberos IV, and that isn't fully compatible with MIT Kerberos V. There is however a krb524d daemon that takes care of converting a Kerberos IV request to a Kerberos V. But that's quite pointless, since we are already using GSSAPI with our Kerberos V server. From what I can tell, you should only run the krb534d daemon if you don't have any other choice. That is, if there weren't any --with-gssapi option here, we'd go for the --with-krb4, and made sure that our converter daemon was running.

Creating a CVS service key

To be able to use GSSAPI/Kerberos V with CVS, you will have to add the appropriate service key into the Kerberos database:

kadmin.local -q "addprinc -randkey cvs/<FQDN>@<YOUR KERBEROS REALM>"
kadmin.local -q "ktadd cvs/<FQDN>"

As you can see, the service name for CVS, are... Right, cvs!

Cyrus IMAP/POP

This is currently unverified by me, but this is supposed to be the way it's done...

Building Cyrus IMAP and POP3 server

To have the Cyrus IMAP and POP3 server use GSSAPI (SASL) to authenticate the user, we need the source of the Cyrus IMAPd/POP3d package (apt-get source cyrus-imapd). And to build, these are the options to configure:

[I'm currently trying this out, come back in a few days]

For non-Debian systems, these are the full configure options:

[I'm currently trying this out, come back in a few days]

Configure Cyrus IMAP and POP3 server

See Cyrus IMAP/POP Howto:Cyrus IMAP Configuration and imapd.conf(5) for more about this.

Creating a IMAP/POP3 service key

To be able to use GSSAPI/Kerberos V with IMAPd/POP3d, you will have to add the appropriate service keys into the Kerberos database:

kadmin.local -q "addprinc -randkey imap/<FQDN>@<YOUR KERBEROS REALM>"
kadmin.local -q "addprinc -randkey pop/<FQDN>@<YOUR KERBEROS REALM>"
kadmin.local -q "ktadd -k /etc/krb5.keytab.cyrus imap/<FQDN>"
kadmin.local -q "ktadd -k /etc/krb5.keytab.cyrus pop/<FQDN>"
chown cyrus /etc/krb5.keytab.cyrus

The keytab above is used in the wrapper needed for GSSAPI/KerberosV support:

#!/bin/sh

KRB5_KTNAME=/etc/krb5.keytab.cyrus
export KRB5_KTNAME
exec /usr/sbin/imapd.real $@

LibPAM-LDAP and LibNSS-LDAP

Building and installation

Downloading source

Basicly the only thing that needs to be done with these two packages are rebuilding (ie, configure and make) them, to get SSL/TLS support. For those of you that are running Debian GNU/Linux, execute this command

apt-get source libpam-ldap libnss-ldap

and the source of the two packages will be downloaded and unpacked in the current directory.

Building packages

To create the two Debian GNU/Linux packages, execute this command (we only have to rebuild them to have them recognize that we have the installed OpenSSL development package files)

find -maxdepth 1 -type d -name 'lib*ldap-*' -exec sh -c 'cd {} && debuild -rfakeroot -uc -us' \;

Install the newly made packages

Now it's just a matter of executing the following command to install them:

dpkg -i lib*ldap_*.deb

SAMBA

This is currently unverified by me, but this is supposed to be the way it's done...

Building Samba/Samba-TNG

Wed, May 30, 2001

Have compiled samba-2.2.0.final with the following options. I'm currently trying to configure samba. Using 'security = user' and 'encrypt passwords = no' don't work at all, and using encrypted password don't either (it bypasses the auth mechanisms).

--with-krb5
--with-ssl
--with-sslinc=/usr/include/openssl

According on a mail on the kerberos mailinglist, Microsofts Step-by-Step Guide to Kerberos 5 (krb5 1.0) Interoperability should be interesting to read... You be the judge, I haven't bothered to read it fully yet :).

Fri, Jun 1, 2001

It seems that the LDAP support in samba 2.2 isn't working at all. Have downloaded samba TNG via CVS, hopefully that will work...

Compile options
--with-fhs
--prefix=/usr
--sysconfdir=/etc
--with-privatedir=/etc/samba
--with-lockdir=/var/state/samba
--localstatedir=/var
--with-netatalk
--with-smbmount
--with-pam
--with-syslog
--with-sambabook
--with-utmp
--with-readline
--with-krb5
--with-ssl
--with-sslinc=/usr/include/openssl
--with-ldap
--with-utmp
Make string
make SMBLOGFILE=/var/log/smb NMBLOGFILE=/var/log/nmb all smbtorture rpctorture debug2html

OpenAFS

I have this working just fine on my live server, and it have been working great (better than expected!) for about three months now. From the occasional glitch when I started to understand what exactly AFS is, I now have all my users, my web directory and whole of my FTP support directory on AFS.

There's many good things about AFS, and one that I've started to like more and more, is that root is no longer almighty! Root have (at least default) absolutely NO rights in AFS space! It's all about tickets (Kerberos V) and tokens. The ACL (Access Control List) of the directory decide who have access to what, not the system UID (User Identification Number).

AFS also come with 'replication support' as standard, so adding more servers is a good thing. And easy to, from what it seems.

To get OpenAFS up and running with Kerberos V (OpenAFS only works with Kerberos IV as standard), there is some additional software's necessary besides the OpenAFS sources. These are the OpenAFS PAM module and the the special OpenAFS/KerberosV support software's.

Getting OpenAFS and the associated PAM/KRB5 softwares to compile under Debian GNU/Linux 2.2 (code name Potato) have been proven to be very difficult. There's a lot of build dependencies that have to be fulfilled and very few of the packages required exists for Potato. I have therefor left out the building of all these packages. If you really want to build for Potato, you will have to figure out how to build those yourself.

OpenAFS

Building OpenAFS

Build OpenAFS kernel module

Installing OpenAFS

OpenAFS KerberosV support software

Building OpenAFS KerberosV support software

Installing OpenAFS KerberosV support software

Configure OpenAFS KerberosV support software

OpenAFS PAM module

Building and Installing the OpenAFS PAM module

Configure OpenAFS PAM module

Configure OpenAFS

Creating a AFS service key

Putting the AFS service key into the AFS KeyFile

Mount the AFS volume

Create the new cell

Setup the cell configuration files

Getting a Kerberos ticket and a AFS token

Setting up root volumes

Testing the OpenAFS softwares

Testing OpenAFS KerberosV support software

Testing OpenAFS PAM module

OpenAFS

Building OpenAFS

The source package for OpenAFS is just simply called 'openafs' so download the source, using the command

apt-get source openafs

I have not needed to make any modifications to these packages, they are fine as is. These are the options that the Debian GNU/Linux package is using to configure the OpenAFS sources:

afslogsdir=/var/log/openafs
--with-afs-sysname=$(SYS_NAME)
--disable-kernel-module
--prefix=/usr
--sysconfdir=/etc
--libexecdir=/usr/lib
--localstatedir=/var/lib

The variable SYS_NAME is delivered from the output of the /bin/arch command (in the util-linux package). For my Sun SPARC Station 4, this will equal sparc_linux22. Strangely enough, this seems to be the system name even if I use a 2.4 kernel. I think I must look into this more...

To build the package on a Debian GNU/Linux box, the command

debuild -uc -us -rfakeroot

is used. If not running a Debian GNU/Linux box, execute the command

make dest
Build OpenAFS kernel module

When the build of the sofware is done, there will be a openafs-modules-source package (in my example, for the version I built, this file will be called openafs-modules-source_1.2.3final2-3_all.deb). This is the source to the kernel module, which is needed to give OpenAFS support to the kernel. The module for the kernel is built by unpacking the file openafs.tar.gz which gets installed into /usr/src when installing this package. This file have to be unpacked from the /usr/src tree for the make-kpkg command (which is in the kernel-package package.

To create a Debian GNU/Linux package for the kernel and for the OpenAFS module, issue the following command inside the kernel source tree of your choice.

make-kpkg -uc -us configure buildpackage modules_image

You will have to have the kernel configured using either make config, make menuconfig or make xconfig depending on favorite choice. My personal favorite is the second one, make menuconfig. Graphically enough for me :)

The buildpackage option creates the kernel packages, so that can be lefout if you don't want/need a package for your kernel.

When the modules_image have finished, it will leave a

openafs-module-KERNELVERSION_OPENAFSVERSION_SPECIALVERSION_ARCH.deb

file in /usr/src. For my Sun SPARC Station 4, trying to build my first 2.4 kernel on this architecture, this file will be named:

openafs-modules-2.4.18_1.2.3final2-5+10.00.Custom_sparc.deb

and that is installed using dpkg (with the option -i). If not using Debian GNU/Linux, the package is installed when you issued the command make dest.

Installing OpenAFS

The packages that have to be installed are:

All hosts

Development Host

Server Host(s)

openafs-client

libopenafs-dev

openafs-dbserver

openafs-modules-XX-YY

openafs-modules-source

openafs-fileserver



openafs-kpasswd

The development packages only have to be installed on the host where all the packages are built, not on the client/server hosts themselves. The libopenafs-dev package is needed by all software's that is going to be compiled to use some functionality that OpenAFS provides. That include the OpenAFS KerberosV support software and the OpenAFS PAM module below.

Before we continue with configuring OpenAFS, we need some supplementary commands since we're using Kerberos V. So these have to be built first.

OpenAFS KerberosV support software

OpenAFS only comes with Kerberos IV (four) support. We need this software to be able to use the Kerberos V (five) database, which was the very first thing we did, and not have to have two databases (the Transarc KA server which comes with OpenAFS and the Kerberos V server) for user authentication/authorization.

Building OpenAFS KerberosV support software

The source package for this is called openafs-krb5, and are configured using the following configure options:

--prefix=/usr
--with-krb5=/usr/
--with-afs=/usr

Building the openafs-krb5 package is done with debuild as always (see above for more information). The software is built using make on a non Debian GNU/Linux box...

Installing OpenAFS KerberosV support software

The build process will create the openafs-krb5 package, and is installed using dpkg. On a non Debian GNU/Linux box, issue the command make install.

Configure OpenAFS KerberosV support software

No configuration of the OpenAFS Kerberos V migration kit have to be done. Instead of using klog to get a AFS token, one uses aklog instead. This is (usually) done by the OpenAFS PAM module, but not always, so use aklog after getting a Kerberos V ticket.

OpenAFS PAM module

This package is intended to be used by PAM aware programs getting a AFS token, and requires aklog which is in the OpenAFS KerberosV support software. Use it as any other PAM module.

Building and Installing the OpenAFS PAM module

The source for this is called libpam-openafs-session, so a

apt-get source libpam-openafs-session

is needed to get source for the package. Using the same command as when we were building OpenAFS, we will end up with the package libpam-openafs-session. This package is installed using the command dpkg -i (as ANY package is installed on a Debian GNU/Linux box is :).

Building and installing this software on a non Debian GNU/Linux box, issue the command make and then make install.

The installation of this software will result in a file called

/lib/security/pam_openafs_session.so

on a Debian GNU/Linux box, and

/lib/security/pam_openafs-krb5.so

on a non Debian GNU/Linux machine. Why the files are named differently, is something you will have to ask the maintainer for the Debian GNU/Linux package about. I have not bothered with this, so be my guest asking him :)

Configure OpenAFS PAM module

The is no configuration that needs to be done for this package, it's just a matter of using it. This is done in the service file, located under /etc/pam.d. For example, using the pam_openafs_session module with ssh, this is what my /etc/pam.d/ssh file looks like (use as directed :)

auth            required        pam_nologin.so
auth            required        pam_env.so
auth            sufficient      pam_krb5.so forwardable
auth            required        pam_unix.so try_first_pass shadow
auth            required        pam_issue.so issue=/etc/issue.net

account         sufficient      pam_krb5.so forwardable
account         required        pam_unix.so try_first_pass shadow

password        required        pam_krb5.so forwardable

session         sufficient      pam_krb5.so forwardable
session         optional        pam_openafs_session.so
session         required        pam_unix.so
session         optional        pam_lastlog.so
session         optional        pam_motd.so

How much of this that's actually needed, is up to you to decide and verify, but this works for me. What this file do, is verify the password against the Kerberos V database, OR if that fails, against the /etc/shadow file (the shadow option). When that is done, it will obtain a AFS token when the session starts.

We should really only add this module to services that have an interactive session, such as ssh, login, ftp etc. NOT something like the IMAP and POP services (unless you deliver mail to the users home directory that is).

Configure OpenAFS

Creating a AFS service key

There is some things that needs to be setup before we can use AFS. One such thing is to create a service principal for AFS. This is in the form afs@REALM. Usually your AFS cell is the same as your Kerberos realm, just in lower case. So since my Kerberos realm is BAYOUR.COM, I decided to use the AFS cell name of bayour.com. If your AFS cell name don't match your Kerberos realm like this, you will have to use the AFS principal form afs/CELL@REALM (like: afs/google.com@BAYOUR.COM). Creating the service principal, and putting it in a keytab is done like this:

kadmin.local -q "ank -randkey afs"
kadmin.local -q "ktadd -e des-cbc-crc:v4 -k /etc/krb5.keytab.afs afs"

Putting the AFS service key into the AFS KeyFile

We need AFS to recognize the service principal, and that is done by putting the service key into the AFS KeyFile. This is done with the command asetkey like this:

asetkey add 4 /etc/krb5.keytab.afs afs

The number 4 here is the keynumber that got created in Creating a AFS service key so make sure you took note about this. If you forgot which number it is, you can use the following command line to find that out:

kadmin.local -q 'getprinc afs' | grep ^Key

Mount the AFS volume

AFS uses a special directory and file structure, very different from the ordinary UN*X way of storing files. We need a special partition to be mounted on /vicepX where X is a letter from a to z (and from aa to zz – see the OpenAFS documentation for more about this). There have been indications that this partition can not be on a journaling file system (such as JFS, XFS and Ext3) on Linux.

If you don't have a free partition, you can settle for a file that is mounted using the loop module. Create such a file like this:

dd if=/dev/zero of=/var/lib/openafs/vicepa bs=1024k count=32
mke2fs /var/lib/openafs/vicepa
mount -oloop /var/lib/openafs/vicepa /vicepa

Create the new cell

Setup the cell configuration files

We need to have our IP address and cell name in both the file server cell configuration file and in the Client configuration file. If this is to be both a client and server, that is. Usually the very first machine is both, but does not need to be. In Debian GNU/Linux, the configuration files is /etc/openafs/server/CellServDB for the file server, and /etc/openafs/CellServDB for the client. Make sure our IP address and cell name is located at the top of these files. The format of this file is:

>CELLNAME
IPADDRESS

So for my test environment, these files begin like this:

>bayour.com
192.168.1.4 # tuzjfi.bayour.com

We also need to specify which cell this is and the configuration file for this is /etc/openafs/ThisCell. In my example, my AFS cell name is bayour.com, so I enter this into this file.

Setup AFS services

When this is done, we can start the fileserver with the command

/etc/init.d/openafs-fileserver start

Now it's time to setup and start the other services that we need for this to be a proper file and database server for AFS. I will only list them right of, no explanation.

bos addhost tuzjfi tuzjfi -localauth ||true
bos adduser tuzjfi turbo -localauth
bos create tuzjfi ptserver simple /usr/lib/openafs/ptserver -localauth
bos create tuzjfi vlserver simple /usr/lib/openafs/vlserver -localauth
bos create tuzjfi fs fs -cmd /usr/lib/openafs/fileserver \
        -cmd /usr/lib/openafs/volserver -cmd /usr/lib/openafs/salvager \
        -localauth
vos create tuzjfi a root.afs -localauth

In these examples, I have specified tuzjfi which is my test platform's hostname. Replace with your hostname! Also, the paths to the commands (/usr/lib/openafs/) might differ from your installation, so take note!

Also, turbo in these commands is my principal name which is to be the administration user for my AFS cell. Exchange with your principal name!

When this is done, we can start the AFS client which mounts the /afs tree which is where we access our AFS file system. This is done with the command

/etc/init.d/openafs-client force-start
Do not under any any circumstances access anything under /vicepX! It is in special AFS format, and any changes might render your AFS system unusable!
Getting a Kerberos ticket and a AFS token

To be able to create volumes (which can roughly be translated to partitions – storage space in AFS), we need a token for the administration user (which we created above). This is done by issuing the command (exchange with your principal name):

kinit turbo && aklog
Setting up root volumes

The following command sequences will create the necessary volumes with the proper access control. Don't forget to change all occurrences of 'tuzjfi' to your hostname, and all references to 'bayour.com' to your cell name. The 'bayour' entries is quick access links to the cell mount point, and it's up to you if you want/need them...

fs sa /afs system:anyuser rl
vos create tuzjfi a root.cell -localauth
fs sa /afs/bayour.com system:anyuser rl
fs mkm /afs/.bayour.com root.cell -cell bayour.com -rw
fs mkm /afs/.root.afs root.afs -rw
ln -s /afs/bayour.com /afs/bayour
ln -s /afs/.bayour.com /afs/.bayour
vos addsite tuzjfi a root.afs -localauth
vos addsite tuzjfi a root.cell -localauth
vos release root.afs -localauth
vos release root.cell -localauth

Testing the OpenAFS softwares

Testing OpenAFS KerberosV support software

To verify that it is possible to get a AFS token from the OpenAFS server(s), you must have a Kerberos V ticket. This is done using the command kinit. If kinit where successful in getting a ticket, it will look something like this when looking at the ticket. Viewing what tickets you have is done with the command klist without parameters, like this:

[papadoc.pts/1]$ kinit
Password for turbo@<MY_KERBEROS_REALM>: 
[papadoc.pts/1]$ klist
Ticket cache: FILE:/tmp/krb5cc_turbo
Default principal: turbo@<MY_KERBEROS_REALM>

Valid starting     Expires            Service principal
05/31/02 09:59:23  05/31/02 19:59:19  krbtgt/<MY_KERBEROS_REALM>@<MY_KERBEROS_REALM>


Kerberos 4 ticket cache: /tmp/tkt1000
klist: You have no tickets cached
[papadoc.pts/1]$ 

Now it's time to get the AFS token:

[papadoc.pts/1]$ aklog
[papadoc.pts/1]$ tokens

Tokens held by the Cache Manager:

User's (AFS ID 1) tokens for afs@<MY_AFS_CELL> [Expires May 31 19:59]
   --End of list--
[papadoc.pts/1]$ 

As you can see, if everything goes well, aklog won't output anything. This is in good old UNIX style. If it's okay, why say anything :)

Testing OpenAFS PAM module

When the Testing OpenAFS KerberosV support software have been successful, it is time to verify that the PAM module works. This is done by trying to login with a service that is OpenAFS aware. In Configure OpenAFS PAM module we enabled the ssh service to use OpenAFS, so we try to login through ssh.

Miscellaneous information

Migrating existing users

For those that are converting an existing setup (be it users located in /etc/passwd, NIS/NIS++, NDS etc) it would be nice if there where a 'execute and continue' solution to on the fly convert the current database while keeping the users passwords. But there is no such thing, and never will (in most cases anyway). This is because most, if ALL 'password storage systems' have some means of encrypting the password. And most of them is a one-way encryption, meaning that it's not possible to decrypt it (only force a check, trying out random password to see if it's a match).

It is therefor necessary to either write a program that inserts the users password into Kerberos (after a successful authorization) or you can ask each and every user to come to you to receive/change their password. On a big system, this is just not possible, so there you have to go with option one.

There is however a third alternative, although in my eyes not the perfect one... It is to only include the NEW users in this new system, and slowly migrate (forcing a password change) the existing ones.

I went for the first alternative, because my users are very spread geographically, so it was not possible for them to come to me for a new password, and I don't like to talk passwords over the phone. Some of my users I never meet. So what I did was I modified the pam_ldap module to insert the users clear text password into the clearTextPassword attribute in the LDAP database, then after three months I did a search for users with a clearTextPassword entry, and use that when changing the users password in the Kerberos server. Something like this:

ldapsearch -LLL 'cleartextpassword=*' clearTextPassword krb5PrincipalName

This will give us something like this

dn: uid=turbo,ou=People,dc=papadoc,dc=bayour,dc=com
krb5PrincipalName: turbo@<MY KERBEROS REALM>
clearTextPassword: ThisIsMySecretPasswordInClearTextFormat

This will however also give us the passwords that are set to 0 or *. We must initially set it to some value, because OpenLDAP does not allow us to insert a NULL value. You either use an attribute (which requires a value) or you don't. So you'll have to write a script that parses the information, filtering out those that don't make sense.

Then, for each value retrieved, modify the krb5PrincipalName with the value of clearTextPassword. If you're paranoid, or don't want this information in the database, just modify each LDAP object, removing the clearTextPassword attribute and the corresponding object class.

To change a password in the Kerberos database in a script, this is how to do it

kadmin.local -q "cpw -pw <USER PASSWORD> <USER PRINCIPAL>"

The magic here is the -pw option.

Bumping the Debian GNU/Linux package version

Instead of putting the packages on hold, one can increase the version number in a 'secure' way. That is, one makes the version number such that it will always be higher than the default Debian package number, that way it won't be upgraded/overwritten by a default Debian version. To do this, one edits the file debian/changelog. If we take the entry I made for the cyrus-sasl packages as an example, the top of the changes file will look like this:

cyrus-sasl (2:1.5.24-5.TF.3) unstable; urgency=low
  * --without-des. It seems that's part of the Krb4 packages, not Krb5...

 -- Turbo Fredriksson <turbo@debian.org>  Sun,  1 Apr 2001 19:10:58 +0200

cyrus-sasl (2:1.5.24-5.TF.1) unstable; urgency=low
  * Can't do search with '-H ldaps:///', but to the non-ssl works.
    Norbert Klasen <klasen@zdv.uni-tuebingen.de> say:
    Seems to be some signend/unsigned arithmetic mismatch.
    => Patched plugins/gssapi.c

 -- Turbo Fredriksson <turbo@debian.org>  Wed,  7 Mar 2001 15:30:00 +0100

cyrus-sasl (2:1.5.24-5.TF) unstable; urgency=low
  * Build with the following parameters to configure:
        --enable-gssapi         Needed to have kerberos auth
        --with-des              Even better to have I guess

 -- Turbo Fredriksson <turbo@debian.org>  Tue, 27 Feb 2001 17:34:33 +0100

The important number here is 2: before the actual number (1.5.24-5). This number will not be seen when doing a

dpkg -l libsasl-modules

but only when doing

dpkg -s libsasl-modules | grep '^Version: '

The .TF is added just to make sure that I remember that it's a home made packages. It will however work just fine without it. If I remove the 2: and just have .TF, the package will be upgraded by any package with a version number higher than 1.5.24-5. That can be, for example 1.5.24-5.1 which would indicate the first Non Maintainer upload. A fix for this package, by the maintainer, would have the number 1.5.24-6 which would also overwrite my package (if I didn't have the 2:). By setting myself (the Turbo Fredriksson <turbo@debian.org> entry) I will be listed as the maintainer when viewing the status of the package (dpkg -s libsasl7 for example). That is also a indication that it is a home made package. To make this a 'fully fledged Debian package', instead of issuing the command debuild -uc -us -rfakeroot i will remove the -uc -us (which is unsigned source and changelog. Without those two parameters, the package will be signed with my PGP (or GPG) signature. In emacs, there's the debian-changelog-mode command, that will give you a proper editing mode for changelogs. The mode is in the emacs package.

Problems that can occur

Nothing works right out of the box. Sad to say, but that's the way it is. I have tried to list as many of the most common problems here, but I'm still working on this, so please contribute!

Problems when the KVNO don't match up.

No such attribute error

No such object error

Local error

Problems with ACL's

SLAPADD problems/messages

Attribute type undefined

Attribute not allowed

Missing required attribute



If you can't have pam_ldap to authenticate you, this is most likely a problems with ACL's

Problems when the KVNO don't match up.

A problem with the kvno can be verified by executing the klist -k command. If I do it on my machine, I will get this output:

Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   4 kadmin/admin@<MY KERBEROS REALM>
   4 kadmin/admin@<MY KERBEROS REALM>
   4 kadmin/changepw@<MY KERBEROS REALM>
   4 kadmin/changepw@<MY KERBEROS REALM>
   5 ftp/<MY FQDN>@<MY KERBEROS REALM>
   3 host/<MY FQDN>@<MY KERBEROS REALM>
   3 host/<MY FQDN>@<MY KERBEROS REALM>
   4 ldap/<MY FQDN>@<MY KERBEROS REALM>
   5 ftp/<MY FQDN>@<MY KERBEROS REALM>
   4 ldap/<MY FQDN>@<MY KERBEROS REALM>

The reason there are two of a kind, is because they use different crypto algorithms. To check this, use the command

klist -keK | grep ldap

(we're only interested in the ldap service key at this point), it will return something like this:

   4 ldap/<MY FQDN>@<MY KERBEROS REALM> (DES cbc mode with CRC-32)  (0x<A HEX NUMBER>)
   4 ldap/<MY FQDN>@<MY KERBEROS REALM> (Triple DES cbc mode with HMAC/sha1) (0x<A HEX NUMBER>)

To verify that the kvno for the ldap service key is correct, issue the command

kvno ldap/<MY FQDN>@<MY KERBEROS REALM>

This is what I get back:

ldap/<MY FQDN>@<MY KERBEROS REALM>: kvno = 4

As you can see, they match up now. However, I wasted two whole days on looking for a problem with OpenLDAP/SASL, when it was in fact a problem with this number.

If the number received from kvno is lower than the number received from klist, one have to remove all the service keys and principal of that service and then add them again. I doubt that this is the correct/best way to do it, but it works for me (probably since this is a fresh install, without a big DB etc.).

kadmin.local -q "ktrem ldap/<FQDN> all"
kadmin.local -q "delprinc ldap/<FQDN>"
kadmin.local -q "addprinc -randkey ldap/<FQDN>"
kadmin.local -q "ktadd -k /etc/krb5.keytab ldap/<FQDN>"

If the number from kvno is higher than the one from klist, just add the service key to the keytab, removing (?) all the old ones. Use ktadd below until the numbers from both klist and kvno match up.

kadmin.local -q "ktadd -k /etc/krb5.keytab ldap/<FQDN>"
kadmin.local -q "ktrem ldap/<FQDN> old"

Update, 4/13/01: When doing all this for a company I'm doing some consulting for, I noticed that this might not be necessary (removing and then adding the principal, that is). I'm not sure what happened, but I'll tell you what I did.

The company have three machines, dns1, dns2 and kattla (the dragon from Astrid Lindgren's Lionheart). Kattla is the LDAP/Kerberos server, and dns1 and dns2 is the DNS servers.

I added the host/<FQDN> principals for the three machines in kattla's keytab. When trying krsh/ktelnet to dns1, the machine complained about 'no such file'. Using strace I found that kshd/ktelnetd where looking for the keyfile /etc/krb5.keytab. I had hoped that I wouldn't need that (since I thought/had hoped that all that would be in the KDC). Now, I wouldn't want to copy the whole keytab from kattla (since that included ALL server's host keys). So I executed

ktadd -k /etc/krb5.keytab.dns1

on kattla and copied that file to dns1 as file /etc/krb5.keytab. Logical conclusion? I thought so. But that's where I got the same problem as before. The keytab on dns1 had version 4, but I had tried connecting and got version 3 in my ticket (that is, doing kvno host/dns1.DOMAINNAME on my own server, revealed version 3). This was a real nuisance. I couldn't figure out a way to have the same version in the two files.

Doing some testing, I tried executing kdestroy and then kinit again. That helped!

Now, I'm not sure if I really need all the host keys in kattla but as said, I'm not very good at Kerberos administration yet...

No such attribute error

You get this error when SASL isn't configured/working properly. Please see the simple bind examples on when to know if SASL works or not.

No such object error

This is most likely because you are trying to do a simple/anonymous bind, but aren't using the correct parameters to ldapsearch/ldapadd/ldapmodify. Try adding -x to the command line. If you are using -x, but still get this error, it might be that your ACL's don't allow viewing the base dn (where the supportedSASLMechanisms attributes are).

Local error

This error messages will look like this

# ldapsearch -h localhost -p 389 -I -b "" -s base -LLL supportedSASLMechanisms
SASL/GSSAPI authentication started
SASL Interaction
Please enter your authorization name: 
ldap_sasl_interactive_bind_s: Local error

This is because you don't have a Kerberos TGT (Ticket Granting Ticket). Just execute kinit to get a ticket.

Will Day (on the OpenLDAP-Software list) also reported that he got this problem because he hadn't specified the FQDN host name of the LDAP server, which led it to default to localhost, for which it couldn't get a Kerberos ticket.

Problems with ACL's

I migrated from OpenLDAP1 to OpenLDAP2. Having used OpenLDAP1 for over a year on a number of production servers, going to OpenLDAP2 was quite a nuisance. The first problem I got was that the old database wouldn't load at all (which was a problem with the non-existence of proper schemas). The other, and the one that gave me the most grief was the ACL's. It seems like OpenLDAP2 is much more strict about the correctness and order of the ACL's. So it's important to have all the stuff in the right order and in the right place. By a lot of trial and error, I came up with The OpenLDAP access file you see in this document. It might be the most perfect, but at least it works. If all other fails, try my ACL and see if that work. If it does, start modifying that to get the restrictions you want. I'm still working on perfecting this list, so come back every now and then to see if I have any updates...

Otherwise, don't hesitate to ask on the OpenLDAP-Software mailing list or if you need to make your own schemas, have a look at the OpenLDAP2 Admin Guide:Schema Specification.

SLAPADD problems/messages

Attribute type undefined

slapadd: could not parse entry (line=<SOME LINE NR>)

This (usually ?) means that one (or more) of the attribute you are trying to use, don't exist in any schema. For example, I kept getting this when trying to use the objectclass krb5Principal. The attribute I meant to use where krb5PrincipalName but a typo slipped in the LDIF, so it was named krb5Principal instead...

NOTE: The line it complains about, is the first empty line after the object (that is, the empty line between the two adjacent objects) in the LDIF file. There is no problem on the line itself, but the object above the empty line. To find exactly what attribute it complains about, copy the whole (and ONLY the) troublesome object to a separate LDIF file, and try to just add that object. Then use -d -1 when executing slapadd.

Solution: Correct attribute name

Attribute not allowed

slapadd: dn="<SOME DN>" (line=<SOME LINE NR>): attribute not allowed

This (usually ?) means that you have attribute which is not a MUST or MAY attribute in the objectclasses you are using.

Solution: Find the objectclass this attribute belong to, and add that to the LDIF.

Missing required attribute

slapadd: dn="<SOME DN>" (line=<SOME LINE NR>): missing required attribute

This should be quite obvious. You are trying to use a objectclass, but you have not specified one (or more) of the MUST attributes. For example, when trying to modify my old DB (replacing the attribute userPassword), I wrote a perl script that parsed the old LDIF, and replaced all the userPassword: {crypt}... values with userPassword: {KERBEROS}user@<MY KERBEROS REALM>. Some of the objects (especially the AdminDN object) should not be replaced, it should retain the crypted value. But my script was buggy, so the attribute where totaly removed. Those DN's used the objectclass simpleSecurityObject which MUST have the attribute userPassword.

Solution: Add the missing REQUIRED (MUST) attributes to the LDIF.

Shortcuts

For those of you running Debian GNU/Linux which thinks all this about making your own package are daunting, or if you're just to lazy to do it your self, you can always get the pre-compiled binaries from me. I make no promises to keeping them up to date, I'm deploying this on a live server, without access to a development platform. Because of this, it's difficult to keep downloading packages, remake them and then doing a install. IF something breaks, it will break my live server!

HOWEVER, if you thing it's about time I upgraded (ie, these packages are WAY out of date) don't hesitate to send me a simple and friendly 'nudge' mail, telling me to get my acts together! :)

APT configuration

If you use Debian GNU/Linux and would like to use the packages I've created, here's the line you should add one of the following lines to the /etc/apt/sources.list file, and run the command apt-get update to update the list of available packages.

deb ftp://ftp.bayour.com/pub/debian local .
deb-src ftp://ftp.bayour.com/pub/debian local .

These packages have such a higher version number, that they won't be upgraded by the packages from the official Debian GNU/Linux FTP sites. See the section about Bumping the Debian GNU/Linux package version section of what I mean.

Packages are available for the Intel processors and for Sun SPARC only. Unfortunately I don't have any Alpha, PPC, m68k machines, so I can't currently support these architectures. Using my source packages, all you have to do is download them yourself, and compile using debuild as directed elsewhere in this document...

These are the packages that are available for installations

KerberosV server

KerberosV client

KerberosV services

PAM/NSS

krb5-kdc

krb5-doc

krb5-ftpd

libnss-ldap

krb5-admin-server

krb5-user

krb5-rsh-server

libpam-ldap

krb5-dev

krb5-clients

krb5-telnetd

libpam-krb5






OpenSSL

Cyrus SASL

OpenLDAP2

OpenAFS

libssl0.9.6a

libgdbmg1

libiodbc2

openafs-dbserver

openssl

libpam0g

libldap2

openafs-fileserver

libssl0.9.6a-dev

libcommerr2

ldap-utils

openafs-modules-source


libkrb53

slapd

openafs-client


libsasl7

libldap2-dev

libopenafs-dev


libsasl-modules


libpam-openafs-session


libsasl-bin




Miscellaneous

PostgreSQL

cvs

libecpg3

ssh

libpgsql2.1

sudo

odbc-postgresql

postgresql

postgresql-client

postgresql-dev

Table 1: Packages to install. Packages in italic is for development only...

The PAM/NSS modules above will come with SSL and TLS enabled, if downloaded from me. CVS, SSH, sudo and PostgreSQL is compiled with GSSAPI/Kerberos support (which the original packages are not).

Mailing lists for help

Debian GNU/Linux

MIT Kerberos V

NSS/LDAP

OpenAFS-Info

OpenSSL

Cyrus SASL

PAM/LDAP


Berkeley DB

OpenLDAP

Samba TNG


LDAPv3, why bother

Foreword

Papadoc, before conversion

Why SSL/TLS?

Why Kerberos?

Kerberos replacement software

Why SASL?

Foreword

Why should we use so much encryption and such a complicated setup, when user information (inclusive the password) works so great together with libpam-ldap? Well, basicly the keyword here is growth (and maybe security, even though many isn't that paranoid as me :). To illustrate what I mean by growth, I will show you the system I use, and the (small) differences to a system I did for the company I worked for.

Papadoc, before conversion

I only have one machine (called papadoc for 'historical' reasons). This system 'only' hosts five domains, with about 50 users (most of them family and friends). Having users (and all there relevant information, such as UID/GID number, home directory, passwords, mail address, mail aliases etc, etc) in an LDAP database, using libpam-ldap to help authentication, was my main reason for LDAP. Be able to structure users in a tree-like fashion, with the possibility to have a fail-over system (an extra LDAP database, a so called 'replica') is a very nice feature. But I'm not going to tell you much about the reasoning for LDAP in the first place, there are other, better HOWTOs/FAQs etc out there.

At my previous job, we had the exact same system, but with a lot more domains, a lot more users and finally, a lot more machines. Since this was an ISP, redundancy is vital. So a replica was quickly setup (so that we could have an online backup of the user/mail database). Using round-robin (poor mans load-balancer) reduced the load of the master database.

Why SSL/TLS?

Here came (and comes for me to when, not if, I add a second DB or a second machine, be it shell, mail server or other type of system) the first big gripe I had with OpenLDAP1 (at the time of this writing, I'm still running OpenLDAP v1.2.11 on my system, but are slowly migrating to OpenLDAP2 according to this document). Since OpenLDAP1 don't have built in support for SSL/TLS (or any other secure authentication mechanism), all communication between the master and slave (or by any of the other servers on the network, about 50 or so at last count) is done in clear text! It's quite easy for someone on the same network segment (yes, EVEN if it's a switched network!) to listen on the communication and retrieving all the passwords etc. This can be avoided to some extent by using external programs to do the SSL tunnelling, such as stunnel. My experience with this is that it isn't that reliable. Stunnel dies every now and then, and it's difficult to automate the process. Another big gripe I had, was the fact that the replication DN and password (options replica and bindmethod) have to be stored in clear text in the configuration file. And the third thing is that libpam-ldap is doing the authentication in clear text as well. This isn't true any more (latest version, v99), since it can be compiled with SSL support.

Using only PAM/LDAP, an authentication happens something like this:

login -> PAM -> PAM/LDAP -> LDAPServer

Everything between login and the LDAP server is clear text communication.

Also imagine adding a second system, or putting the LDAP serveri on it's own machine. All logins (be it login/imap/pop/ssh/ftp etc) is verified in clear text between the system and the machine where the LDAP database is residing. Now we have tree machines, the actual server, the master LDAP database and the slave database (or a second login system). Login in this text does refer to a software that does some kind of user authentication, not the program login. All communication back and forth is done in clear text, giving anyone (basically) the chance to discover any password.

Why Kerberos?

But why store the user passwords in the Kerberos database in the first place? Why not just use it for/when we need a replica (or replicas)? We only really need Kerberos to have a service key, right? Nope, not quite true. The answer is quite simple actually. Kerberos is designed solely as a secure password storage database (with a secure authentication protocol) on an insecure network. And contrary to popular belief, a local network IS NOT to be considered a secure environment! LDAP, on the other hand, is designed to be a database for distributed, public information.

Kerberos replacement software

Put simply, passwords are more secure in a Kerberos database, than in a LDAP ditto. Besides, with at least MIT Kerberos, there are special, kerberised binaries that replace the original ones. This will give you a more secure way of authentication (you don't have to go through PAM etc). The software to let this be possible, is libnss-ldap. It will get all the public information (such as UID/GID numbers, home directory etc, etc) from LDAP, but look at the Kerberos server fo the password. Thus, all sensitive information is encrypted, even before leaving the binary. The binaries/services that can be replaced right-out-of-the-box is login, ftpd, ftp, rlogind, rlogin, rshd, rsh, telnetd, telnet and passwd.

Why SASL?

Oki, I guess I have convinced you why it is imperative to use SSL/TLS, and we have discussed some of the nice things about Kerberos. But why use SASL? Where does that come into play? Well, when using the combination SASL and KerberosV (SASL can use other means of storing password, Kerberos is just my choice), we can use a KerberosV keytab to authenticate the master database with the slave with. Thus, no need for any passwords etc in the slapd configuration file. See Creating a replication principal for more about this. The reason we use SASL, is because SASL is designed as a middle-layer. That is, it sits between the LDAP server and the authentication system (in this case, Kerberos). As mentioned, SASL could just as well use any other authentication system, such as the default UNIX way (/etc/passwd, /etc/group etc), it's own database file (usually /etc/sasldb) etc. In theory, it can even use a LDAP database (which might be a little redundant, and difficult do obtain, with out creating authentication loops). With a little code writing, it's even possible to use a KerberosIV server. Some use libpam-smb to look-up the user/password on a Windows PDC. Simply, SASL is designed as a modular authentication protocol, and it's usage is as a middle-layer. The difference between SASL and PAM (which in many ways resembles each other) is that SASL have integrity and confidentiality protection, while PAM don't have anything like that.

With all this stuff we have discussed (LDAP, SSL/TLS, SASL and Kerberos), we get this flow of authentication (remember the flow, libpam_ldap?):

login -> PAM -> PAM/LDAP -> SSL/TLS -> LDAP -> SASL -> KerberosV

If we only want the UID/GID number etc (like when doing ls -l etc), the communication stops at the LDAP server, and don't continue with SASL/Kerberos.

There are still many hops the information have to travel, many of them not that very secure (like PAM). So to minimise that, we could replace many (preferably all) of the programs with proper Kerberised binaries, see the section about Kerberos replacement software. That will create the following authentication flow.

For public information:

login -> NSS -> NSS/LDAP -> LDAP

and for password authentication:

login -> Kerberos

Much cleaner, don't you think? A nice feature would be to have SSL/TLS to the libnss-ldap software, but I'm not quite that paranoid yet :). It might already have that option, I just haven't bothered to check...

UPDATE: I just recompiled the libnss-ldap package, and if the OpenSSL development package are installed, libnss-ldap will come with SSL/TLS.

Updates

In the package listings below, the package names in bold is the one you need if installing the rest of my packages (ie, just using the packages, not building anyting yourself) and the ones in italic is needed for building you own packages of the other software. If you are very daring, have a look at the Shortcuts section.

BerkeleyDB

v3.3.11

15/8 2001: Build and install exactly like you did on Building and installing Berkeley DB.

Unfortunately, Sleepycat have changed some of the interface, so that OpenLDAP will have to be rewritten slightly to use the new version of BerkeleyDB.

THAT IS, OPENLDAP WILL NOT WORK WITH THIS VERSION OF BERKELEYDB!

OpenSSL

v0.9.6a

28/5 2001: Built v0.9.6a from the Debian GNU/Linux sources. See OpenSSL.

openssl
libssl0.9.6
libssl-dev
ssleay

v0.9.6b

15/8 2001: Built v0.9.6b from the Debian GNU/Linux sources. See OpenSSL.

OpenLDAP

v2.0.10

28/5 2001: According to a mail on the OpenLDAP-Software mailinglist:

At 05:17 PM 5/22/01, Mark Whitehouse wrote:
I am experiencing some database corruption problems with back-ldbm using
Berkeley DB 3.2.9.  Any advances over this configuration would especially
interest me.

v2.0.11

12/8 2001: I'm currently testing this version, and it works fine in a CHROOT jail.

I'll try to upgrade my machine the next couple of hours/days and let you know...

[papadoc.pts/4]$ dpkg -l | grep ssl
ii  libssl0.9.6    0.9.6b-1       SSL shared libraries
ii  libssl09       0.9.4-5        SSL shared libraries
ii  libssl09-dev   0.9.4-5        SSL development libraries
ii  libssl095a     0.9.5a-5       SSL shared libraries
ii  openssl        0.9.6b-1       Secure Socket Layer (SSL) binary and related
[papadoc.pts/4]$ dpkg -l | grep ssl
ii  libssl-dev    0.9.6b-1       SSL shared libraries

16/8 2001: I just don't seem to get this to work. I'm still working on it though, since I REALLY need it!

v2.0.14

21/11 2001: I finally got this version to work! You will have to patch servers/slurpd/config.c. This is what it looks like:

diff -urN openldap-2.0.10/servers/slurpd/slurp.h openldap-2.0.10.new/servers/slurpd/slurp.h
--- openldap-2.0.10/servers/slurpd/config.c     Mon Sep 18 18:08:08 2000
+++ openldap-2.0.10.new/servers/slurpd/config.c Thu May 24 15:29:17 2001
@@ -34,7 +34,7 @@
 #include "slurp.h"
 #include "globals.h"
 
-#define MAXARGS        100
+#define MAXARGS        500
 
 /* Forward declarations */
 static void    add_replica LDAP_P(( char **, int ));

The patches you see in the Bugs in OpenLDAP, v2.0.7 section is NOT needed with this version. The only patch necessary is the one above (servers/slurpd/config.c). Also, this patch is NOT needed with OpenLDAP v2.0.18 and later! I'm currently trying to install that, I'll let you know...

v2.0.18

21/11 2001: This worked right out of the box! Weird! No patches had to be applied, I just compiled it according to the section Building OpenLDAP v2.

v2.0.21

24/01 2002: This worked out perfectly! No need for any patches etc. Just compile and install!

Note that you should really install this, and not anything earlier. There is a bug in version 2.0.19 (and earlier I assume).

v2.0.22

06/02 2002: This worked out perfectly! No need for any patches etc. Just compile and install!

Just for the record, these are the changed files in the Debian GNU/Linux package. Other than this, I made no changes...

  1. The debian/rules
  2. The debian/changelog

v2.0.23

26/03 2003: Same as previous version. Works great! Same modifications as v2.0.22.

  1. The debian/rules
  2. The debian/changelog

CyrusSASL

v1.5.27

20/11 2001: Thanx to Allan Streib, I got some updates on the new CurysSASL software:

  1. There is a potential security vulnerability in cyrus-sasl versions prior to 1.5.27. It is described at: http://xforce.iss.net/static/7443.php

  2. To close the vulnerability above, I downloaded version 1.5.27 from the cyrus FTP site. I found that the problem corrected by your patch 1 has been corrected in this version of gssapi.c. However the second problem (REALM being dropped in a GSSAPI SASL bind) is still there. But your second patch file could not be applied, as there are enough other changes to gssapi.c that patch(1) could not resolve the context. I created the attached patch which corrects the problem in the 1.5.27 release. To apply it, change to the plugins directory and enter:

patch < cyrus-sasl-1.5.27-gssapi.patch

26/03 2002: Rein Tollevik found a problem with chain-crashing postfix-tls using SASL LDAP authentication. Without this patch, all applications that both link to OpenLDAP and use SASL (maybe through PAM) will segfault. Apply this patch by issuing the command:

patch -p1 < cyrus-sasl-1.5.27-sasl_allocation_locked.patch

MIT KerberosV

v1.2.4

04/03 2002: I'm currently looking into compiling this. These are the changes between the 1.2.2 and 1.2.4 releases:

Changes between 1.2.2 and 1.2.3
Changes between 1.2.3 and 1.2.4

My configuration files

Just to make sure that there are no typos or that you haven't misunderstood etc anything in my configuration examples, these are my configuration files (they are however censored). With these files, everything works like a charm. Replication, Secure searches and updates, simple binds etc, etc... They might not be absolutely optimised, but they work...

Master LDAP server

Start script

/etc/init.d/slapd

Configuration file

/etc/ldap/slapd.conf

Access Control Lists file

/etc/ldap/slapd.access

Slave LDAP server

Start script

/etc/init.d/slapd.backup

Configuration file

/etc/ldap/slapd.conf.backup

Access Control Lists file

/etc/ldap/slapd.access.backup

PAM/LDAP files

Name Service Switch configuration file

/etc/nsswitch.conf

Configuration file for LDAP NSS library

/etc/libnss-ldap.conf

Configuration file for LDAP PAM library

/etc/pam_ldap.conf

Misc files

LDAP configuration file

/etc/ldap/ldap.conf

KerberosV configuration file

/etc/krb5.conf

Tables for driving cron

/etc/crontab

Bind9 w/ LDAP SDB driver

/etc/bind/named.conf*

Reference material

Patches

OpenSSH+Kerberos

LDAP

LDAPv2

RFC1777

Lightweight Directory Access Protocol

RFC1778

The String Representation of Standard Attribute Syntaxes

RFC1779

A String Representation of Distinguished Names

RFC1959

An LDAP URL format

RFC1960

A String Representation of LDAP Search Filters

RFC1823

The LDAP Application Program Interface (C language API)

RFC 2596

Use of Language Codes in LDAP

LDAPv3

RFC 2251

Lightweight Directory Access protocol

RFC 2252

LDAPv3: Attribute Syntax Definitions

RFC 2253

LDAPv3: UTF-8 String representation of Distiguished Names

RFC 2254

The string representation of LDAP search filters

RFC 2255

The LDAP URL format

RFC 2256

A summary of the X.500(96) User Schema for use with LDAPv3

RFC 2830

LDAPv3: Extension for Transport Layer Security



Readme

Some differences between LDAPv2 and LDAPv3

Authentication

SASL

RFC 2222

Simple Authentication and Security Layer (SASL)

RFC 2245

Anonymous SASL Mechanism

RFC 2444

The One-Time-Password SASL Mechanism

RFC 2829

Strong Authentication Methods for LDAP (SASL)



Draft

Using Digest Authentication as a SASL Mechanism

Draft

SASL GSSAPI Mechanisms

Draft

The SecurID(r) SASL Mechanism

Draft

X.509 Authentication SASL Mechanism

Draft

Telnet SASL Option

Draft

The Java SASL Application Program Interface

Draft

POP3 AUTHentication command

Draft

DSS Secured Password Authentication Mechanism

Draft

ROAMING-ELGAMAL SASL Authentication Mechanism

Draft

Salted Challenge Response Authentication Mechanism (SCRAM)



Documentation

Cyrus SASL library for System Administrators

Documentation

Configuring GSSAPI and Cyrus SASL

Documentation

SASL Programmer's Guide

Kerberos

RFC 1510

Kerberos v5



HOWTO

Frequently Asked Questions about Kerberos v5

HOWTO

How to Kerberize your site

Readme

Designing an Authentication System: a Dialogue in Four Scenes

Other

RFC 1321

The MD5 Message-Digest Algorithm

RFC 2052

A DNS RR for specifying the location of services (DNS SRV)

RFC 2104

HMAC: Keyed-Hashing for Message Authentication

RFC 2247

Using Domains in LDAP/X.500 Distinguished Names

RFC 2849

The LDAP Data Interchange Format (LDIF)



IBM Redbook

Understanding LDAP

© Mar 8, 2001, Turbo Fredriksson <turbo@bayour.com>. Last changed: Jan 29, 2005

Total number of access: (since Nov 4, 2003)