Microsoft trusting MIT Kerberos

© 2009 Dennis Leeuw dleeuw at made-it dot com
License: GPLv2 or later

Credits

Many thanks go out to Rene Dokter for his help on the Microsoft related parts. Without him I wouldn't have succeeded.

Introduction

When you have a heterogeneous network with Windows servers, Mac OS X servers and GNU/Linux servers you quickly discover that it is very hard to maintain a single database with passwords. You do not want to have NIS, OpenLDAP, AD, Open Directory, smbpasswd, and what have you, in your data center and maintain all those different databases with identical passwords and user information. We want an unified solution to store passwords.

The authentication solution: Kerberos

This document assumes the use of Kerberos V5, since that is what Microsoft, and Apple use. So also on the GNU/Linux installation we will be using the V5 version, and only the V5 solution.

The Pro's

Kerberos also makes sure no passwords are transmitted over the wire which makes it inherently more safe then any other product in the world.

By using trusts between the different systems a user logging in to e.g. Active Directory can use services on the GNU/Linux network without the need of logging in again. The user is “trusted”.

Next to these security and interoperability benefits there is also the gain of Single-Sign-On.

The first step of integration that we are talking about is the use of a single password store. Meaning that the user password is stored in a single place, and maintained in a single place. Active Directory and Open Directory should thus both use the MIT Kerberos server or trust the MIT kerberos server.

Definitions

Before we dive into the world of Kerberos and related stuff we would like you to read: http://web.mit.edu/kerberos/www/dialogue.html. And please, read it again, because understanding this story is crucial to understanding the rest of the document. After you have read the dialogue, we can start to introduce the key terms of Kerberos:

Security Principal or often just plain Principle
is the entity in the Kerberos database for a user or computer. You could compare this with the user name on other systems.
Realm
The collection of principals belonging to the same security group, or network. A windows domain is really a realm.
Ticket
Encrypted information used by all parties to authenticate a security principal. For every form of access a ticket is needed.
KDC
Key Distribution Center. The server responsible for supplying the tickets. It actually consists of two parts. The authentication service (AS) and the ticket granting service (TGS).
Authentication Service (AS)
The service that initially verifies that a user is who he claims to be. When a user is authenticated, the KDC issues a ticket-granting ticket or TGT.
TGT
TGT is a Ticket-Granting-Ticket. With the TGT a user can request additional tickets to access services on the network. It is the TGT that makes Single Sign On possible.
Ticket Granting Service (TGS)
The Ticket Granting Service verifies the user's identity using the Ticket Granting Ticket and issues a ticket for the desired service.
KRBTGT Account
This is a special account to create Ticket Granting Tickets.
Validating Server
Is the server that the client tries to access.
Session Key
Random number generated by the KDC when it builds a ticket. It is the shared secret that the KDC, the client, and the validating server have in common.
Key salt
the salt is a string concatenated to the password to make sure the string2key function creates a unique encryption key, via a one-way hash. In Kerberos 5 the salt is the complete principal name including the realm. The reason the salt is used is to make sure the outcome of the one way hash is unique across realms.
kvno
is an acronym for Key version number. Kerberos can hold multiple keys for a principal. To distinguish between those keys every key has version number. The number is incremented by one when the password or encryption is changed.

Active Directory

Since Microsoft Windows is a bit different from the rest of the world, it is worth a couple of words. The Microsoft Kerberos implementation is meant to replace NTLM. So a couple of services are still NTLM only and can not be used or can only by used through the GSSAPI which is called SSPI on Windows.

The domain name in Windows is case insensitive, while in MIT Kerberos it is case sensitive. Recent revisions to the Kerberos standard have specified that uppercase realm names are preferred and lowercase realm names have been depreciated.

Unlike the MIT implementation, the Windows Kerberos implementation uses an in-memory credential cache to store tickets and TGTs (the MIT implementation uses a disk file).

Microsoft also uses a couple of Microsoft specific terms:

  1. User Principle Name - A Kerberos user principal

  2. Service Principle Name - A Kerberos service or host principal

  3. Update Sequence Number might be identical to kvno ???

  4. Local Security Authority - Portion of Windows that calls upon log in services (WINLOGON and NETLOGON) to get security credentials from users. The user-side is the Local Security Subsystem (LSASS.EXE) and the server side is the Security Reference Monitor (SRM).

Con's

