Using Kerberos 5 for Single Sign-On Authentication

Vincent Danen

December 10, 2012

Using Kerberos 5 for Single Sign-On Authentication

The purpose of this article is to detail the configuration of a Kerberos realm for single sign-on authentication. In particular, the document will cover installation and configuration on Red Hat Enterprise Linux 5.3, however it should be relevant enough for any recent Linux distribution or UNIX variant, provided they're using a recent enough version of Kerberos (this revision refers to version 1.6.1). Although the document deals with Red Hat Enterprise Linux specifically, it largely does so for the server-side (i.e.. the KDC, etc.) and will cover general Linux, Windows, and OS X Kerberos client configuration.

Kerberos is a program that authenticates workstations against a server. It was developed at MIT and is named after the three-headed watchdog from Greek mythology. This watchdog guarded the entrance to Hades, or the underworld, and was a fearsome beast indeed. Kerberos is aptly named.

Using Kerberos, a client (which is generally a user or host), sends a request for a ticket to the Kerberos server, or Key Distribution Center (KDC). The KDC creates a Ticket-Granting Ticket (TGT) for the client and encrypts is using the client's password as the key. It then sends the encrypted ticket back to the client. At this point, the client attempts to decrypt the TGT using its password. If the client successfully decrypts the TGT (which means it provided the correct password), it keeps the decrypted TGT as proof of it's identity.

TGT's are not indefinite; they expire at a specified time. However, having the TGT allows the client to obtain additional tickets, which give permission to access specific services. These additional tickets are transparent to the users and require no additional work on their behalf.

Kerberos negotiates the communication between any two points on the internet or an intranet. It can also encrypt communication between these two points. Because of this, it provides a layer of security that is independent of either side of any firewall.

Sounds a little daunting, doesn't it? Well, it doesn't have to be. Kerberos was designed to be (relatively) easy to use. Most of the commands it provides are nearly identical to the Linux network programs you already use. It is a single sign-on system, which means that you only need to type your password once per session. Everything else is transparent. After you have entered your password, Kerberos handles all of the authentication and encryption itself.

Kerberos can be installed by downloading the source and compiling it from the MIT website web.mit.edu/kerberos/www/ or by installing it via your Linux vendor; most Linux distributions come with Kerberos pre-packaged already. On RHEL5, to install the server components of Kerberos, execute:

# yum install krb5-server

This will install the Kerberos client and server components. More specifically, the following packages will be installed (the same is true for Mandriva; other distributions may have slightly differing package names):

  • krb5-libs (possibly libkrb5x depending on the distribution)
  • krb5-workstation
  • krb5-server

This is all you need to get started on RHEL5. Other distributions may have separate packages for the kerberized telnet and ftp client/servers, so you may need to install additional packages for that (i.e. on Mandriva you would want telnet-server-krb5 and telnet-client-krb5). You will want to install the telnet server/client to test the setup.

Configuring the Kerberos Server

Once Kerberos is installed on one or more machines (we'll get to the non-Linux clients shortly), it is time to configure it. For the purpose of this document we will assume that you are using Kerberos within your own network and that it is installed on two separate computers; one to be a client, the other to be the KDC server.

The first step is to setup the KDC, or Key Distribution Center. The KDC will issue Kerberos tickets. You can optionally have more than one KDC; each KDC containing a copy of the Kerberos database. There is one master KDC that holds the master copy of the database, and that data is then propagated to the slave KDCs at regular intervals. All changes to the database must be made on the master KDC, as the master is the only KDC that allows database administration. The slave KDCs can provide ticket-granting services, which allows clients to obtain tickets when and if the master KDC is unavailable. You really only need to setup slave KDCs if you want a little more redundancy on your network and it provides a good fail-safe should anything go wrong with the master KDC (i.e. it will still permit users to login, etc.). For the time being, we'll assume you are not setting up any slave KDCs; we'll get to that later.

On the system that will be the master KDC, you need to edit the configuration files, specifically /etc/krb5.conf and /etc/kerberos/krb5kdc/kdc.conf. By default, Kerberos itself (and thus many Linux distributions and UNIX variants) will use /var/kerberos/ rather than /etc/kerberos/; some distributions such as Mandriva use the latter because configuration files really don't belong in /var/.

The /etc/krb5.conf file will look similar to this:

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = LINSEC.CA
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 forwardable = yes

[realms]
 LINSEC.CA = {
  kdc = kerberos.linsec.ca
  admin_server = kerberos.linsec.ca
  default_domain = linsec.ca
 }

[domain_realm]
 .linsec.ca = LINSEC.CA
 linsec.ca = LINSEC.CA

[appdefaults]
 pam = {
   debug = false
   ticket_lifetime = 36000
   renew_lifetime = 36000
   forwardable = true
   krb4_convert = false
 }

This basically sets up a few rules for your Kerberos realm. The [libdefaults] section deals with the defaults on ticket generation. This indicates that tickets have a lifetime of 24000 seconds, or 400 minutes. It indicates the default realm, in this case LINSEC.CA (realms are always specified upper-case). You can think of a realm as your domain name within Kerberos. Then it specifies some ticket encryption types.

The [realms] section defines your realm. Here we define the realm LINSEC.CA and list our KDCs (in this case kerberos.linsec.ca). We also define the master (admin) server, which is also kerberos.linsec.ca. We specify the default domain, which is linsec.ca. The next section, [domain_realm], merely specifies that all systems matching the domain linsec.ca belong to the LINSEC.CA realm.

The next sections deal with pointing out the KDC configuration file and is only needed on the KDCs themselves. The next two sections deal with login settings; the first with PAM settings (if you use pam_krb5), and the final section ([login]) deals with Kerberos IV compatibility which we are turning off (Kerberos IV should not be used.. period).

The next configuration file to edit on the KDC is /var/kerberos/krb5kdc/kdc.conf, which was specified in the [kdc] section with the profile keyword in krb5.conf. The file should have contents similar to the following:

kdcdefaults]
 v4_mode = nopreauth
 kdc_tcp_ports = 88

