Kerberos II

So about two weeks ago I started playing with Kerberos. And I'm still not finished with it, kerberizing one service after the other. Really fun, that.

Kerberizing a network protocol involves somehow sending the Kerberos ticket in-band with the rest of the conversation. This is not entirely defined by the Kerberos protocol, and indeed, different network protocols have come up with different ways of sending the Kerberos ticket to the service. So far, I've encountered SPNEGO for HTTP, GSSAPI for IMAP and SSH, and SASL for LDAP. It sounds like a complex mess, but it really isn't; in general, kerberizing a service involves three steps:

  1. Installing the Kerberos plugin (if any) for both the server and the client;
  2. Generating the service principal, and adding it to a/the keytab;
  3. Configuring the service so that it knows it can do Kerberos, and so that it knows how to act when a Kerberos request is sent

Yes, in the cases I've seen it's really that simple. Although I'm skipping step 0 here–reading the documentation. But I've done that for you already ;-)

The hardest part is the initial setup. But even that isn't very hard, because the process is very well documented. For starters, install the krb5-doc package, and read the excellent /usr/share/doc/krb5-doc/README.KDC which explains just enough of the system to get you started. The rest will be explained to you through debconf and the like; and if you want more, the krb5-doc package also contains three info files which explain concepts and usage very well. There's an alternative implentation called heimdal, which I presume works similar; but I haven't tried it, so I don't have much details on that one. The process of installing krb5 is very straightforward; the only thing I'll let you know is that you should ensure that any host you're going to kerberize should have reverse name lookups configured and working correctly; otherwise, you're going to run into a bunch of serious problems.

After the initial setup, you'll have a Kerberos realm, usually your domain name in upper case (GREP.BE in my case). You'll now want to set up principals for your users and principals for your hosts. Now, let me show you how to configure Kerberos for LDAP, PAM, HTTP, IMAP, and SSH:

PAM
By installing and using the libpam-krb5 package, you'll log in to kerberos and receive your TGT immediately at login time; the alternative would be having to use kinit (in the krb5-user package) afterwards. pam_krb5.so also takes care of destroying your tickets when you log out, so that you don't have to worry about that. This is very handy, but not really required; you could just use kinit all the time. Of course, using pam_krb5.so also means you have only one password for everything—and that is a very good argument to use it.
Anyway; our three steps:
  1. Installing the plugin
  2. As you've guessed, libpam-krb5 is the package you'll need. That, or the heimdal implementation.

  3. Generating and installing the service principal
  4. In the case of any service such as PAM that will give you a shell (thus, as we'll see later on, also SSH), the principal is supposed to be host/<hostname>@<REALM>. For instance, on rock.grep.be, the principal PAM will use is host/rock.grep.be@GREP.BE. We'll create it with kadmin (which can be done on any kerberized host):

    wouter@rock:~$ sudo kadmin
    Password for root/admin@GREP.BE:
    kadmin:  addprinc -randkey host/rock.grep.be@GREP.BE
    WARNING: no policy specified for host/rock.grep.be@GREP.BE; defaulting to no policy
    Principal "host/rock.grep.be@GREP.BE" created.
    kadmin:  ktadd host/rock.grep.be@GREP.BE
    Entry for principal host/rock.grep.be@GREP.BE with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
    Entry for principal host/rock.grep.be@GREP.BE with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.
    kadmin:  q
    

    Generating the principal can really be done as any /admin user; but as the same isn't true for writing the keytab, I'm using sudo in the above example to become root.

  5. Configuring
  6. account	required	pam_krb5.so ignore_root
    auth	sufficient	pam_krb5.so ignore_root forwardable
    password optional	pam_krb5.so ignore_root
    session	optional	pam_krb5.so ignore_root
    

    After adding the above lines to the relevant files in /etc/pam.d, you should log off, then log on again, run 'klist', and marvel.

    If you add the lines to your passwd file as shown above, and don't remove the pam_unix.so lines, then local passwd-based authentication will still work. This can be nice if, for example, the Kerberos server is down, or you're working on a laptop that isn't always within reach of the Kerberos server. It doesn't do any harm; the worst that can happen is that at some point you happen to be on a network where there's a firewall which drops packets on the floor rather than sending you an ICMP port unreachable; in that case, you need to wait for the Kerberos login to time out, which takes half a minute or so (I haven't timed).

SSH
  1. Installation
  2. If you're running unstable, you don't need to do anything. The OpenSSH packages in unstable are all set to understand Kerberos.

    If, however, you're running stable, you'll want to replace your ssh package by the ssh-krb5 package, which is the regular SSH package plus some patches to enable GSSAPI (read: Kerberos) authentication.

  3. Service principal
  4. If you've done the PAM setup above, you're all set; SSH, being a service which gives you a shell, also uses the host/ service principal.

  5. Configuration
  6. Make sure both the server and the client have the GSSAPIAuthentication option enabled. After you've done so, restart the server.