Of course there aren't only positive things about Kerberos, there are also weak points. So here we will give you some things to think about when using Kerberos and to maintain a secure system:

  1. Kerberos uses a principal's password as the fundamental proof of identity, so as with every other kind of password based security, it is essential to keep the password private.

  2. The strength of the security within Kerberos is based on the unbreakability of the encryption technology. Since we need to connect with Active Directory we are bound to rc4-hmac encryption.

  3. A brute force attack on the KDC could compromise the entire network, since it contains all the passwords (in an encrypted version, but still). So the security of the KDC is essential.

  4. Kerberos assumes that the host it is running on is safe, so if an attacker can get hold of a client it can steal tickets and during the lifetime of the ticket do the same things a normal user could.

  5. On multi-user systems the above point even becomes more important. Meaning that the different users should not be able to access each others files and memory.

  6. Since anybody can request a TGT of any user, and that ticket is encrypted with the user's secret key (password), it is simple to perform an offline attack on this ticket by trying to decrypt it with different passwords. Kerberos 5 introduced to solve this problem.

A MIT Kerberos installation

Expected knowledge

GNU/Linux (Operating System, DNS, OpenLDAP) knowledge is a must, Microsoft Windows (Operating System, DNS, AD) knowledge is a must and a good understanding of how user id's are used in the different systems is a must.

We also assume that the reader has setup an LDAP system before and knows his way around with tools that deal with user account creation on the different platforms.

Software used

Function

Host name

Software

AD server

ads.forest.example.com

Windows 2003 R2 Enterprise Edition Service Pack 2

Windows client

bofh015

Windows XP Professional Version 2002 Service Pack 3

GNU/Linux client

bofh011

Fedora release 9 (Sulphur), MIT Kerberos 1.6.3

GNU/Linux server

krb5.example.com

CentOS release 5.2 (Final), MIT Kerberos 1.6.1, OpenLDAP 2.3.27

It's about time

Kerberos is very time sensitive so make sure all your computers (servers and clients) use NTP. And are synced against the same time server. For our situation we used krb5.example.com as the NTP server.

DNS, realm or domain

MS Kerberos uses DNS for everything it needs to know about Kerberos, MIT also recommends the use of DNS, so we will do too.

It is possible to use non-DNS style Kerberos names, however that is not recommended and we will thus not use them. The advise is to use the uppercase naming of the DNS domain as the name for the Kerberos realm.

And for the GNU/Linux with MIT kerberos we use:

DNS: example.com

realm: EXAMPLE.COM

Note that MS also uses a NetBIOS name for its systems called the domain name, which might create confusion. For the Windows network we use:

DNS: forest.example.com

realm: FOREST.EXAMPLE.COM

NETBIOS: FOREST

Throughout this document, when we refer to domain, we mean the DNS domain. For Kerberos we will refer to realm and for NetBIOS we will call it the NetBIOS name or Microsoft domain.

The MIT Kerberos server

The krb5.conf file is a Windows INI style configuration file. This file is located in the /etc directory and used on both the workstation and the server to configure Kerberos.

This file can have different sections, which are headed by the section name in square brackets ([]). The available sections are:

If there is no DNS TXT record you must specify the default_domain in the realms section. If no SRV records are used the KDC an admin_server tags are mandatory in the realms section. Since our DNS is setup correctly we strictly speaking only need the admin_server tag. To make sure that even without the SRV tags everything works we provide you with a full krb5.conf configuration file, if you also mention the host names with IP addresses in you host file, Kerberos will keep on running even without DNS:

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