[realms]
 LINSEC.CA = {
  #master_key_type = des3-hmac-sha1
  acl_file = /var/kerberos/krb5kdc/kadm5.acl
  dict_file = /usr/share/dict/words
  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
  supported_enctypes = des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal des-cbc-crc:v4 des-cbc-crc:afs3
 }

The [kdcdefaults] section defines some defaults for the KDC and is fairly self-explanatory. The kdc_ports keyword defines the port that the KDC listens to which, by default, is port 88. The rest are locations of various files required by the KDC.

The [realms] section specifies more detailed information about the realm that was previously defined, LINSEC.CA. This specifies where the database is kept, the ACL (Access Control List) file, the keytab file (more on this later), and various other options dealing with supported encryption types, listening ports, etc. More information is available on this configuration file, and the krb5.conf configuration file by viewing the manpages (kdc.conf.5 and krb5.conf.5 respectively).

Use modprinc to modify defaults

If you want to change the behaviour of the realm, such as renewable tickets or ticket lifetime, use kadmin to change principle options. Use getprinc to get the settings for the realm's TGT:

kadmin.local:  getprinc krbtgt/LINSEC.CA
Principal: krbtgt/LINSEC.CA@LINSEC.CA
Expiration date: [never]
Last password change: [never]
Password expiration date: [none]
Maximum ticket life: 1 day 00:00:00
Maximum renewable life: 0 days 00:00:00
Last modified: Wed Jun 17 09:25:46 MDT 2009 (db_creation@LINSEC.CA)
Last successful authentication: [never]
Last failed authentication: [never]
Failed password attempts: 0
Number of keys: 5
Key: vno 1, Triple DES cbc mode with HMAC/sha1, no salt
Key: vno 1, ArcFour with HMAC/md5, no salt
Key: vno 1, DES with HMAC/sha1, no salt
Key: vno 1, DES cbc mode with RSA-MD5, no salt
Key: vno 1, DES cbc mode with CRC-32, no salt
Attributes:
Policy: [none]

You can now change these settings use modprinc:

kadmin.local:  modprinc -maxlife 2days -maxrenewlife 14days +allow_renewable krbtgt/LINSEC.CA
Principal "krbtgt/LINSEC.CA@LINSEC.CA" modified.
kadmin.local:  getprinc krbtgt/LINSEC.CA
Principal: krbtgt/LINSEC.CA@LINSEC.CA
Expiration date: [never]
Last password change: [never]
Password expiration date: [none]
Maximum ticket life: 2 days 00:00:00
Maximum renewable life: 14 days 00:00:00
Last modified: Wed Oct 21 13:08:58 MDT 2009 (root/admin@LINSEC.CA)
Last successful authentication: [never]
Last failed authentication: [never]
Failed password attempts: 0
Number of keys: 5
Key: vno 1, Triple DES cbc mode with HMAC/sha1, no salt
Key: vno 1, ArcFour with HMAC/md5, no salt
Key: vno 1, DES with HMAC/sha1, no salt
Key: vno 1, DES cbc mode with RSA-MD5, no salt
Key: vno 1, DES cbc mode with CRC-32, no salt
Attributes:
Policy: [none]

Here we used modprinc -maxlife 2days -maxrenewlife 14days +allow_renewable krbtgt/LINSEC.CA to change the Kerberos realm LINSEC.CA's krbtgt principle to allow for 2 day tickets with a maximum renewable lifetime of 14 days, and to allow renewable tickets. You may also have to use a similar command for any users that need the new settings; change krbtgt/LINSEC.CA to user@LINSEC.CA in that case.

