This section covers the installation of the Heimdal Kerberos implementation as well as some aspects of administration. This section assumes you are familiar with the basic concepts of Kerberos (see also Section 19.3. “Network Authentication — Kerberos”).
The domain of a Kerberos installation is called a realm and is identified by a name, such as FOOBAR.COM or simply ACCOUNTING. Kerberos is case-sensitive, so foobar.com is actually a different realm than FOOBAR.COM. Use the case you prefer. It is common practice, however, to use uppercase realm names.
It is also a good idea to use your DNS domain name (or a subdomain, such as ACCOUNTING.FOOBAR.COM). As shown below, your life as an administrator can be much easier if you configure your Kerberos clients to locate the KDC and other Kerberos services via DNS. To do so, it is helpful if your realm name is a subdomain of your DNS domain name.
Unlike the DNS name space, Kerberos is not hierarchical. You cannot set up a realm named FOOBAR.COM, have two “subrealms” named DEVELOPMENT and ACCOUNTING underneath it, and expect the two subordinate realms to somehow inherit principals from FOOBAR.COM. Instead, you would have three separate realms for which you would have to configure crossrealm authentication for users from one realm to interact with servers or other users from another realm.
For the sake of simplicity, assume you are setting up just one realm for your entire organization. Setting up crossrealm authentication is described in [tung:99], for instance. For the remainder of this section, the realm name SAMPLE.COM is used in all examples.
The first thing required to use Kerberos is a machine that will act as the key distribution center, or KDC for short. This machine holds the entire Kerberos user database with passwords and all information.
The KDC is the most important part of your security infrastructure — if someone breaks into it, all user accounts and all of your infrastructure protected by Kerberos is compromised. An attacker with access to the Kerberos database can impersonate any principal in the database. Tighten security for this machine as much as possible:
Put the server machine into a physically secured location, such as a locked server room to which only a very few people have access.
Do not run any network applications on it except the KDC. This includes servers and clients — for instance, the KDC should not import any file systems via NFS or use DHCP to retrieve its network configuration.
It is probably a good approach to install a minimal system first then check the list of installed packages and remove any unneeded packages. This includes servers, such as inetd, portmap, and cups, as well as anything X11-based. Even installing an SSH server should be considered a potential security risk.
No graphical login is provided on this machine as an X server is a potential security risk. Kerberos provides its own administration interface.
Configure /etc/nsswitch.conf to use only local files for user and group lookup. Change the lines for passwd and group to look like this:
passwd: files group: files
Edit the passwd, group, shadow, and gshadow files in /etc and remove the lines that start with a + character (these are for NIS lookups).
Also consider disabling DNS lookups, because there is a potential risk involved. If there is a security bug in the DNS resolver library, an attacker might be able to trick the KDC into performing a DNS query that triggers this bug. To disable DNS lookups, simply remove /etc/resolv.conf.
Disable all user accounts except root's account by editing /etc/shadow and replacing the hashed passwords with * or ! characters.
To use Kerberos successfully, make sure all system clocks within your organization are synchronized within a certain range. This is important because Kerberos protects against replayed credentials. An attacker might be able to observe Kerberos credentials on the network and reuse them to attack the server. Kerberos employs several defenses to prevent this. One of them is that it puts time stamps into its tickets. A server receiving a ticket with a time stamp that differs from the current time rejects the ticket.
Kerberos allows a certain leeway when comparing time stamps. However, computer clocks can be very inaccurate in keeping time — it is not unheard of for PC clocks to lose or gain half an hour over the course of a week. For this reason, configure all hosts on the network to synchronize their clocks with a central time source.
A simple way to do so is by installing an NTP time server on one machine and having all clients synchronize their clocks with this server. Do this either by running an NTP daemon in client mode on all these machines or by running ntpdate once a day from all clients (this solution will probably work for a small number of clients only). The KDC itself needs to be synchronized to the common time source as well. Because running an NTP daemon on this machine would be a security risk, it is probably a good idea to do this by running ntpdate via a cron entry. NTP configuration itself is beyond the scope of this section. For more information, refer to the NTP documentation included in your installed system under /usr/share/doc/packages/xntp-doc.
It is also possible to adjust the maximum deviation Kerberos allows when checking time stamps. This value (called “clock skew”) can be set via the krb5.conf file as described in Section 19.4.6.3. “Adjusting the Clock Skew”.
By default, the Kerberos daemons running on the KDC host log information to the syslog daemon. To keep an eye on what your KDC is doing, process these log files regularly, scanning for unusual events or potential problems. Either do this by running a log scanner script on the KDC host itself or by copying these files from the KDC to another host with rsync. Forwarding all log output via syslogd's log forwarding mechanisms is not recommended, because information traverses the network unencrypted.
This section covers the initial installation of the KDC, including creation of an administrative principal.
Before you can start, install the Kerberos software. On the KDC, install the packages heimdal, heimdal-lib, and heimdal-tools with rpm -ivh heimdal-*.rpm heimdal-lib-*.rpm heimdal-tools*.rpm.
Your next step is to initialize the database where Kerberos keeps all information about principals. First, set the database master key, which is used to protect the database from accidental disclosure, in particular when it is backed up to a tape. The master key is derived from a pass phrase and is stored in a file called the stash file. This is so you do not need to type in the password every time the KDC is restarted. Make sure you choose a good pass phrase, such as a sentence from a book opened to a random page.
When you make tape backups of the Kerberos database (/var/heimdal/heimdal.db), do not back up the stash file (which is in /var/heimdal/m-key). Otherwise, everyone able to read the tape could also decrypt the database. Therefore, it is also a good idea to keep a copy of the pass phrase in a safe or some other secure location, because you will need it when restoring your database from backup tape after a crash.
To set the master key, run kstash without arguments and enter the pass phrase twice:
kstash Master key:<enter pass phrase> Verifying password - Master key:<enter pass phrase again>
Finally, create entries for your realm in the Kerberos database. Run kadmin with the -l option as shown. This option tells kadmin to access the database locally. By default, it tries to contact the Kerberos admin service over the network. At this stage, this will not work because it is not running yet.
Now, tell kadmin to initialize your realm. It will ask you a number of questions in return. It is best to accept the default settings offered by kadmin initially:
kadmin -l kadmin> init SAMPLE.COM Realm max ticket life [unlimited]: <press return> Realm max renewable ticket life [unlimited]: <press return>
To verify that it did anything, use the list command:
kadmin> list * default@SAMPLE.COM kadmin/admin@SAMPLE.COM kadmin/hprop@SAMPLE.COM kadmin/changepw@SAMPLE.COM krbtgt/SAMPLE.COM@SAMPLE.COM changepw/kerberos@SAMPLE.COM
This shows that there are now a number of principals in the database. All of these are for internal use by Kerberos.
Next, create two Kerberos principals for yourself: one normal principal for your everyday work and one for administrative tasks relating to Kerberos. Assuming your login name is newbie, proceed as follows:
kadmin -l kadmin> add newbie Max ticket life [1 day]: <press return> Max renewable life [1 week]: <press return> Principal expiration time [never]: <press return> Password expiration time [never]: <press return> Attributes []: <press return> newbie@SAMPLE.COM's Password: <type password here> Verifying password: <re-type password here>
Accepting the defaults by pressing Enter is okay. Choose a good password, however.
Next, create another principal named newbie/admin by typing add newbie/admin at the kadmin prompt. The admin suffixed to your user name is a “role”. Later, use this role when administering the Kerberos database. A user can have several roles for different purposes. Roles are basically completely different accounts with similar names.
Start the KDC daemons. This includes kdc itself (the daemon handling user authentication and ticket requests), kadmind (the server performing remote administration), and kpasswddd (handling user's password change requests). To start the daemon manually, enter rckdc start. Also make sure KDC is started by default when the server machine is rebooted with the command insserv kdc.
When configuring Kerberos, there are basically two approaches you can take — static configuration via the /etc/krb5.conf file or dynamic configuration via DNS. With DNS configuration, Kerberos applications try to locate the KDC services via DNS records. With static configuration, add the host names of your KDC server to krb5.conf (and update the file whenever you move the KDC or reconfigure your realm in other ways).
DNS-based configuration is generally a lot more flexible and the amount of configuration work per machine is a lot less. However, it requires that your realm name is either the same as your DNS domain or a subdomain of it. Configuring Kerberos via DNS also creates a minor security issue — an attacker can seriously disrupt your infrastructure through your DNS (by shooting down the name server, by spoofing DNS records, etc). However, this amounts to a denial of service at most. A similar scenario applies to the static configuration case unless you enter IP addresses in krb5.conf instead of host names.
One way to configure Kerberos is to edit the configuration file /etc/krb5.conf. The file installed by default contains various sample entries. Erase all of these entries before starting. krb5.conf is made up of several sections, each introduced by the section name included in brackets like [this].
To configure your Kerberos clients, add the following stanza to krb5.conf (where kdc.sample.com is the host name of the KDC):
[libdefaults] default_realm = SAMPLE.COM [realms] SAMPLE.COM = { kdc = kdc.sample.com kpasswd_server = kdc.sample.com admin_server = kdc.sample.com }
The default_realm line sets the default realm for Kerberos applications. If you have several realms, just add another statement to the [realms] section.
Also add a statement to this file that tells applications how to map host names to a realm. For instance, when connecting to a remote host, the Kerberos library needs to know in which realm this host is located. This must be configured in the [domain_realms] section:
[domain_realm] .sample.com = SAMPLE.COM www.foobar.com = SAMPLE.COM
This tells the library that all hosts in the sample.com DNS domains are in the SAMPLE.COM Kerberos realm. In addition, one external host named www.foobar.com should also be considered a member of the SAMPLE.COM realm.
DNS-based Kerberos configuration makes heavy use of SRV records (see (RFC2052) A DNS RR for specifying the location of services at http://www.ietf.org). These records are not supported in earlier implementations of the BIND name server. At least BIND version 8 is required for this.
The name of an SRV record, as far as Kerberos is concerned, is always in the format _service._proto.realm, where realm is the Kerberos realm. Domain names in DNS are case insensitive, so case-sensitive Kerberos realms would break when using this configuration method. _service is a service name (different names are used when trying to contact the KDC or the password service, for example). _proto can be either _udp or _tcp, but not all services support both protocols.
The data portion of SRV resource records consists of a priority value, a weight, a port number, and a host name. The priority defines the order in which hosts should be tried (lower values indicate a higher priority). The weight is there to support some sort of load balancing among servers of equal priority. You will probably never need any of this, so it is okay to set these to zero.
Heimdal Kerberos currently looks up the following names when looking for services:
This defines the location of the KDC daemon (the authentication and ticket granting server). Typical records look like this:
_kerberos._udp.SAMPLE.COM. IN SRV 0 0 88 kdc.sample.com. _kerberos._tcp.SAMPLE.COM. IN SRV 0 0 88 kdc.sample.com.
This describes the location of the password changing server. Typical records look like this:
_kpasswd._udp.SAMPLE.COM. IN SRV 0 0 464 kdc.sample.com.
Because kpasswdd does not support TCP, there should be no _tcp record.
This describes the location of the remote administration service. Typical records look like this:
_kerberos-adm._tcp.SAMPLE.COM. IN SRV 0 0 749 kdc.sample.com.
Because kadmind does not support UDP, there should be no _udp record.
As with the static configuration file, there is a mechanism to inform clients that a specific host is in the SAMPLE.COM realm, even if it is not part of the sample.com DNS domain. This can be done by attaching a TXT record to _keberos.hostname, as shown here:
_keberos.www.foobar.com. IN TXT "SAMPLE.COM"
The clock skew is the tolerance for accepting tickets with time stamps that do not exactly match the host's system clock. Usually, the clock skew is set to 300 seconds, or 5 minutes. This means a ticket can have a time stamp somewhere between 5 minutes ago and 5 minutes in the future from the server's point of view.
When using NTP to synchronize all hosts, you can reduce this value to about one minute. The clock skew value can be set in /etc/krb5.conf like this:
[libdefaults] clockskew = 120
To be able to add and remove principals from the Kerberos database without accessing the KDC's console directly, tell the Kerberos administration server which principals are allowed to do what. Do this by editing the file /var/heimdal/kadmind.acl (ACL is an abbreviation for access control list). The ACL file allows you to specify privileges with a fine degree of control. For details, refer to the manual page with man 8 kadmind.
Right now, just grant yourself the privilege to do anything you want with the database by putting the following line into the file:
newbie/admin all
Replace the user name newbie with your own. Restart the KDC for the change to take effect.
You should now be able to perform Kerberos administration tasks remotely using the kadmin tool. First, obtain a ticket for your admin role and use that ticket when connecting to the kadmin server:
kinit newbie/admin newbie/admin@SAMPLE.COM's Password: <enter password> /usr/sbin/kadmin kadmin> privs change-password, list, delete, modify, add, get
Using the privs command, verify which privileges you have. The list shown above is the full set of privileges.
As an example, modify the principal newbie:
kadmin> mod newbie Max ticket life [1 day]:2 days Max renewable life [1 week]: Principal expiration time [never]:2005-01-01 Password expiration time [never]: Attributes []:
This changes the maximum ticket life time to two days and sets the expiration date for the account to January 1, 2005..
Here is a brief list of kadmin commands. For more information, refer to the manual page of kadmin.
add a new principal
edit various attributes of a principal, such as maximum ticket life time and account expiration date
remove a principal from the database
renames a principal to newname
list all principals matching the given pattern. Patterns work much like the shell globbing patterns: list newbie* would list newbie and newbie/admin in our example.
display detailed information about the principal
changes a principal's password
At all stages, help is available by typing ? and Enter. This even works in prompt environments generated by modify and add.
The init command used when initially creating the realm (as well as a few others) is not available in remote mode. To create a new realm, go to the KDC's console and use kadmin in local mode (using the -l command line option). The same is true for dumping and restoring the KDC database using the dump, load, and merge commands.
In addition to making sure every machine on your network knows which Kerberos realm it is in and what KDC to contact, create a host principal for it. So far, only user credentials have been discussed. However, Keberos-compatible services usually need to authenticate themselves to the client user, too. Therefore, special host principals must be present in the Kerberos database for each host in the realm.
The naming convention for host principals is host/>hostname<@<REALM>, where hostname is the host's fully qualified host name. Host principals are similar to user principals, but have significant differences. The main difference between a user principal and a host principal is that the key of the former is protected by a password — when a user obtains a ticket-granting ticket from the KDC, he needs to type his password so Kerberos can decrypt the ticket. Obviously, it would be quite inconvenient for the system administrator if he had to obtain new tickets for the SSH daemon every eight hours or so.
Instead, the key required to decrypt the initial ticket for the host principal is extracted by the administrator from the KDC once and stored in a local file called the keytab. Services such the SSH daemon read this key and use it to obtain new tickets automatically when needed. The default keytab file resides in /etc/krb5.keytab.
To create a host principal for machine.sample.com, enter the following commands during your kadmin session:
kinit newbie/admin newbie/admin@SAMPLE.COM's Password: <type password> kadmin add -r host/machine.sample.com Max ticket life [1 day]: Max renewable life [1 week]: Principal expiration time [never]: Password expiration time [never]: Attributes []:
Instead of setting a password for the new principal, the -r flag tells kadmin to generate a random key. This is used here because no user interaction is wanted for this principal. It is a server account for the machine.
Finally, extract the key and store it in the local keytab file /etc/krb5.keytab. This file is owned by the superuser, so you must be root to execute the next command:
ktutil get host/machine.sample.com
When completed, make sure you destroy the admin ticket obtained via kinit above with kdestroy.
SUSE LINUX comes with a PAM module named pam_krb5, which supports Kerberos login and password update. This module can be used by applications, such as console login, su, and graphical login applications like KDM, where the user presents a password and would like the authenticating application to obtain an initial Kerberos ticket on his behalf.
The pam_unix module, too, supports Kerberos authentication and password updating. To enable Kerberos support in pam_unix, edit the file /etc/security/pam_unix2.conf so it contains the following lines:
auth: use_krb5 nullok account: use_krb5 password: use_krb5 nullok session: none
After that, all programs evaluating the entries in this file use Kerberos for user authentication. For a user that does not have a Kerberos principal, pam_unix falls back on the normal password authentication mechanism. For those users who have a principal, it should now be possible to change their Kerberos passwords transparently using the passwd command.
To make fine adjustments to the way in which pam_krb5 is used, edit the file /etc/krb5.conf and add default applications to pam. For details refer to the manual page with man 5 pam_krb5.
The pam_krb5 module was specifically not designed for network services that accept Kerberos tickets as part of user authentication. This is an entirely different matter, which is discussed below.
OpenSSH supports Kerberos authentication in both protocol version 1 and 2. In version 1, there are special protocol messages to transmit Kerberos tickets. Version 2 does not use Kerberos directly anymore, but relies on “GSSAPI”, the General Security Services API. This is a programming interface that is not specific to Kerberos — it was designed to hide the peculiarities of the underlying authentication system, be it Kerberos, a public-key authentication system like SPKM, or others. The GSSAPI library included in SUSE LINUX supports only Kerberos, however.
To use sshd with Kerberos authentication, edit /etc/ssh/sshd_config and set the following options:
# These are for protocol version 1 KerberosAuthentication yes KerberosTgtPassing yes # These are for version 2 GSSAPIAuthentication yes GSSAPIKeyExchange yes
Then restart your SSH daemon using rcsshd restart.
To use Kerberos authentication with protocol version 2, enable it on the client-side as well. Do this either in the system-wide configuration file /etc/ssh/ssh_config or on a per-user level by editing ~/.ssh/config. In both cases, add the option GSSAPIAuthentication yes.
You should now be able to connect using Kerberos authentication. Use klist to verify you have a valid ticket then connect to the SSH server. To force SSH protocol version 1, specify option -1 on the command line.
When using Kerberos, one way to distribute the user information (such as user ID, groups, home directory, etc.) in your local network is to use LDAP. This requires a strong authentication mechanism that prevents packet spoofing and other attacks. One solution is to use Kerberos for LDAP communication, too.
OpenLDAP implements most authentication flavors through SASL, the simple authentication session layer. SASL is basically a network protocol designed for authentication. The SASL implementation used in SUSE LINUX is cyrus-sasl, which supports a number of different authentication flavors. Kerberos authentication is performed through GSSAPI (General Security Services API). By default, the SASL plug-in for GSSAPI is not installed. Install it manually with rpm -ivh cyrus-sasl-gssapi-*.rpm.
To enable Kerberos binding to the OpenLDAP server, create a principal ldap/earth.sample.com and add that to the keytab:
kadmin add -r ldap/earth.sample.com ktutil get ldap/earth.sample.com
By default, the LDAP server slapd runs as user and group ldap, while the keytab file is readable by root only. Therefore, either change the LDAP configuration so the server runs as root or make the keytab file readable by group ldap.
To run slapd as root, edit /etc/sysconfig/openldap. Disable the OPENLDAP_USER and OPENLDAP_GROUP variables by putting a comment character in front of them.
To make the keytab file readable by group LDAP, execute
chgrp ldap /etc/krb5.keytab chmod 640 /etc/krb5.keytab
Neither solution is perfect. However, at the moment it is not possible to configure OpenLDAP to make it use a separate keytab file. Finally, restart the LDAP server using rcldap restart.
You should now be able to use tools, such as ldapsearch, with Kerberos authentication automatically.
ldapsearch -b ou=People,dc=suse,dc=de '(uid=newbie)' SASL/GSSAPI authentication started SASL SSF: 56 SASL installing layers [...] # newbie, People, suse.de dn: uid=newbie,ou=People,dc=suse,dc=de uid: newbie cn: Olaf Kirch [...]
As you can see, ldapsearch prints a message that it started GSSAPI authentication. The next message is admittedly very cryptic, but it shows that the “Security Strength Factor” (SSF for short) is 56. (The value 56 is somewhat arbitrary. Most likely it was chosen because this is the number of bits in a DES encryption key.) What this tells you is that GSSAPI authentication was successful and that encryption is being used to provide integrity protection and confidentiality of the LDAP connection. If there are several SASL mechanisms that could be used, you can force ldapsearch to use GSSAPI by adding -Y GSSAPI to the command line options.
In Kerberos, authentication is always mutual. This means that not only have you authenticated yourself to the LDAP server, but also the LDAP server authenticated itself to you. In particular, this means communication is with the desired LDAP server, rather than some bogus service set up by an attacker.
Now, allow each user to modify the login shell attribute of their LDAP user record. Assuming you have a schema where the LDAP entry of user joe is located at uid=joe,ou=people,dc=suse,dc=de, set up the following access controls in /etc/openldap/slapd.conf:
# This is required for things to work _at all_ access to dn.base="" by * read # Let each user change their login shell access to dn="*,ou=people,dc=suse,dc=de" attrs=loginShell by self write # Every user can read everything access to * by users read
The second statement gives authenticated users write access to the loginShell attribute of their own LDAP entry. The third statement gives all authenticated users read access to the entire LDAP directory.
There is one minor piece of the puzzle missing, which is how the LDAP server can find out that the Kerberos user joe@SAMPLE.COM corresponds to the LDAP distinguished name uid=joe,ou=people,dc=suse,dc=de. This sort of mapping must be configured manually using the saslExpr directive. In our example, add the following to slapd.conf:
saslRegexp uid=(.*),cn=GSSAPI,cn=auth uid=$1,ou=people,dc=example,dc=com
To understand how this works, you need to know that when SASL authenticates a user, OpenLDAP forms a distinguished name from the name given to it by SASL (such as joe) and the name of the SASL flavor (GSSAPI). The result would be uid=joe,cn=GSSAPI,cn=auth.
If a saslRegexp has been configured, it checks the DN formed from the SASL information using the first argument as a regular expression. If this regular expression matches, the name is replaced with the second argument of the saslRegexp statement. The placeholder $1 is replaced with the substring matched by the (.*) expression.
More complicated match expressions are possible. If you have a more complicated directory structure or a schema in which the user name is not part of the DN, you can even use search expressions to map the SASL DN to the user DN.