Nuts and Bolts SSSD Lead image: Anja Kaiser; Fotolia
Anja Kaiser; Fotolia
 

Single sign-on with SSSD, LDAP, and Kerberos

Cached Tickets

Mobile users need a connection to the LDAP and Kerberos servers to authenticate over insecure IP networks. The System Security Services Daemon (SSSD) helps plug this gap. By Thorsten Scherf

When a user logs in to a Linux system, the Name Service Switch (NSS) is responsible for finding the user account in the user database. Traditionally, the user database is the /etc/passwd file. If the account exists, the PAM subsystem authenticates the user, for example, by comparing the password entered by the user with its counterpart in the /etc/shadow file. This approach quickly reaches its limits, especially if a large number of user accounts exist. In this example, the accounts would need to be created on every single machine because the user and password databases only exist on the local filesystem.

Objects All Around

The problem of user account management can easily be solved using a centralized directory service, such as NIS or LDAP, in which the user credentials are not stored locally but on a central server. Systems that can access the central server can thus query the server when a user tries to log in. Because NIS isn't exactly renowned for providing a secure environment, I'll be using the LDAP directory service in this article. In contrast to NIS, LDAP uses a hierarchical tree structure to store information in attributes.

If you combine these attributes, objects are the result: user objects, for example. A schema defines which information (attributes) can be used together.

An /etc/dirsrv/schema/10rfc2307.ldif schema file on the 389 directory server defines the required attributes for RFC 2307- and 2307bis-compliant user objects. The object class from which user accounts are derived is called posixAccount (Listing 1).

Listing 1: Definition of posixAccount

# grep -i posixaccount /etc/dirsrv/schema/10rfc2307.ldif
objectClasses: ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Standard LDAP
objectclass' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $
homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description )
X-ORIGIN 'RFC 2307' )

All required user attributes, like the UID, login name, and primary user group, are listed here after the MUST tag, whereas optional attributes are listed after the MAY tag. A similar object class exists for group objects and is named posixGroup (Listing 2).

Listing 2: Definition of posixGroup

# grep -i posixgroup /etc/dirsrv/schema/10rfc2307.ldif
objectClasses: ( 1.3.6.1.1.1.2.2 NAME 'posixGroup' DESC 'Standard LDAP
objectclass' SUP top STRUCTURAL MUST ( cn $ gidNumber ) MAY ( userPassword
$ memberUid $ description ) X-ORIGIN 'RFC 2307' )

A detailed description on how the directory server works is beyond the scope of this article, but you can read about in other places [1] if you are interested in more details.

For this article, I assume that an LDAP server with user accounts already exists. Which product you use here doesn't really matter, as long as it complies with the two RFCs I mentioned previously.

Of course, you could store the user password in the LDAP user object. After all, the posixAccount does specifically define a userPassword attribute for this purpose. However, this would obviously cause a security issue: When a user logs in, the password is transmitted in the clear to the LDAP server. If you don't use TLS encryption between the client and the server, anybody could sniff the cleartext password off the wire.

Instead of using TLS to secure communications between the systems involved, the user password should not be transmitted across the wire in the first place, which means saving the password at a location other than on the LDAP server. Incorrectly configured access rules (ACLs) for the password attribute would also mean considerable risk. Fortunately, the Kerberos authentication protocol provides a secure alternative.

Three-Headed Dog

Instead of user passwords, Kerberos transmits tickets across the wire. The tickets are initially exchanged between all the objects involved. This approach offers the advantage of never needing to transmit the password across the network, and tickets provide a single sign-on (SSO) option for users. In other words, once a user has authenticated against the Kerberos server, authentication against any other Kerberos-based service, say an LDAP server, is handled transparently, and users don't need to type their passwords again.

The protocol requires a Kerberos server, also known as a Key Distribution Center (KDC). The KDC contains a database with the passwords of every object involved in the exchange – that is, for users, network services, and machines. All of these are generically referred to as Kerberos principals. The passwords belonging to the principals are governed by a ruleset that specifies how complex they have to be and what their validity period is. Apart from these details, the server doesn't store any user or system information; all of that is stored at a different location, such as on a directory server.

The initial Kerberos login is very simple. The client opens a connection to a Kerberos server (KDC). This process either occurs transparently for the user via the login program or relies on kinit. The KDC comprises two components: an Authentication Server (AS) and a Ticket-Granting Server (TGS). The Authentication Server receives the client query and checks its namespace (realm) for the requested username (user principal). If the principal occurs in the Kerberos database, the AS generates a random session key and a Ticket-Granting Ticket (TGT). The TGT contains a variety of information, including the client name and associated IP address, a validity date, a timestamp, and the session key.