(I only mention this here as, from what my testing has shown, setting non-default renewable/initial ticket lifetimes in kdc.conf don't seem to actually work when the client kinit's).

Creating the Kerberos Database

The next step is to create the Kerberos database on the master KDC. Using the kdb5_util program on the master KDC, we need to create the database and a stash file. The stash file is a local copy of the master key that resides in encrypted form on the KDC's hard drive. The stash file is used to authenticate the KDC to itself automatically before starting the Kerberos daemons and as a result is a very important file that can be a very large security hole if not secured correctly. This file should exist only on a local hard drive, should have mode 0600 permissions, and should be owned by root. Essentially, no one other than root should have any kind of access to this file. Finally, the stash file should not be part of any backup routine unless the backups are physically secured as well. It is for this reason that most people chose and advise that the master KDC should be it's own system without any services other than running the KDC, that it should be physically secure, and disallow any interaction other than, perhaps, ssh access.

As the administrator, kdb5_util should exist in your path already (typically being installed /usr/kerberos/sbin/), however if you installed Kerberos from source you may need to add /usr/kerberos/sbin and /usr/kerberos/bin to your PATH.

# kdb5_util create -r LINSEC.CA -s
Loading random data
Initializing database '/etc/kerberos/krb5kdc/principal' for realm 'LINSEC.CA',
master key name 'K/M@LINSEC.CA'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key:
Re-enter KDC database master key to verify:

