MIT Kerberos installation on Debian

Posted by docelic on Wed 5 Dec 2007 at 10:15

The purpose of this Guide is to give you a straight-forward, Debian-friendly way of installing and configuring Kerberos. We will go through introduction to Kerberos, installation, configuration, PAM config and setting up of encrypted telnet/ftp session to the server. We will show how to use Kerberos logins as a replacement for SSH keys, and how to use standard (optionally encrypted) telnet/ftp connections instead of SSH.


The newest version of this article can be found at http://techpubs.spinlocksolutions.com/dklar/kerberos.html.

Table of Contents

Introduction
Conventions
Kerberos
Installation
Initial Test
Access Rights
Kadmin Test
Adding a User
Obtaining a Kerberos Ticket
Installing Kerberized Services
Connecting to a Kerberized Service
Troubleshooting the Connection
PAM Configuration

Introduction

Kerberos is a service that has traditionally been captivating system administrators' and advanced users' interest, but its (seemingly or not) high entry barrier and infrastructure requirements prevented many of them from ever using it.

A lot of theory and introductory material has been written on it. We will present a summary here that will be enough for you to put everything in context and form a mental map of the whole problem domain.

Kerberos is a sophisticated authentication technology for securing access to network applications. Passwords are never transmitted over the network. Instead, cryptographic tokens (called "tickets") are used to provide the identity of the user to services. These tickets are acquired by users from a security server, call a Key Distribution Centre (KDC). Furthermore, Kerberos requires mutual authentication of both parties (user and server); this prevents a malicious service from masquerading as an authorised service and stealing information from the user.

Kerberos is a Single Sign-On (SSO) technology. This means that the user only has to authenticate once against the KDC to acquire as many tickets as required by the user in the course of his session. Kerberos is application agnostic. Kerberos is not tied to any particular application, and has been implemented for all common network services (ssh, HTTP, FTP, SMTP, IMAP, etc).

In most simple scenarios, Kerberos can be used as a functional equivalent of SSH keys that you use for passwordless login. Also, it is geared towards infrastructure-based Unix/Linux setups (as opposed to ad-hoc installations), and that's where its true effectiveness lies.

The "glue layer":

Conventions

It's quite disappointing when you are not able to follow the instructions found in the documentation. So let's agree on a few points:

Kerberos

Well. Here we come to MIT Kerberos.

Installation

sudo apt-get install krb5-{admin-server,kdc}

During installation, Kerberos' Debconf interface will ask you a few questions. Here's the list of questions and realistic answers to them:

Default Kerberos version 5 realm? SPINLOCK.HR
# (Your Internet domain name in uppercase - a standard for naming Kerberos realms)

Kerberos4 compatibility mode to use? none
# (No krb4 compatibility needed in our setup)

What are the Kerberos servers for your realm? krb.spinlock.hr
# (Make sure your DNS resolves krb.spinlock.hr to
# the NETWORK IP of the server, NOT 127.0.0.1!). If you do not use
# the DNS server, adjust an entry in /etc/hosts like this:
#
# 127.0.0.1 localhost.localdomain localhost
# 192.168.7.12 monarch.spinlock.hr monarch krb.spinlock.hr What is the administrative server for your realm? krb.spinlock.hr # (Make sure your DNS resolves krb.spinlock.hr to
# the NETWORK IP of the server, NOT 127.0.0.1!). If not, same hint as above.

Once we do the above, both the admin-server (kadmind) and the KDC will try to start. Kadmind will fail since we haven't created any realms yet.