[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
forwardable = true

[realms]
EXAMPLE.COM = {
	kdc = kerberos.example.com:88
	admin_server = kerberos.example.com:749
	default_domain = EXAMPLE.COM
}

[domain_realm]
.examle.com = EXAMPLE.COM
example.com = EXAMPLE.COM

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

Next we need to setup the kdc.conf file, which is also a windows style INI file. It can be found in /var/kerberos/krb5kdc/kdc.conf. The sections in the file are:

In the realms section we have reduced the amount of supported_enctypes to the ones supported by Microsoft Windows. Since Open Directory uses MIT Kerberos all systems should use the same encryption types (also known as etypes, more on etypes can be found in Appendix A).

[kdcdefaults]
v4_mode = none
# kdc_tcp_ports = 88

[realms]
EXAMPLE.COM = {
	# GENERIC STUFF
	#master_key_type = des3-hmac-sha1
	dict_file = /usr/share/dict/words
	supported_enctypes = rc4-hmac:normal rc4-hmac-exp:normal des-cbc-crc:normal

	# DB stuff
	acl_file = /var/kerberos/krb5kdc/example.com/kadm5.acl
	admin_keytab = /var/kerberos/krb5kdc/example.com/kadm5.keytab
	database_name = /var/kerberos/krb5kdc/example.com/principals

	# PRINCIPAL stuff

}

We store our database information in a realm specific directory, so we will be able to add realms in the future and have a directory per realm, we thus need to create the directory:

mkdir /var/kerberos/krb5kdc/example.com

To give certain users the ability to change settings in the password store, and others only the ability to query we have to create an access control list called the kadmin.acl in the directory of the realm:

krbadm@EXAMPLE.COM *
*/admin@EXAMPLE.COM *
*/*@EXAMPLE.COM i
*@EXAMPLE.COM i

Now that everything is in place we can create our database:

kdb5_util create -r EXAMPLE.COM -s
The -s option generates a stash file.

NOTE: The database can be remove with:

rm -f /var/kerberos/krb5kdc/example.com/principals*
rm -f /var/kerberos/krb5kdc/.k5.EXAMPLE.COM

Add administrators to the Kerberos database

Create an admin account that acts as our root account on Kerberos:

kadmin.local
kadmin.local: addprinc admin/admin@EXAMPLE.COM

With the listprincs command you can get an overview of the currently available principals.
kadmin.local:  listprincs 
K/M@EXAMPLE.COM
admin/admin@EXAMPLE.COM 
kadmin/admin@EXAMPLE.COM
kadmin/changepw@EXAMPLE.COM 
kadmin/krb5.example.com@EXAMPLE.COM
kadmin/history@EXAMPLE.COM 
krbtgt/EXAMPLE.COM@EXAMPLE.COM
You see that besides our just created admin/admin account there are a couple more, which are automatically created for you and are needed by Kerberos to function correctly.

krb5.keytab

All non-Microsoft Kerberos machines need a file, called /etc/krb5.keytab, to authenticate to the KDC. The keytab file is an encrypted, local, on-disk copy of the KDC's key. In order to generate a keytab for a host, the host must have a principal in the Kerberos database.

Since our KDC is also a client for itself it needs such a krb5.keytab file. Before we can generate the keytab file, we first need to add krb5 to the database as a known host with a password, but we also want to be flexible, we do not want to change all keytab files when we promote e.g. a slave as a master. So we will not use krb5 as the host name, but it's alias kerberos.

The password that is generated for the key should never be changed, we thus use the -randkey option to generate a random password, which even we will not know. Using kadmin.local we generate the host principal for krb5 like this:

kadmin.local: addprinc -randkey host/kerberos.example.com

Now we can extract the needed keys to our local /etc/krb5.keytab file:

kadmin.local: ktadd host/kerberos.example.com
kadmin.local: ktadd kadmin/admin
kadmin.local: ktadd kadmin/changepw

Start the KDC and KADMIN

On Red Hat based systems, like ours, we run authconfig-tui and add Kerberos support to make sure PAM is setup correctly. After that we can start our services.

Starting krb5kdc

service krb5kdc start

Starting kadmind

Adjust the /etc/init.d/kadmin script to reflect our setup. Since the current script assumes everything to be in /var/kerberos/krb5kdc/ we had to tweak the script a bit.

For CentOS 5.2 change around line 25 the following:

# See where our KDC stores its stuff 
# we assume single realm. 
KDC_CONF="/var/kerberos/krb5kdc/kdc.conf"
	
db_file=`grep database_name ${KDC_CONF} |grep -v ^# | awk '{print $3}'`

For CentOS 5.3 change around line 29:

       if [ ! -f /var/kerberos/krb5kdc/principal ] ; then
into (note the plural):
       if [ ! -f /var/kerberos/krb5kdc/example.com/principals ] ; then

Now we can start kadmin:

service kadmin start

Reading MIT KDC logs

To help in debugging certain problems it helps to understand the logging of the MIT kerberos server. Let us start with a log line from the krb5kdc.log:

Feb 26 17:02:01 krb5.example.com krb5kdc[26922](info): AS_REQ (7 etypes {23 -133 -128 3 1 24 -135}) 192.168.1.3: \
	ISSUE: authtime 1235664121, etypes {rep=23 tkt=16 ses=23}, kprutser@EXAMPLE.COM for krbtgt/EXAMPLE.COM@EXAMPLE.COM

The first element is AS_REQ in our example. Here is a complete list of possible elements and their meaning:

Between semi-colons are the etypes supported by the requester. The negative numbers are numbers used by protocol implementers, so they are vendor specific, and the positive numbers come from RFC 3961.

The IP address (192.168.1.3) mentioned is the IP address of the requesting party.

Then we get the authtime which is in seconds since 1970-01-01 00:00:00 UTC.

Then we get where this request was based on {rep=23, tkt=16, ses=23}, which is where in this case my problem was. The ticket is etype 16, while as we saw before, the client didn't support des3-cbc-sha1-kd. Both reply (rep) and session(ses) have the correct type. More on the different etypes can be found in Appendix B

Adding workstations

This section will add workstations and an user to the MIT Kerberos server.

Adding the user

Add a test user to the Kerberos database:

kadmin.local: addprinc kprutser
WARNING: no policy specified for kprutser@EXAMPLE.COM; defaulting to no policy 
Enter password for principal "kprutser@EXAMPLE.COM":
Re-enter password for principal "kprutser@EXAMPLE.COM": 
Principal "kprutser@EXAMPLE.COM" created.

For the GNU/Linux system this user should be present in a user database where the UID and GID can be resolved, like OpenLDAP. And for windows this user should be present in AD. See the PIG documentation on creating AD users with OpenLDAP tools.

The GNU/Linux workstation

On the Linux client we need a krb5.conf file that reflects our server setup, here we fully use the DNS features:

[libdefaults]
# default_realm = EXAMPLE.COM
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
forwardable = true

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

On Red Hat based systems we run authconfig-tui and add kerberos to the client machine.

Add the kerberos host to the local /etc/krb5.keytab file:

kadmin: ktadd host/kerberos.example.com 
kadmin: quit
Or copy the /etc/krb5.keytab file from your Kerberos host.

With klist make sure the kvno's are identical.

Tests

Sign in to your own domain (need to get ticket):

Use kinit to sign in. (we need to get a ticket)

kinit kprutser
Password for kprutser@EXAMPLE.COM:

Use klist to show that you got a real ticket

ssh to realm kdc (should be able to login without password)

ssh to kerberos (you should be able to connect without password)

The Windows XP Workstation

On a clean workstation add the realm to XP, by issuing on the command line:

ksetup /setrealm EXAMPLE.COM
ksetup /addkdc EXAMPLE.COM kerberos.example.com

Note1: No user mappings (for those that read the documentation elsewhere on the Internet)
Note2: But user needs to exist locally!!!

Make sure that the password for the windows client host principal is identical on windows and on kerberos (we can NOT use the -randkey option):

On the kerberos server use:

addprinc -pw password host/bofh015.example.com

On the windows client use:

ksetup /SetComputerPassword password

On the KDC you will see the following in your log files (lines wrapped for readability):

Mar 02 14:57:33 krb5.example.com krb5kdc[27027](info): AS_REQ (7 etypes {23 -133 -128 3 1 24 -135}) 192.168.1.3: \
	ISSUE: authtime 1236002253, etypes {rep=23 tkt=23 ses=23}, kprutser@EXAMPLE.COM for krbtgt/EXAMPLE.COM@EXAMPLE.COM 
Mar 02 14:57:33 krb5.example.com krb5kdc[27027](info): AS_REQ (7 etypes {23 -133 -128 3 1 24 -135}) 192.168.1.3: \
	ISSUE: authtime 1236002253, etypes {rep=23 tkt=23 ses=23}, kprutser@EXAMPLE.COM for krbtgt/EXAMPLE.COM@EXAMPLE.COM 
Mar 02 14:57:33 krb5.example.com krb5kdc[27027](info): TGS_REQ (7 etypes {23 -133 -128 3 1 24 -135}) 192.168.1.3: \
	ISSUE: authtime 1236002253, etypes {rep=23 tkt=23 ses=23}, kprutser@EXAMPLE.COM for host/bofh015.example.com@EXAMPLE.COM
Mar 02 14:57:33 krb5.example.com krb5kdc[27027](info): TGS_REQ (7 etypes {23 -133 -128 3 1 24 -135}) 192.168.1.3: \
	ISSUE: authtime 1236002253, etypes {rep=23 tkt=23 ses=23}, kprutser@EXAMPLE.COM for host/bofh015.krb5.example.com@EXAMPLE.COM 
Mar 02 14:57:39 krb5.example.com krb5kdc[27027](info): AS_REQ (7 etypes {18 17 16 23 1 3 2}) 192.168.1.3: \
	ISSUE: authtime 1236002259, etypes {rep=23 tkt=23 ses=23}, kprutser@EXAMPLE.COM for krbtgt/ EXAMPLE.COM@EXAMPLE.COM 
Mar 02 14:57:39 krb5.example.com krb5kdc[27027](info): AS_REQ (7 etypes {18 17 16 23 1 3 2}) 192.168.1.3: \
	ISSUE: authtime 1236002259, etypes {rep=23 tkt=23 ses=23}, kprutser@EXAMPLE.COM for krbtgt/ EXAMPLE.COM@EXAMPLE.COM

Which means you have a ticket for the user (first 2 log lines), a ticket for the machine (second two log lines) and a TGT (last two log lines).

Tests

Log in on the XP client using the KRB5.EXAMPLE.COM realm. You should be able to log in without problems.