You will then be asked to provide the KDC with a database master key. This key can be any string and should be as difficult to guess as possible (like any other good password). Once this is done, you will have a number of new files in /var/kerberos/krb5kdc/, specifically the principal, principal.kadm5, principal.kadm5.lock, principal.ok, and .k5.LINSEC.CA files (the latter's file name is based on the kerberos realm name). If you do not want the stash file created, run kdb5_util without the -s command switch, and remove the key_stash_file keyword from the kdc.conf file. If you do this, however, you will be required to enter the database master key (password) every time you start the Kerberos daemons. Great for security, but of little practical use and a huge nuisance if the lights go out in the middle of the night and you need to rush into the office to bring the KDC back up.

Kerberos Principals and Instances

Before moving on to creating the ACLs, you need to understand what a Kerberos principal is as everything we will do after this point deals with principals and instances.

Kerberos uses the term "principals" to identify users or hosts so that Kerberos can properly assign tickets. A principal is typically divided into three parts: The primary, the instance, and the realm. The format for a Kerberos principal is primary/instance@REALM. You can think of principals as advanced user names for your Kerberos realm.

The primary is the first part of the principal. In the case of a user, it is the same as the user's username. In the case of a host, the primary is the word host.

The "instance" is an optional string that qualifies the primary. The instance is separated from the primary by the slash (/) character. In the case of a user, the instance is usually non-existent, but it may exist if the user has an additional principal. For instance, you may have a user with one principal of their username which is used for every day operations, and another principal with an instance of "admin" which may be used to administrate a database. For example, the principal joe@LINSEC.CA is very different from joe/admin@LINSEC.CA. Each has a separate password and separate permissions. In the case of a host, the instance is the fully qualified domain name (FQDN) of the host, for example kerberos.linsec.ca.

Finally, the realm is the defined Kerberos realm. For the purposes of this document, the realm is LINSEC.CA. Kerberos realms are typically the network's domain name in upper-case letters.

Two example principals are:

root/admin@LINSEC.CA
host/kerberos.linsec.ca@LINSEC.CA

The Access Control List

The next step is to create an Access Control List (ACL) file and put the Kerberos principal of at least one of the administrators in it. The file we are going to create is /var/kerberos/krb5kdc/kadm5.acl, which is specified as such in the kdc.conf file. The syntax for the ACL file is:

Kerberos principal  permissions     optional_target_principal

Kerberos principals (which include the principal and optional target principal) can contain the * wildcard, so you can define an administrator with full permissions. Insert the following into your kadm5.acl file (on Annvix and Mandriva system, this is already pre-configured for the default "out-of-the-box" realm so all you should need to change is the realm name):

*/admin@LINSEC.CA *

To give another quick example, suppose you wanted a principal called fred@LINSEC.CA to be able to add, list, and inquire about any principals with the instance "root". You would add the following to kadm5.acl:

fred@LINSEC.CA      ali     */root@LINSEC.CA

There are a number of different ACL's you can define, and in larger organizations, it makes sense to be able to delegate administrative privilege. Perhaps you want a user to be able to view the principals without changing them, or perhaps you want one user able to administrate all non-admin instance accounts. Understanding the ACLs is key to manipulating user access to the Kerberos database. The following ACLs can be used to specify strict access to the database:

ACL Description
a allows the addition of principals or policies in the database
A prohibits the addition of principals or policies
d allows the deletion of principals or policies
D prohibits the deletion of principals or policies
m allows the modification of principals or policies
M prohibits the modification of principals or policies
c allows the changing of passwords for principals
C prohibits the changing of passwords for principals
i allows inquiries to the database
I prohibits inquiries
l allows the listing of principals and policies
L prohibits the listing of principals and policies
* all privileges (admcil)
x all privileges (admcil)

By making good use of ACLs and principals, you can allow some people to manage certain groups of users. For instance, if you were the head administrator of the network and you used the principal fredadmin you would give yourself access to all aspects of the database using:

fredadmin@LINSEC.CA *

Now suppose you had a principal, cathy@LINSEC.CA who acts as an administrator when Fred is away. Fred trusts Cathy to some degree, so he gives her access to change principals and policies, but doesn't want her to change passwords for principals. Because he also doesn't want Cathy using her cathy@LINSEC.CA principal for this, he creates a new principal for her called cathy/admin@LINSEC.CA. To allow Cathy to do what she may need to do in his absence, Fred adds the following line to the kadm5.acl file:

cathy/admin@LINSEC.CA admilC

Cathy has been given an ACL of "admilC", but Fred could have just as easily written it "admil" and just omitted the "c" ACL. Either ACL acts the same, but when you start building ACLs, Cathy might be able to change passwords for one group of users but not for another. In that case, Cathy would be explicitly denied (with the "C" ACL) the ability to change passwords for the second group while given it for the first. As a result, it's usually best to write the ACLs clearly and specify each ACL, whether it is enabled or not. For example:

cathy/admin@LINSEC.CA admilc */sales@LINSEC.CA
cathy/admin@LINSEC.CA admilC */admin@LINSEC.CA

Here Cathy can change passwords for users with the "sales" instance, but not for users with the "admin" instance.

Now that you understand have possibly defined a few ACLs, the next step is to add an administrative principal and some policies to the Kerberos database. This must also be done on the master KDC. The administrative principal that you add should be the one listed in the kadm5.acl file above, which in the initial example was */admin@LINSEC.CA. To do this, the kadmin.local program is used:

# kadmin.local
Authenticating as principal root/admin@LINSEC.CA with password.
kadmin.local: addpol users
kadmin.local: addpol admin
kadmin.local: addpol hosts
kadmin.local: ank -policy users fred
Enter password for principal "fred@LINSEC.CA":
Re-enter password for principal "fred@LINSEC.CA":
Principal "fred@LINSEC.CA" created.
kadmin.local: ank -policy admin fred/admin
Enter password for principal "fred/admin@LINSEC.CA":
Re-enter password for principal "fred/admin@LINSEC.CA":
Principal "fred/admin@LINSEC.CA" created.
kadmin.local: ank -randkey -policy hosts host/kerberos.linsec.ca
Principal "host/kerberos.linsec.ca@LINSEC.CA" created.
kadmin.local: ktadd -k /etc/krb5.keytab host/kerberos.linsec.ca
Entry for principal host/kerberos.linsec.ca with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added
to keytab WRFILE:/etc/krb5.keytab.
Entry for principal host/kerberos.linsec.ca with kvno 3, encryption type DES cbc mode with CRC-32 added to
keytab WRFILE:/etc/krb5.keytab.
kadmin.local: ktadd -k /etc/kerberos/krb5kdc/kadm5.keytab kadmin/admin kadmin/changepw
kadmin.local: quit
Entry for principal kadmin/admin with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab
WRFILE:/etc/kerberos/krb5kdc/kadm5.keytab.
Entry for principal kadmin/admin with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab
WRFILE:/etc/kerberos/krb5kdc/kadm5.keytab.
Entry for principal kadmin/changepw with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab
WRFILE:/etc/kerberos/krb5kdc/kadm5.keytab.
Entry for principal kadmin/changepw with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab
WRFILE:/etc/kerberos/krb5kdc/kadm5.keytab.

Here we are doing a number of things to setup the database. The first step is to create policies for "users", "admin", and "hosts". While this isn't absolutely necessary, it's a good idea to get into the habit of using policies in case you want to use them later. Policies allow for a lot of fine-tuning of parameters and restrictions of accounts.

The ank command adds a new principal (you can also use addprinc). User principles require a password; you will have to assign the passwords when you create them. Host principles do not require passwords, so the -randkey option is used to generate a random key instead of a password. Hosts have credentials, just like users, but they cannot supply a password on their own, so the secret key for the host is stored in the /etc/krb5.keytab file with the first ktadd command.

Finally, the keytab for kadmind is also created with the ktadd command. This is the key that kadmind will use to decrypt the administrator's Kerberos tickets to determine whether or not access will be granted to the database. This keytab needs to be created with entries for the principles "kadmin/admin" and "kadmin/changepw". The -k parameter specifies the keytab file to write to and it must be the same as that specified in the kdc.conf file.

At this point you are ready to start the Kerberos daemons on the master KDC. Start the Kerberos services using:

# service krb5kdc start
# service kadmin start

If you built from source or don't have a system to manage the start and stop of the Kerberos daemons, you can use:

# /usr/kerberos/sbin/krb5kdc
# /usr/kerberos/sbin/kadmind

Of course, change the locations of the binaries to where they were installed; they may be in /usr/sbin/ instead. If started in this manner, the daemons will fork in the background and do their thing.

Testing the Install

For a basic setup, Kerberos is now up and running and ready to go. The time has come to test and make sure everything is configured properly. The first step is to use kinit to ensure the KDC can be contacted and you can properly provide your password and receive credentials.

$ kinit
Password for fred@LINSEC.CA:

Provide the password for Fred that you had previously defined when you added the principle to the database. When you have succeeded, use klist to examine your credentials:

$ klist
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: fred@LINSEC.CA

Valid starting     Expires            Service principal
07/15/05 11:39:07  07/15/05 21:39:07  krbtgt/LINSEC.CA@LINSEC.CA
        renew until 07/16/05 11:39:07


Kerberos 4 ticket cache: /tmp/tkt1001
klist: You have no tickets cached

The next step is to test the administrative system, using the separate administrative principle you previously defined:

$ /usr/sbin/kadmin
Authenticating as principal fred/admin with password.
Password for fred/admin@LINSEC.CA:
kadmin:  listprincs
K/M@LINSEC.CA
host/kerberos.linsec.ca@LINSEC.CA
kadmin/admin@LINSEC.CA
kadmin/changepw@LINSEC.CA
kadmin/history@LINSEC.CA
krbtgt/LINSEC.CA@LINSEC.CA
fred/admin@LINSEC.CA
fred@LINSEC.CA
kadmin: quit

The next step is to make services work properly. Kerberos comes with Kerberized-telnet client and server, on RHEL5 they are included in the krb5-workstation package. Other distributions may or may not ship the Kerberos versions of telnet and telnetd; if they don't you can build and install them from the Kerberos source but it is most likely that if a distribution ships Kerberos, they will include the Kerberized telnet as well either as a replacement for traditional telnet or in addition to. To start the telnetd on RHEL5 you must edit /etc/xinetd.d/ekrb5-telnet and set "disable = no". This will let xinetd know to start that service when it starts. To start xinetd, use:

Annvix use:

# service xinetd start

or use "restart" if xinetd was already running. Once telnetd is running, try to telnet to the localhost on the KDC master system. Note that you cannot use telnet localhost because "localhost" is not defined anywhere in Kerberos (nor would you want it to be). Instead, telnet to the FQDN domain name and include the username on the commandline:

$ telnet -l fred -x kerberos.linsec.ca
Trying 192.168.10.100...
Connected to kerberos.linsec.ca (192.168.10.100).
Escape character is '^]'.
Waiting for encryption to be negotiated...
[ Kerberos V5 accepts you as ``fred@LINSEC.CA'' ]
done.
Last login: Sat Jul 16 09:39:11 from foofoo.linsec.ca

[fred@kerberos ~]$ exit
Connection closed by foreign host.
$ klist
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: fred@LINSEC.CA

Valid starting     Expires            Service principal
07/16/05 09:39:13  07/16/05 19:39:13  krbtgt/LINSEC.CA@LINSEC.CA
        renew until 07/17/05 09:39:13
07/16/05 09:45:06  07/16/05 19:39:13  host/kerberos.linsec.ca@LINSEC.CA
        renew until 07/17/05 09:39:13


Kerberos 4 ticket cache: /tmp/tkt1001
klist: You have no tickets cached

Although there was a lot here to demonstrate that telnetting with Kerberos works, there's actually a fair amount going on here that we'll explain. The first step is to telnet to the KDC using it's FQDN (kerberos.linsec.ca in this instance). We pass the username on the commandline so we don't get a login prompt, and we also pass -x in order to force encryption of the telnet session. As you can see, the first step is for encryption to be established before anything else happens. After this, you see a note from Kerberos saying it accepted the login as fred@LINSEC.CA, which is the Kerberos principal for user fred.

The connection is established and you're logged in. Exit the telnet session and issue the klist command and you will see that not only do you have a TGT ticket, but you also have a ticket for the host kerberos.linsec.ca. This ticket was granted when you successfully logged into the host.

If you were to run klist inside the telnet session, you would see you have no credentials; no tickets are assigned to you. In order to move past the system to use another Kerberos server, you would have to run kinit again. However, you can pass the -f command to telnet in order to forward your credentials to the remote host, which isn't done by default. For instance:

$ telnet -l fred -x kerberos.linsec.ca
Trying 192.168.10.100...
Connected to kerberos.linsec.ca (192.168.10.100).
Escape character is '^]'.
Waiting for encryption to be negotiated...
[ Kerberos V5 accepts you as ``fred@LINSEC.CA'' ]
done.
Last login: Sat Jul 16 09:45:06 from kerberos

[fred@kerberos ~]$ klist
klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_p7351)