To actually create the realm, invoke krb5_newrealm. The command will ask about the master password (write it down since it's very important but also very rarely used) and create the realm using the name as defined in the Debconf step (SPINLOCK.HR).

We now need to tune the Kerberos config file, /etc/krb5.conf. It is split into sections. Look for [realms] and notice the listed famous realms in there that don't belong to your configuration (ATHENA.MIT.EDU, GNU.ORG, ANDREW.CMU.EDU etc.). You can leave them there and at the end add:

SPINLOCK.HR = {
kdc = krb
admin_server = krb
default_domain = spinlock.hr
}

Then search further below for [domain_realm] and add your realm definitions:
.spinlock.hr = SPINLOCK.HR
spinlock.hr = SPINLOCK.HR

Then, at the end of the file add this logging section:

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

(Kerberos logs to syslog by default, but I like separate files, as you see. Run sudo mkdir /var/log/kerberos to create the log directory.)

Run sudo invoke-rc.d krb5-admin-server restart.
Run sudo invoke-rc.d krb5-kdc restart.

Re-start the log monitoring command (see the section called "Conventions") so that the tail program can pick up new log files from the kerberos/ directory.

Initial Test

It's already the time to test the installation. We assume that both the admin server and the KDC can be restarted with no errors. (Again, you are watching the log files, right?).

To just quickly test the installation, we will use the kadmin.local database administration program.

Start kadmin.local, then type listprincs. That command should print out the list of principals (user, host and/or service accounts). The whole session should look like this:

sudo kadmin.local
Authenticating as principal root/admin@SPINLOCK.HR with password.

kadmin.local:  listprincs

K/M@SPINLOCK.HR
kadmin/admin@SPINLOCK.HR
kadmin/changepw@SPINLOCK.HR
kadmin/history@SPINLOCK.HR
krbtgt/SPINLOCK.HR@SPINLOCK.HR

kadmin.local:  quit

You may have a few questions now. First of all, how did kadmin.local authenticate as principal root/admin without asking for a password or anything? And second, what's the difference between kadmin and kadmin.local?

There's one common answer to both questions. kadmin.local is a command intended to be ran only on the administration server. It does not connect using the Kerberos protocol; instead, it directly opens the Kerberos database on the local filesystem and authenticates as any user it desires. This can only work for the system administrator who has sufficient privileges to open the database files on the local Unix filesystem, as one would guess. kadmin is the same thing, but it works over the network. It means it uses the Kerberos protocol to connect, and it requires the account password as part of the routine.

Access Rights

Take a look at the /etc/krb5kdc/kadm5.acl file. It defines user access rights in Kerberos. For users with no special privileges, no action is required. To admin users, however, we want to grant all privileges. To do this, make sure the following line is present in the file and enabled (that is, without the comment '#' character at the beginning):

*/admin *

Also, a word or two on principal names is in order here. In the test step above, you might have noticed principal names like kadmin/admin@SPINLOCK.HR. The general naming syntax for principals is SPEC@REALM, where SPEC, by convention, consists of components separated by "/". In the case of user names, the first component identifies the user name, and the second component, when present, identifies user role. This is a nice separation of privileges; System administrators will authenticate to Kerberos like any other user during off-hours (for example, as NAME). Only when the duty calls will they authenticate as NAME/admin and obtain administrative privileges on the Kerberos database.

Knowing all this, let's create principal root/admin.

sudo kadmin.local
Authenticating as principal root/admin@SPINLOCK.HR with password.

kadmin.local:  addprinc root/admin

WARNING: no policy specified for root/admin@SPINLOCK.HR; defaulting to no policy
Enter password for principal "root/admin@SPINLOCK.HR": PASSWORD
Re-enter password for principal "root/admin@SPINLOCK.HR": PASSWORD
Principal "root/admin@SPINLOCK.HR" created.

kadmin.local:  quit

Kadmin Test

Now that we've created the root/admin user, double-check that all the permissions are granted to admin roles in the /etc/krb5kdc/kadm5.acl (instructions given in the previous section); then restart the admin server (sudo invoke-rc.d krb5-admin-server restart).

At this point, we should be able to use the kadmin just as we used kadmin.local. (With the exception, of course, that kadmin will prompt for a password to connect using the Kerberos protocol, as already explained).

sudo kadmin
Authenticating as principal root/admin@SPINLOCK.HR with password.

Password for root/admin@SPINLOCK.HR: PASSWORD

kadmin:  listprincs

K/M@SPINLOCK.HR
kadmin/admin@SPINLOCK.HR
kadmin/changepw@SPINLOCK.HR
kadmin/history@SPINLOCK.HR
krbtgt/SPINLOCK.HR@SPINLOCK.HR
root/admin@SPINLOCK.HR

kadmin:  quit

Adding a User

Assuming that you've got everything right up to this step, let's now add a new user account (a "principal") to Kerberos. We've already done this above for root/admin, but let's now to it for your regular, unprivileged account.

NOTE: Before creating the Kerberos principal, make sure your intended user already exists as a regular system user (in /etc/passwd most likely). Why it has to be an existing user will be explained later.

Supposing your account name is "mirko", do the following:

sudo kadmin.local
Authenticating as principal root/admin@SPINLOCK.HR with password.

kadmin:  addprinc mirko

WARNING: no policy specified for mirko@SPINLOCK.HR; defaulting to no policy
Enter password for principal "mirko@SPINLOCK.HR": PASSWORD
Re-enter password for principal "mirko@SPINLOCK.HR": PASSWORD
Principal "mirko@SPINLOCK.HR" created.
kadmin:  quit

(It would be wise to pick a password that is different from your system password. That way, in the Kerberos test phase, you will easily be able to see whether the password was authenticated against the normal Unix passwd file, or against the Kerberos database.)

Obtaining a Kerberos Ticket

Now, you remember we said Kerberos would issue us a ticket once we authenticate. Let's try running klist to see the list of tickets:

klist -5

klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_1000)