Kerberos encodes the TGT with a key that only the Authentication Server and the TGS know. In combination with the session key, the ticket is now sent to the client – not in the clear, of course, but encoded with a key generated from the client's password. After the client receives the AS response (the encoded TGT and session key), the user is prompted to enter her password. The password is converted into a key, which is then used to decode the TGTs that just arrived. The client saves the TGT in its credential cache and deletes the password the user entered from memory. Thanks to the TGT, the user can now prove her identity for the validity period of the ticket without needing to authenticate again by typing the password.

The user's identity has thus been verified by the TGT on the workstation side. If the user wants to access another network service, such as the LDAP server referred to earlier, the TGT needs to request another ticket from the KDC, but from the Ticket-Granting Server this time. This service ticket (ST) is issued for precisely the server for which the user requested it – in other words, the server needs to support access to the Generic Security Services API.

Requesting a service ticket is more complex. The client sends a request to the TGS. The request comprises the name of the server the client wants to access, an authenticator, and the stored TGT.

The authenticator comprises the client name, its IP address, and a timestamp (the current time on the client). The encrypted TGT is sent along with the authenticator to the Ticket-Granting Server. The authenticator is also encoded with the session key that the client received along with the TGT. The Ticket-Granting Server decodes the authenticator and the TGT and compares their content, the IP address by which the request was issued, and the current time. If everything matches, a new session key is generated for use by the client and the server that it wanted to access (e.g., the LDAP server) in future. This new session key is part of the service ticket that the Ticket-Granting Server issues, encrypts (with the TGT's own session key), and returns to the requesting client.

The game now starts again from scratch. The client receives the service ticket and passes it on to the required server (LDAP) to prove its identity. In addition to the service ticket, another authenticator is generated and sent to the server. If the ST and authenticator information match, the client is validated and thus authenticated without needing to authenticate against the server by providing a username and password.

The authenticator provides protection against an attacker sniffing a service ticket off the network and replaying it to a server to gain access later. An attack of this kind is known as a replay attack.

To ensure that the client is correctly authenticated, the time on all of the machines involved in the exchange must be set correctly. The easiest way to set the time is to use the Network Time Protocol (NTP).

Figure 1 again shows the procedure for a Kerberos session:

1. The client requests a TGT from the AS.

2. The AS issues this for the TGS and sends it back to the client.

3. The client requests a service ticket and sends the TGT to the TGS.

4. The TGS sends the ST back to the client.

5. The client sends the ST to the target server and authenticates it.

6. The target server authenticates the client.

States in a Kerberos session.
Figure 1: States in a Kerberos session.

The Kerberos Server

The Kerberos Server owns the database in which the principals are stored and thus needs to be very secure. You should never run any other services on the same machine. Principals exist for both users and Kerberos-based services and hosts. A principal has the following generic structure: primary/instance@REALM, where instance is optional and only used for grouping. For example, a user principal could look like this:

tscherf/admin@TUXGEEK.DE

An example of an LDAP server is:

ldap/tiffy.tuxgeek.de@TUXGEEK.DE

The realm holds all the principals in a certain zone and corresponds to the uppercase DNS domain name. Along with the principals, the user and service passwords are also stored in the database.

The server is fairly easy to configure. To do so, you enter the name of your Kerberos realm in /etc/krb5.conf and issue the kdb5_util create command to create the database in the /var/kerberos/krb5kdc directory.

The database is managed either locally with the kadmin.local tool or remotely with kadmin. This setup assumes that the KAdmin service is enabled on the KDC, and you also need a valid admin principal in the /var/kerberos/krb5kdc/kadm5.acl file.

When one of the management tools is called, it can issue an add_principal to add a new principal to the database – for example, add_principal -pw password tscherf.

The procedure is similar for a service or a workstation: add_principal -randkey ldap/ldap.tuxgeek.de or add_principal -randkey host/grobi.tuxgeek.de. The service principals must be known on the corresponding servers.

To allow this process to happen, you need to generate the service password from the Kerberos database by running the following command:

ktadd -k /etc/krb5.keytab host/tiffy.tuxgeek.de

Then you securely copy the /etc/krb5.keytab file to the computer hosting the service, with scp, for example. Then you need to specify this keytab file along with the service password in the configuration file for each Kerberos service. Kerberos services typically search for a file with the default name of /etc/krb5.keytab. After you launch the KDC by typing service krb5kdc start, the service is ready for operations.

To make sure the LDAP server accesses the Kerberos database to authenticate users, you will need to create a principal for it on the Kerberos server and copy it to the server. You can issue the following command:

kadmin.local: add_principal -randkey ldap/tiffy.tuxgeek.de
kadmin.local: ktadd -k  /tmp/ds.keytab ldap/tiffy.tuxgeek.de

After copying the /tmp/ds.key to the /etc/dirsrv directory, you also need to tell the server the path to the file:

echo "KRB5_KTNAME=/etc/dirsrv/ ds.keytab; export KRB5_KTNAME" >> /etc/sysconfig/dirsrv

After rebooting the server, users can now use Kerberos to log in to the server (Listing 3). They need a matching TGT to do so, of course. Without this current configuration, they would need to request this manually from the KDC with kinit. When it accesses a Kerberos service, each client requests a service ticket for the requested service in the background. The service ticket is then used for authentication.

Listing 3: Kerberos Session Establishment

01 # kinit tscherf
02 Password for tscherf@TUXGEEK.DE:
03
04 # klist -5
05 Ticket cache: FILE:/tmp/krb5cc_500
06 Default principal: tscherf@TUXGEEK.DE
07
08 Valid starting     Expires            Service principal
09 08/06/10 15:41:50  08/07/10 15:41:50  krbtgt/TUXGEEK.DE@TUXGEEK.DE
10    renew until 08/06/10 15:41:50
11
12 # ldapsearch -LLL -h localhost -b "dc=tuxgeek,dc=de" uid=tscherf
13 SASL/GSSAPI authentication started
14 SASL username: tscherf@TUXGEEK.DE
15 SASL SSF: 56
16 SASL data security layer installed.
17 dn: uid=TScherf,ou=People,dc=tuxgeek, dc=de
18 givenName: Thorsten
19 sn: Scherf
20 loginShell: /bin/bash
21 uidNumber: 9999
22 gidNumber: 9999
23 objectClass: top
24 objectClass: person
25 objectClass: organizationalPerson
26 objectClass: inetorgperson
27 objectClass: posixAccount
28 uid: tscherf
29 cn: Thorsten Scherf
30 homeDirectory: /home/tscherf
31
32 # klist -5
33 Ticket cache: FILE:/tmp/krb5cc_500
34 Default principal: tscherf@TUXGEEK.DE
35
36 Valid starting     Expires            Service principal
37 08/06/10 15:41:50  08/07/10 15:41:50  krbtgt/TUXGEEK.DE@TUXGEEK.DE
38    renew until 08/06/10 15:41:50
39 08/06/10 15:43:20  08/07/10 15:41:50  ldap/tiffy.tuxgeek.de@TUXGEEK.DE
40    renew until 08/06/10 15:41:50

Depending on the directory server you use, you need to make sure that the mapping between the Kerberos principal for the user and the matching distinguished name (DN) on the LDAP server is correct. A plugin exists to handle this on the 389 Directory Server.

To allow a user to log in to a workstation using LDAP and Kerberos, you need to modify the configuration files for the PAM and NSS subsystems. PAM configuration files are typically in the /etc/pam.d directory, and NSS uses the /etc/nsswitch.conf file.

The system-config-authentication tool is useful for configuring these files (Figure 2), and it also takes care of the required configuration changes.From now on, the PAM pam_krb5.so library will validate the user's password. The Name Service Switch uses libnss_ldap.so to query the user data on the LDAP server. When a user logs in to the system, a Kerberos TGT is issued, which can be used later for password-free access to other Kerberos services.

The system-config-authentication tool facilitates the PAM and NSS subsystem changes.
Figure 2: The system-config-authentication tool facilitates the PAM and NSS subsystem changes.

If the computer is always connected with the network, the procedure I have looked at thus far will work without any problems; any client can connect to any server (Figure 3). Problems begin when one of the two server systems – or, in the worst case, both systems – is unreachable, which can happen if the workstation happens to be a laptop.

Client systems establish independent connections to the server systems.
Figure 3: Client systems establish independent connections to the server systems.

While connected to the enterprise network, a user can log in with his company account, but if the user is on the road, he will not be able to use this account. For precisely this reason, many users create a second, local account for mobile use of their devices. However, the fairly recent System Security Services Daemon (SSSD) removes the need for this step.

FreeIPA

SSSD is part of the FreeIPA Project [2] but also exists as a separate tool. Fedora 11 had an early version of it on board, and the current versions are now used. Users on other distributions can install the service using the package manager or download the source code for the tool directly from the project homepage [3].

SSSD provides various functions, three of which are really interesting. First, the tool solves the offline authentication issue for users. SSSD keeps the credentials for a centralized server in a local cache to do so. When a user logs in to an enterprise network with a company account on his laptop, the credentials are automatically stored in the SSSD cache. You can configure the retention period in a centralized configuration file.

Second, SSSD supports queries to multiple LDAP or NIS servers. Thus, you can query a number of different user databases. From a performance point of view, using the new daemon offers some obvious advantages. Instead of needing to set up a connection to query each LDAP server, now only a single socket from SSSD to the LDAP server is required.

Third, the daemon has its own NSS and PAM interfaces for requesting client systems (Figure 4). On the back end, security providers handle access to the corresponding identity or authentication servers. If they are unreachable, the cache is checked for existing credentials.

SSSD provides a local interface to the PAM and NSS subsystems.
Figure 4: SSSD provides a local interface to the PAM and NSS subsystems.

Again, the easiest way to configure the service is to use the system-config-authentication tool (Figure 5). FreeIPA is required as the user database, and a Kerberos server is required for authentication. The PAM configuration file (Listing 4) now uses pam_sss.so instead of pam_krb5.so. This tool also handles access to the PAM interface in SSSD. To make sure that the NSS docks with the interface intended for it, the configuration tool creates an sssd entry for the user database in /etc/nsswitch.conf.

Listing 4: PAM Configuration for SSSD

01 /etc/pam.d/system-auth
02 auth        required      pam_env.so
03 auth        sufficient    pam_unix.so nullok try_first_pass
04 auth        requisite     pam_succeed_if.so uid >= 500 quiet
05 auth        sufficient    pam_sss.so use_first_pass
06 auth        required      pam_deny.so
07
08 account     required      pam_unix.so broken_shadow
09 account     sufficient    pam_localuser.so
10 account     sufficient    pam_succeed_if.so uid < 500 quiet
11 account     [default=bad success=ok user_unknown=ignore] pam_sss.so
12 account     required      pam_permit.so
13
14 password    requisite     pam_cracklib.so try_first_pass retry=3
15 password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
16 password    sufficient    pam_sss.so use_authtok
17 password    required      pam_deny.so
18
19 session     optional      pam_keyinit.so revoke
20 session     required      pam_limits.so
21 session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
22 session     required      pam_unix.so
23 session     optional      pam_sss.so
The system-config-authentication tool is also useful for SSSD configuration tasks.
Figure 5: The system-config-authentication tool is also useful for SSSD configuration tasks.

In the /etc/sssd/sssd.conf configuration database for SSSD, you will see the individual sections for NSS and PAM (Listing 5). The global sssd contains the settings for the service itself. The domains keyword controls access to multiple user databases, which are then defined by configuration options. The man page man 5 sssd.conf provides a comprehensive overview of the available configuration options.

Listing 5: SSSD Configuration File

01 [sssd]
02 config_file_version = 2
03 reconnection_retries = 3
04 sbus_timeout = 30
05 services = nss, pam
06 domains = tuxgeek
07
08 [nss]
09 filter_groups = root
10 filter_users = root
11 reconnection_retries = 3
12
13 [pam]
14 reconnection_retries = 3
15
16 [domain/tuxgeek]
17 auth_provider = krb5
18 cache_credentials = True
19 ldap_id_use_start_tls = False
20 debug_level = 0
21 enumerate = True
22 krb5_kpasswd = tiffy.tuxgeek.de
23 ldap_schema = rfc2307bis
24 ldap_search_base = dc=tuxgeek,dc=de
25 krb5_realm = TUXGEEK.DE
26 chpass_provider = krb5
27 id_provider = ldap
28 ldap_uri = ldap://127.0.0.1/
29 krb5_kdcip = tiffy.tuxgeek.de
30 ldap_tls_cacertdir = /etc/openldap/cacerts

Conclusions

The use of the System Security Services Daemon offers huge benefits, especially for mobile users. Instead of working with different accounts, users can work with a single account. In offline mode, user credentials are supplied from the cache. This function is also useful in data centers to help bridge the gap cause by a temporary failure of an LDAP or Kerberos server. Compared with the Name Service Cache Daemon, SSSD offers far more granular management of the cache entries, and (in the default configuration) the cache entries will not become invalid while a user is offline.