Kerberos 4 ticket cache: /tmp/tkt1001
klist: You have no tickets cached

As you can see, you have no tickets cached on the telnet system. If you were to telnet with -f however, this changes:

$ telnet -l fred -x -f kerberos.linsec.ca
Trying 192.168.10.100...
Connected to kerberos.linsec.ca (192.168.10.100).
Escape character is '^]'.
Waiting for encryption to be negotiated...
[ Kerberos V5 accepts you as ``fred@LINSEC.CA'' ]
done.
Last login: Sat Jul 16 10:08:29 from kerberos

[fred@kerberos ~]$ klist
Ticket cache: FILE:/tmp/krb5cc_p7378
Default principal: vdanen@LINSEC.CA

Valid starting     Expires            Service principal
07/16/05 10:09:59  07/16/05 19:39:13  krbtgt/LINSEC.CA@LINSEC.CA
        renew until 07/17/05 09:39:13


Kerberos 4 ticket cache: /tmp/tkt1001
klist: You have no tickets cached

Here you see that your TGT has been forwarded so you obtain your credentials. The manpage for the Kerberized telnet contains more information on the various options you can pass to telnet.

Congratulations! Kerberos is setup and successfully configured! You can now use the Kerberized telnet and even the Kerberized FTP client and server that also come with Kerberos.

