![]() | Microsoft trusting MIT Kerberos
© 2009 Dennis Leeuw dleeuw at made-it dot com |
Many thanks go out to Rene Dokter for his help on the Microsoft related parts. Without him I wouldn't have succeeded.
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.
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.
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.
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:
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:
User Principle Name - A Kerberos user principal
Service Principle Name - A Kerberos service or host principal
Update Sequence Number might be identical to kvno ???
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).
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:
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.
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.
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.
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.
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.
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.
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.
|
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 |
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.
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 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:
libdefaults – contains default values for the kerberos library
login – contains default values for the klogin program
appdefaults – contains the defaults for kerberized applications
realms – contains realm descriptions
domain_realm – describes relationships between DNS domains and realms
logging – describes how logging is performed (only needed on the KDC)
capaths – contains the authentication paths for cross-realm authentication
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:
kdcdefaults – defaults for overall KDC behaviour
realms – specifies realm specific information
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 -sThe -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
Create an admin account that acts as our root account on Kerberos:
kadmin.local kadmin.local: addprinc admin/admin@EXAMPLE.COMWith 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.COMYou 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.
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
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.
service krb5kdc start
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
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:
AS_REQ is the initial user authentication request (i.e. made with kinit) This message is directed to the KDC component known as Authentication Server (AS);
AS_REP is the reply of the Authentication Server to the previous request. Basically it contains the TGT (encrypted using the TGS secret key) and the session key (encrypted using the secret key of the requesting user);
TGS_REQ is the request from the client to the Ticket Granting Server (TGS) for a service ticket. This packet includes the TGT obtained from the previous message and an authenticator generated by the client and encrypted with the session key;
TGS_REP is the reply of the Ticket Granting Server to the previous request. Located inside is the requested service ticket (encrypted with the secret key of the service) and a service session key generated by TGS and encrypted using the previous session key generated by the AS;
AP_REQ is the request that the client sends to an application server to access a service. The components are the service ticket obtained from TGS with the previous reply and an authenticator again generated by the client, but this time encrypted using the service session key (generated by TGS);
AP_REP is the reply that the application server gives to the client to prove it really is the server the client is expecting. This packet is not always requested. The client requests the server for it only when mutual authentication is necessary.
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
This section will add workstations and an user to the MIT Kerberos server.
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.
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: quitOr copy the /etc/krb5.keytab file from your Kerberos host.
With klist make sure the kvno's are identical.
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)
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).
Log in on the XP client using the KRB5.EXAMPLE.COM realm. You should be able to log in without problems.