IMAP
I'm using dovecot as my IMAP server, which has builtin support for GSSAPI authentication (at least in unstable; haven't checked stable in this regard).
  1. Installation
  2. As dovecot comes with everything compiled in, there is no need for installing extra packages.

  3. Service principal
  4. You'll need the imap/ principal (e.g., imap/rock.grep.be@GREP.BE). Note that the host name which is found by doing a reverse lookup on the ip of the server is what counts, not the name of the server as you're using it (so not, e.g., imap/imap.grep.be@GREP.BE)

  5. Configuration
  6. Edit your dovecot.conf, and find the line that starts with "mechanisms" in the auth default stanza. Make sure it contains at least the word gssapi. Restart dovecot.

    I haven't found a Free (as in speech) IMAP client that supports GSSAPI authentication. My client of choice, offlineimap, doesn't seem to support it; mutt doesn't either (unless I'm missing something); and while thunderbird in unstable is supposed to support it, I haven't been able to configure it correctly yet. Probably me. I have, however, been able to verify that it works by using a non-free software package. Obviously, this isn't good enough. In addition, I found that horde and imp don't like an IMAP server that has GSSAPI enabled if they don't, while enabling GSSAPI in horde requires a PHP extension that isn't packaged in Debian. So I've disabled it for the time being. Stay tuned.

LDAP
  1. Installation
  2. LDAP requires uses SASL for authentication, which doesn't have GSSAPI modules in the default package; for those, you need the libsasl2-modules-gssapi-heimdal package.

    Attentive readers will have noticed that this package contains the string heimdal in it, rather than krb5, and that this is not the same implementation that I've been using previously. Yes, true. But since there's no libsasl2-modules-gssapi-krb5, and since Kerberos is, after all, a well-defined protocol, this is not an issue—except in that you need a bit more diskspace for the additional libraries.

    Note that the modules have to be installed on both the client and the server.

  3. Service principal
  4. You need a service principal that starts with ldap/, obviously followed by the hostname and the realm.

  5. Configuration
  6. For those people whom you want to allow to authenticate themselves using Kerberos, make sure they have '{SASL}<principal>' in their userPassword attribute set (e.g., I have userPassword: {SASL}wouter@GREP.BE). You can have that in addition to a regular encrypted password; the userPassword attribute is a multi-value attribute. Now if you use ldapsearch or anything similar, it will try to negotiate GSSAPI authentication as the SASL mechanism. If it doesn't do so, you can force it by adding -Y GSSAPI to the command line.

HTTP
  1. Installation
  2. You need the libapache-mod-auth-kerb or libapache2-mod-auth-kerb modules on the server. For the client, you need a browser which has SPNEGO support; Konqueror and Firefox are two examples of browsers that do.

  3. Service principal.
  4. The prefix here should be HTTP/. That's right, in upper case, contrary to previous examples where this wasn't the case.

    HTTP is also different in that apache usually isn't running as root. This is a good thing; however, it does mean that the kerberos authentication module is unable to read /etc/krb5.keytab. You'll have to write the service principal to a different keytab for apache; I've used the -k option to the ktadd command in kadmin to specify the keytab as /etc/apache2/keytab; I'll assume you do the same.

  5. Configuration
  6. Something like this, on the server:

    <Location /some/URL>
    	AuthType Kerberos
    	KrbMethodNegotiate on
    	Require valid-user
    	Krb5Keytab /etc/apache2/keytab
    </Location>
    

    This will enable SPNEGO authentication; and if SPNEGO authentication fails for some reason (for example, because the used browser doesn't support SPNEGO, or because the user isn't logged in to Kerberos), it will fall back to Basic Authentication.

    While the latter is usually a good idea, it's less of a good idea if you're not using SSL, since then your password would be sent over the wire in cleartext. Luckily, the basic authentication can be switched off, by using KrbMethodK5Passwd off. If you go to my webserver logs, you'll see that you'll get a 401 right away, while the HTTPS version of the same allows you to try to log in by using basic authentication.

    On the client side, if you're using Firefox, you need to go to about:config, and set the option network.negotiate-auth.trusted-uris to a string that will identify the servers that may do SPNEGO authentication in your realm. In my case, I've set it to grep.be. For konqueror, doing something similar is not required—it'll do SPNEGO authentication out of the box.

So, that's what I've got set up on my network currently. Next on the list: NFS4 kerberos auth (requires updated nfs utilities, which aren't in Debian yet because of issues with NFS2, IIRC), PostgreSQL (it does seem to support it), and finding out if or how I can create principals can't be used for one authentication scheme or the other.

Phew, that was a long post. I'll stop now.