Setting up Client Realm Systems

Now that Kerberos is configured and setup on the KDC, you need to extend this to other systems. This is extremely easy to do. All that is needed is to ensure that Kerberos client software is installed on the other hosts by having krb5-workstation installed on them (I believe this may be a default in Red Hat Enterprise Linux 5). Once this is done, copy the /etc/krb5.conf file from the KDC to the client system. Now you can use kadmin from the client to administer the database.

Adding New Users and Hosts to the Database

Maintaining the Kerberos database is just as important as using it, so we'll figure out how to add more client systems to the realm and how to make those users and hosts known to Kerberos.

Once Kerberos is completely configured, you can use the kadmin program from any realm host to add a new user or host:

$ /usr/sbin/kadmin
Authenticating as principal fred/admin@LINSEC.CA with password.
Password for fred/admin@LINSEC.CA:
kadmin: ank -policy users joe
Enter password for principal "joe@LINSEC.CA":
Re-enter password for principal "joe@LINSEC.CA":
Principal "joe@LINSEC.CA" created.
kadmin: quit

By the same token, you can create an administrative principal for the same user by using ank again but give it the instance admin and the principal name joe/admin. You do not need to use kadmin.local as we did when initially setting up the database; kadmin.local is a bootstrapping program used only when the database hasn't been initially setup.

Likewise, you can setup new hosts in a similar fashion:

$ /usr/sbin/kadmin
Authenticating as principal fred/admin@LINSEC.CA with password.
Password for fred/admin@LINSEC.CA:
kadmin: ank -randkey -policy hosts host/foofoo.linsec.ca
kadmin: ktadd -k /etc/krb5.keytab host/foofoo.linsec.ca
kadmin: quit

These commands should be run on the host are you adding to the realm. In the above example, we would run kadmin on the host foofoo.linsec.ca. This is because the ktadd command creates the /etc/krb5.keytab file for the host foofoo.linsec.ca and it is only useful if this file exists on that particular host; it must belong to that hosts's keytab file.

Once the host is setup, you can test the setup in a similar manner we previously showed, using telnet or ssh, kinit and klist.

Setting up a Mac OS X Client (<= 10.6)

Configuring Mac OS X as a Kerberos client is a little more difficult than setting up a Linux client. As with the Linux client, you need a copy of the /etc/krb5.conf file from the Kerberos server. On OS X, however, the file must be copied to /Library/Preferences/edu.mit.Kerberos. For instance:

[domain_realm]
    .linsec.ca = "LINSEC.CA"
    linsec.ca = "LINSEC.CA"

[libdefaults]
    default_realm = "LINSEC.CA"

[realms]
    LINSEC.CA = {
        admin_server = kerberos.linsec.ca
        kdc = kerberos.linsec.ca
    }