Fine. This is okay. There are no tickets and there's no credentials cache created, since we didn't authenticate yet :) So let's run kinit to do so:

kinit

Password for mirko@SPINLOCK.HR: PASSWORD

Well, well! We should have a ticket now!

klist -5

Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: mirko@SPINLOCK.HR

Valid starting     Expires            Service principal
11/22/06 22:30:36  11/23/06 08:30:33  krbtgt/SPINLOCK.HR@SPINLOCK.HR

If you remember the story from the beginning, you will recognize "krbtgt" to be the Ticket-granting Ticket.

This is enough for now. Run kdestroy to terminate the ticket.

Installing Kerberized Services

Once you have Kerberos working, you need to Kerberize the services to which you want to authenticate using Kerberos.

It is important to realize that each service may support Kerberos (or any other functionality, for that matter) in two ways:

In your Debian GNU repository, you will see packages like krb-ftpd, krb5-telnetd and krb5-rsh-server. Those are replacement services for ftp, telnet and rsh with direct Kerberos support (they also offer encryption support, replacing ssh in every way). When using Kerberized ftp, telnet or rsh, I like to install those packages with direct Kerberos support. Other services, less important or without explicit Kerberos support, can be configured through PAM and will work equally fine.

For the moment, let's just install the krb5-rsh-server. Care must also be taken to actually enable the rsh server; it is started from Inetd (see /etc/inetd.conf), so Inetd must be running as well.

sudo apt-get install krb5-rsh-server
sudo update-rc.d openbsd-inetd defaults
sudo invoke-rc.d openbsd-inetd restart

Connecting to a Kerberized Service

Now that we have a Kerberos principal, it would be a real waste if we didn't do anything with it :)

Let's install Kerberized versions of the client programs:

sudo apt-get install krb5-clients

Create yourself a ticket again:

kinit

Password for mirko@SPINLOCK.HR: PASSWORD

There's just one boulder on our way now -- namely, testing the connection on the krb5-rsh-server service we've installed!

It is vital to understand that your first attempt to connect to a Kerberized service WILL LIKELY NOT SUCCEED (but we will not be far away from it succeeding). The example below will show a valid connection, even though you will most probably encounter an error. In the next section, there is a good list of exact errors and their solutions. Each time you get an error in this test step, try to match it with errors listed in the section called "Troubleshooting the Connection" and fix accordingly, moving closer to a working setup.

In fact, the "errors" you'll get aren't exactly errors. They're normal consequences of the fact that we used the "keep adjusting until it works" approach instead of a "do this, do that, and it'll work" method.

Again, remember, what follows is a transcript of a WORKING SYSTEM (you'll have to go through a few steps below to get it working for yourself):

krb5-rsh -x krb.spinlock.hr

This rlogin session is encrypting all data transmissions.
Last login: Mon Nov 27 16:49:49 from monarch
Linux monarch 2.4.27-2-686 #1 Mon May 16 17:03:22 JST 2005 i686 GNU/Linux

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.

logout
Connection closed.

Troubleshooting the Connection

Consult this list for solutions to the possible Kerberos connection problems.

When you get rsh login working, skip below to the section called "PAM Configuration".

Error: Connection Refused

krb5-rsh -PN krb.spinlock.hr


connect to address 192.168.7.12: Connection refused
Trying krb4 rlogin...
connect to address 192.168.7.12: Connection refused
trying normal rlogin (/usr/bin/netkit-rlogin)
exec: No such file or directory

Let's take a look at this. First of all, you can see that krb5-rsh has some fallbacks built-in. It first tries to connect using the Kerberos 5 protocol, then Kerberos 4, and then using the normal, non-kerberized rsh. We are only interested in the krb5 result. If any of the other two methods succeed (the krb4 or plain rsh, but they shouldn't!), it's still not what we want.

