incomplete.io

kerberos basics

principals

Kerberos identifies entities on a network by a principal or principal name. A client principal identifies the consumer of a service. This is typically an interactive user, but doesn't have to be. A service principal (or Server Principal) identifies a Kerberised service to be used by a client principal.

Principals are typically represented by well-formed strings to users, and are split into a number of components over the wire and by most Kerberos libraries. Specifically:

  1. Client Principals are made up of a username component and the realm name. In human-readable string form, these two components are joined with an '@' character. For example, the user bob in the INCOMPLETE.IO realm would look like this: bob@INCOMPLETE.IO.
  2. Service Principals are made up of a well-known service type component, a service name (typically a DNS resolvable name) and the realm name. In human-readable string form, the service type comes first, followed by a '/', the service name, an '@' and then the realm name. For example, the HTTP service on the host www.incomplete.io in the INCOMPLETE.IO realm would likely look like this: HTTP/www.incomplete.io@INCOMPLETE.IO.

Note that in this case, the DNS domain name (incomplete.io) matches the Kerberos realm name (INCOMPLETE.IO). This will often be the case, but is also not guaranteed to be in all deployments.

basic kerberos exchanges

The most common Kerberos exchange is for a client principal to authenticate itself in order to make use of a service that supports Kerberos. That process, oversimplified, is as follows. More specific detail can be found in RFC 4120, but for most, the Kerberos library implementation will take care of the details.

  1. The Client requests an initial ticket from a Kerberos KDC (including Active Directory Domain Controllers). The client's key is used to encrypt part of the request, which is ultimately how the user is authenticated by the KDC. The key is usually in the form of a user's password, but can also be things like a certificate or smart card.
  2. The KDC responds with an encrypted Ticket Granting Ticket (TGT), which contains a portion that can be decrypted by the client and a portion that can be decrypted by all of the KDCs in that realm. The client caches the TGT.
  3. The Client wishes to access a remote, Kerberised service at a later point in time. It may perform a number of DNS lookups on the service hostname (www.incomplete.io in the example above), including A and AAAA records to resolve the name to an IP address, and also potentially resolving that IP address back to a name in a process called canonicalisation (see below).
  4. The Client then requests a Service Ticket from the KDC using the TGT cached earlier. This service ticket request includes the service principal of the service the client wishes to authenticate against. Using the example above, that would be HTTP/www.incomplete.io@INCOMPLETE.IO.
  5. The KDC then finds a stored, encrypted key that matches the server principal. This is done in a KDC-specific fashion. See the section on Server Principal Resolution below. If found, it generates a service ticket with a part that can be decrypted by the client and a part that may only be decrypted with the service's key. The client will typically also caches this key.
  6. The client will then encapsulate this in whichever application-specific manner is appropriate. For example the ticket may be wrapped in GSSAPI and SPNEGO headers and be delivered in a HTTP Negotiate header for HTTP, or an SMB Session Setup request.
  7. On receipt of the service ticket, the service will decrypt its encrypted portion of the ticket using its local copy of its encrypted key. For many implementations, this may be an encrypted key stored in a Kerberos keytab file (see below). By decrypting this portion, the service can be confident that the ticket was generated by the KDC for that specific client and that the client was authenticated by the KDC.
  8. In some KDC implementations, extra access control information may be present within the service's encrypted portion of the ticket called the PAC. In the specific case of Active Directory, this may contain a LogonInfo structure that contains group membership information and claims-based authentication information that may be used to make access control decisions.
  9. The service will often then respond with a token encrypted with the session key of the service ticket, which the client can then use to perform Mutual Authentication.

At this point, the service and the client can both be confident that the client and the service have both been verified by the mutually-trusted KDC. This does not necessarily mean that the client is able to access resources within the service. That is where the service will generally do access control checks based on factors such as client principal group membership.

key versioning and keytab files

Most of the tickets issued by a KDC will have a relatively long life of hours or days. It is common practice for a service to change its Kerberos key periodically. Microsoft Windows, for example, defaults to changing its key every 30 days.

If a client has a valid, cached ticket that was encrypted with the old key and the service has changed its key, the service will not be able to validate any incoming requests with the existing ticket unless it has also kept a copy of the previous key. The service will generally respond with a generic authentication error and the client will generally not know to request a new ticket encrypted with the new key. It is also possible that that new key has not yet been replicated to the KDC that the client requests the ticket from.

Every ticket has a key version number that indicates which key was used to encrypt the ticket. Most services will keep the current-version key and the previous version key.

Many Kerberos implementations support providing the service with its key(s) stored in a Kerberos keytab file. These keytab files often contain these multiple versions of the key and often encrypted multiple times using different encryption types. Some examples of keytab file usage appears below.

canonicalisation

Some Kerberos implementations or deployments resolve hostnames to IP addresses (DNS CNAME, A and AAAA records) and those IP addresses back to a hostname (DNS PTR records) in a process called canonicalisation. This allows the use of DNS aliases for a host or cluster of hosts without having to manage multiple service principals within the KDC and the services themselves.

For example, the hostname www.incomplete.io might be an A record that points to the IP address 192.0.2.1. For the sake of intuitiveness for end users, the same host may have another name, say mail.incomplete.io, that resolves to the same IP address and represents one of more mail services on the same host.

With canonicalisation, the client requesting access to a Kerberised service will resolve the provided name to an its IP address, and then resolve that IP address to a unique name, such as b96e8485c65d.docker.incomplete.io. This name is the one that will appear in the service principal when the client makes the request for a service ticket and is therefore the only name and key that the KDC and the server need know about. The imap and www aliases never enter the picture (as far as Kerberos is concerned).

That said, a lot of deployments don't have accurate reverse DNS records, in which case canonicalisation isn't something to be relied upon.

server principal resolution

In the case of many Kerberos implementations such as Heimdal or MIT, the server principal is specified when the key is stored on the KDC.

In the case of Active Directory, the key is stored within the Active Directory object representing the service (often a Computer object). The server principal is stored in the servicePrincipalName (SPN) multi-value attribute. Aliases for a given principal may be added for multiple services against the same key/account simply by adding more SPNs.

Active Directory also has support for an sPNMappings attribute, which allows wildcards for many common services to be mapped to a generic per-object SPN. This is detailed later.

hands-on

TODO

  1. Key versioning
  2. Common errors: client/server not found, clock skew, unable to decrypt ticket
  3. Hands-on: kinit, klist, keytab, wireshark and PAC
Twitter: @IncompleteIO