[logging]
    kdc = FILE:/var/log/krb5kdc/kdc.log
    admin_server = FILE:/var/log/krb5kdc/kadmin.log

Once this file is created, you must change the /etc/authorization file. This will provide the SSO functionality we are looking for, provided the local user's username and password are identical to their Kerberos username and password (with the exception of the realm in the username). I.e. to authenticate joe@LINSEC.CA, the local user's name must be "joe".

In /etc/authorization, search for the string system.login.console you want to change the string "builtin:authenticate,privileged" to "builtin:krb5authnoverify,privileged", as shown below:

<array>
    <string>builtin:smartcard-sniffer,privileged</string>
    <string>loginwindow:login</string>
    <string>builtin:reset-password,privileged</string>
    <string>builtin:auto-login,privileged</string>
-->  <string>builtin:krb5authnoverify,privileged</string>  <--
    <string>loginwindow:success</string>
    <string>HomeDirMechanism:login,privileged</string>
    <string>HomeDirMechanism:status</string>
    <string>MCXMechanism:login</string>
    <string>loginwindow:done</string>

(emphasis shown for the line in question)

The above will work for Mac OS X 10.5 and 10.6. For 10.4, the string you want to change is "authinternal" instead of "builtin:authenticate", however the end result must look the same (in other words, on 10.4 the resulting line must still read "<string>builtin:krb5authnoverify,privileged</string>".

Once the above is done, reboot the system and when you login you will obtain a Kerberos ticket provided the local username/password match that in the Kerberos database.

Enabling auto-renewing Tickets

In Mac OS X 10.6, there is a Launch Agent called com.apple.Kerberos.renew.plist that is supposed to renew tickets automatically. Unfortunately, it doesn't work. This can be edited to use the documented kinit -R rather than the default kinit -B that it is using by editing /System/Library/LaunchAgents/com.apple.Kerberos.renew.plist as root (so sudo vim or something). In the file change <string>-B</string> to <string>-R</string> then save the file. You then need to unload and reload the file using launchctl:

$ launchctl unload /System/Library/LaunchAgents/com.apple.Kerberos.renew.plist
$ launchctl load /System/Library/LaunchAgents/com.apple.Kerberos.renew.plist

If you then look at the output of klist you will see that the ticket is being renewed (if you have a renewable ticket -- this will only work if you can obtain renewable tickets). Unfortunately, there doesn't seem to be a way that I have found to specify obtaining a renewable ticket at login, so you will need to open a terminal to kinit manually regardless of any changes to /etc/authorization. It seems that the ticket obtained by logging in is not renewable, so there is nothing to renew even with the above changes (but using kinit directly will obtain a renewable ticket).

For reference:

$ launchctl list com.apple.Kerberos.renew.plist
{
    "Label" = "com.apple.Kerberos.renew.plist";
    "LimitLoadToSessionType" = "Background";
    "OnDemand" = true;
    "LastExitStatus" = 0;
    "TimeOut" = 30;
    "ProgramArguments" = (
        "/usr/bin/kinit";
        "-R";
    );
};

Without the "-R" change (from "-B") noted earlier, the LastExitStatus noted in the output above will likely be 256. Likewise, the output from below will show an exit status of "1" (error) rather than "0" (success):

$ launchctl list|grep -i kerb
-   0   edu.mit.Kerberos.KerberosAgent
-   0   com.apple.Kerberos.renew.plist
263 -   edu.mit.Kerberos.CCacheServer
-   0   com.apple.KerberosHelper.LKDCHelper

The second column is the exit status.


Setting up a Mac OS X Client (10.7)

Mac OS X changed from using MIT Kerberos to using Heimdal, and how Kerberos is configured has changed quite a bit as well. This section illustrates the differences in setting up an OS X computer as a Kerberos client using Mac OS X 10.7 (Lion).

Typically, the /Library/Preferences/edu.mit.Kerberos settings will be similar, however you must make certain that none of the variables are enclosed in quotes. A working example will look like:

[domain_realm]
    .linsec.ca = LINSEC.CA
    linsec.ca = LINSEC.CA

[libdefaults]
    default_realm = LINSEC.CA
    allow_weak_crypto = yes
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 36000
    renewable = true

[realms]
    LINSEC.CA = {
        admin_server = kerberos.linsec.ca
        kdc = kerberos.linsec.ca
    default_domain = linsec.ca
    }

[logging]
    kdc = FILE:/var/log/krb5kdc/kdc.log
    admin_server = FILE:/var/log/krb5kdc/kadmin.log

The one thing to note is that you will almost definitely need to set "allow_weak_crypto = yes", unfortunately.

The next step is to edit /etc/pam.d/authorization. This is done instead of editing /etc/authorization as was done in the past. OS X now uses PAM to handle Kerberos authentication, and has the required pam_krb5 module already noted. You will, however, need to add the "default_principal" string to the pam_krb5.so line for auth. A working /etc/pam.d/authorization file follows:

# authorization: auth account
auth       optional       pam_krb5.so use_first_pass use_kcminit default_principal
auth       optional       pam_ntlm.so use_first_pass
auth       required       pam_opendirectory.so use_first_pass nullok
account    required       pam_opendirectory.so

Next, if you want to allow kerberized access to this system (i.e. for SSH logins), you will need to create the /etc/krb5.keytab file and edit /etc/sshd_config as noted elsewhere in this article.

The final step is to reboot the computer. When you next login, if you open terminal and type klist you should see that a ticket-granting ticket has been obtained.

Configuring OpenSSH to use Kerberos

OpenSSH 4.0 and higher provides support for GSSAPI (Generic Security Services Application Programming Interface) with allows for the use of Kerberos with SSH2 protocols. On Red Hat Enterprise Linux 5, OpenSSH is configured by default with the appropriate GSSAPI options. On other distributions, you may need to edit sshd_config on the server and comment out all of the Kerberos* options and enable some GSSAPI options. The appropriate sections of sshd_config would look like:

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes

Essentially, you can leave the Kerberos options commented out, but enable the GSSAPIAuthentication and GSSAPICleanupCredentials options. Restart sshd once the file is saved.

On the client system (in this case, the same system) you can either modify ~/.ssh/options to specify the exact hosts to use Kerberos (GSSAPI) authentication with, or you can modify the system-wide /etc/ssh/ssh_config file. Either way, the options you want to enable are:

GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes

The GSSAPIDelegateCredentials option isn't necessary for this to work, but what it does is allow you to forward your Kerberos credentials to the server. By default this is "no", and you can leave it as such if you like. The real magic is to set GSSAPIAuthentication to yes. This tells the client to allow GSSAPI user authentication. The OpenSSH default is set to no, so even if the server allows GSSAPI authentication, the client will not try to negotiate it if this option is not enabled. GSSAPIDelegateCredentials is not enabled by default on Red Hat Enterprise Linux 5.

Once both the server and client(s) allow GSSAPI authentication, you can now ssh to your server using your Kerberos credentials. However, if for some reason you cannot authenticate to the KDC (i.e. it is down), you will be locked out unless you permit password (keyboard-based) authentication or public key authentication. At a minimum you should use public key authentication on the KDC itself (unless you have physical access to it) in order to deal with that machine if the KDC ever goes down; if you don't you will be effectively locked out. Using GSSAPI and public key authentication together makes the most sense; you can use one and fallback to the other if required. Either way, you'll still be able to log in. On a personal aside, I would completely disable password-based authentication entirely and rely strictly on public key and GSSAPI authentication, or public key authentication alone.

Configuring a Subversion client to use Kerberos

Subversion understands GSSAPI authentication without any work, provided the server is using HTTPS. If you are connecting to an HTTP server (unencrypted), the svn program will instead prompt for a password. To correct this, edit ~/.subversion/servers and edit the [global] section so it looks like this:

[global]
http-auth-types = Negotiate

This will allow svn to use GSSAPI credentials with a subversion server that understands them.

(Supposedly it is possible to have svnserve work with GSSAPI using SASL, but I have not tried this as I prefer using apache.)

Configure Firefox to use Kerberos

By default, Firefox does not enable the ability to view Kerberos-protected sites. To change this, you need to type about:config in the address field. Once there, in the filter field, type network.negotiate and look for the network.negotiate-auth.trusted-uris option. Double-click it and type in the kerberos domain name in the pop up box. At this point, you can use kerberos credentials on any site within that domain.

Changing Kerberos Passwords

You can change your Kerberos password on any system that is a part of the Kerberos realm (in other words, any system you can kinit from). Use the kpasswd command to change your Kerberos password. You will be prompted for your existing password, and then will have to enter your new password twice. If you need to change the password for another principal, you can specify it as an option:

$ kpasswd joe/admin

This will change the Kerberos password for the principal joe/admin.

Revision History

  • 01/09/2012: add section on setting OS X Lion clients, based on my blog post
  • 02/25/2011: add section on changing Kerberos passwords
  • 11/02/2009: add LaunchAgent and renewable ticket notes for OS X clients (refer to blog comments for more details
  • 10/21/2009: add some info re using modprinc to change ticket/renewable lifetimes
  • 10/19/2009: add info on configuring Firefox
  • 9/7/2009: add info on configuring OS X clients
  • 7/16/2009: add info on svn clients
  • 6/17/2009: revise to remove Annvix references and update to be relevant for CentOS/RHEL 5.3
  • 12/25/2007: initial article