So where's the problem? Assuming that you did everything right (installed krb5-rsh-server and restarted inetd), the problem is very simple. Namely, by default, Kerberized servers in Debian do not accept unencrypted connections! So, on next attempt, add -x on the command line.

krb5-rsh -PN -x krb.spinlock.hr

Error: Server not found in Kerberos database

krb5-rsh -PN -x krb.spinlock.hr


error getting credentials: Server not found in Kerberos database

As you might know, both the users and the services they use must have an appropriate principal entry in the Kerberos database (we're authenticating both the service and the user who wishes to use it). While users are in form of NAME/ROLE (/role is optional), services are in form SERVICE-TYPE/HOST. So we need to add an entry for service "host" (common name for telnet-like services), on host monarch.spinlock.hr:

sudo kadmin.local
Authenticating as principal root/admin@SPINLOCK.HR with password.

kadmin.local:  addprinc -randkey host/monarch.spinlock.hr

WARNING: no policy specified for host/monarch.spinlock.hr@SPINLOCK.HR; defaulting to no policy
Principal "host/monarch.spinlock.hr@SPINLOCK.HR" created.

kadmin.local: quit

Error: No such file or directory

krb5-rsh -PN -x krb.spinlock.hr


Couldn't authenticate to server: Server rejected authentication (during sendauth exchange)
Server returned error code 60 (Generic error (see e-text))
Error text sent from server: No such file or directory

The above error indicates that we should pay attention to the "e-text" (error text returned to the client). The error text tells us, in kind of a confusing way (since, you see, there is no filename reported), that the /etc/krb5.keytab file is missing altogether. This is not very likely to happen on Debian GNU since the file is created as part of the automatic package configuration routine. In any case, to create the file, we need to use the kadmin.local command and populate the file with two default entries, kadmin/admin and kadmin/changepw:

sudo kadmin.local
Authenticating as principal root/admin@SPINLOCK.HR with password.

kadmin.local:  ktadd -k /etc/krb5.keytab kadmin/admin kadmin/changepw

Entry for principal kadmin/admin with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal kadmin/admin with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal kadmin/changepw with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal kadmin/changepw with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.

kadmin.local: quit

Error: Key table entry not found

krb5-rsh -PN -x krb.spinlock.hr


Couldn't authenticate to server: Server rejected authentication (during sendauth exchange)
Server returned error code 60 (Generic error (see e-text))
Error text sent from server: Key table entry not found

Ok. So we now see that the krb5 server did accept the connection, but there's still something preventing the thing from working. The e-text "Key table entry not found" indicates that the host/service principal (created earlier) is not listed in the keytab file. (While for users a principal entry is enough, services need to be listed in the keytab file as well). So we invoke kadmin.local very similarly to the other ktadd example from above:

sudo kadmin.local
Authenticating as principal root/admin@SPINLOCK.HR with password.

kadmin.local:  ktadd -k /etc/krb5.keytab host/monarch.spinlock.hr

Entry for principal host/monarch.spinlock.hr with kvno 8, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
Entry for principal host/monarch.spinlock.hr with kvno 8, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.

kadmin.local: quit

Error: Decrypt integrity check failed

krb5-rsh -PN -x krb.spinlock.hr


Couldn't authenticate to server: Server rejected authentication (during sendauth exchange)
Server returned error code 31 (Decrypt integrity check failed)
Error text sent from server: Decrypt integrity check failed

Typically, this can happen when you delete the service and add it again, after the ticket was already obtained. If you remember, the principal for the service was created with the -randkey switch, and so as the key changes randomly on each invocation, it broke the decryption integrity check. Your ticket is not expired, but it can't be used any more -- the encryption keys have changed. The solution to this is to simply destroy the ticket and obtain a new one. To do so, just run kdestroy; kinit.

Error: Key version number for principal in key table is incorrect

krb5-rsh -PN -x krb.spinlock.hr


Couldn't authenticate to server: Server rejected authentication (during sendauth exchange)
Server returned error code 60 (Generic error (see e-text))
Error text sent from server: Key version number for principal in key table is incorrect

This means that the encryption key did not change, but the Key Version Number ("KVNO") did. This usually happens when you change the keytab file after obtaining the ticket. Luckily, the solution, can't be simpler: kdestroy; kinit.

That was a pretty extensive list of problems you might encounter. Supposing you got Kerberos login working, let's move onto PAM configuration.

PAM Configuration

Our PAM setup will work out of the box, and it would be very wise that you get familiar with the PAM Configuration File Syntax before introducing any changes.

Long story short, PAM has four management groups. We need to add pam_krb5.so to all of them. See pam_krb5(5) for a description why. (Just keep one thing in mind; session management group isn't as useless as one would conclude from the manual page -- it actually initializes the Kerberos Ticket Granting Ticket for you, so you don't have to invoke kinit manually.)

Anyway, here's the show. (PAM configuration has its quirks, so don't try to be smart too early; just copy-paste this to your files and avoid the trouble.)

/etc/pam.d/common-account

Adjust the file as show below. Either traditional Unix or Kerberos account will be enough to pass this step. If both fail, user will be denied access.

account sufficient        pam_unix.so
account sufficient pam_krb5.so
account required pam_deny.so

/etc/pam.d/common-auth

The following configuration requires a valid password from either Kerberos or the traditional password file. For users that will only authenticate through Kerberos, putting a "*K*" in the password field in /etc/shadow (or /etc/passwd if no shadow passwords are used) is common to both prevent shadow-based authentication and to informally signify a Kerberos login. If both the Kerberos password and the shadow password exist, then the user will be able to type in ANY OF THEM to gain access. If the passwords are the same, then the order of the auth lines will determine which method will take precendence (first match wins).

auth    sufficient        pam_unix.so nullok_secure
auth sufficient pam_krb5.so use_first_pass
auth required pam_deny.so

/etc/pam.d/common-password

The following configuration is used for changing the password, and it only operates on the password in the Kerberos database.

password  sufficient   pam_unix.so nullok obscure md5
password sufficient pam_krb5.so use_first_pass
password required pam_deny.so

/etc/pam.d/common-session

The following configuration invokes the usual pam_limits.so module, then initializes the TGT (if the user authenticated with a Kerberos password), and then logs session open to the system log files. (It will also log session closedown when a user disconnects).

session optional pam_unix.so
session optional pam_krb5.so


Conclusion


At this point, you should have a working Kerberos installation. You can create an account ("principal") in Kerberos, and then use it to log in into the system and/or access services.

Note that Kerberos does not keep user information in its database (user ID, group ID, real name etc.). So, in the above setup as shown, you first have to create a normal Unix user (with /etc/passwd entry), and then create it also in Kerberos. Note that the traditional authentication method (from /etc/password & friends) is listed first in the PAM configuration. This means, if you set an identical password for Unix and Kerberos, pam_unix authentication will succeed, skipping the Kerberos part and failing to automatically initialize your Kerberos ticket. Therefore, choose a different Kerberos password for a user than what you've set in /etc/passwd or shadow. Then, by typing Kerberos password, you'll make sure the right thing happens -- authentication will be performed by Kerberos, and Kerberos will initialize users' Kerberos ticket and allow them to access Kerberizes services without typing in any credentials (similar to SSH keys).

To completely eliminate /etc/passwd (and related files), you will have to install LDAP or something like libnss-ptdb, but this will be covered in other articles.

The newest version of this article can always be found at http://techpubs.spinlocksolutions.com/dklar/kerberos.html.

Davor Ocelic
http://www.spinlocksolutions.com/


Copyright (C) 2006,2007 Davor Ocelic, <docelic@spinlocksolutions.com>
Spinlock Solutions, http://www.spinlocksolutions.com/

This documentation is free; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.


This article can be found online at the Debian Administration website at the following bookmarkable URL (along with associated comments):

This article is copyright 2007 docelic - please ask for permission to republish or translate.