logo_kerberos.gif

Projects/Keytab initiation

From K5Wiki
< Projects
Revision as of 23:20, 23 June 2012 by Ghudson (talk | contribs) (Code changes)

Jump to: navigation, search
This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.


This project is to add support for automatically getting credentials for gss-krb5 security context initiation using a keytab.

Overview

To initiate a gss-krb5 security context, one needs credentials (typically a TGT). During a user login session, these credentials are typically obtained ahead of time by the login system or using kinit (or on Windows or OSX, by bringing up a UI prompt from inside the GSSAPI functions). When a service wishes to communicate with another service, it uses its keytab to acquire credentials. Currently, it is necessary to use kinit -k or k5start out of band in order to ensure that credentials are available for the server's use. This project is to automate this process within the GSSAPI calls.

Requirements

  1. The system should work, perhaps with some external configuration, for a typical caller which invokes gss_init_sec_context() with no initiator cred (or, equivalently, acquires an initiator cred with no desired name).
  2. The system should also behave as well as possible when the caller does supply a desired name, or when krb5_cc_select() can deduce a client principal from the target name. In this case, multiple principals from the same keytab might be used for different initiations.
  3. The system should work well with credential cache collections (see Projects/Client_principal_selection). For example, an application should be able to, from the same process, initiate two security contexts with different desired names, using the same keytab, and have the resulting credentials both be cached within the collection (assuming the default ccache is collection-enabled).
  4. There should be minimal or no surprise. An existing deployment of GSSAPI applications should not begin doing keytab-based initiation and write to the default per-uid ccache without reason to believe this is intended.
  5. Credentials obtained this way should be cached. Otherwise, applications which initialize many security contexts (such as HTTP clients) could generate large numbers of unnecessary AS and TGS requests.

It is not required for this system to work with initiators like krlogin which directly use libkrb5. However, some of the underlying components may be useful for FAST armor ccaches, so putting reusable parts of the code in libkrb5 is desirable.

Design

Default client keytab

libkrb5 provides an API for discovering the default keytab (krb5_kt_default()). The underlying mechanism for discovering this keytab may be an environment variable (KRB5_KTNAME), a profile relation (default_keytab_name under libdefaults), or a hardcoded default (/etc/krb5.keytab). This keytab is currently used, absent application input the contrary, for accepting security contexts with gss_accept_sec_context or krb5_rd_req.

Automated keytab initiation will not make use of this keytab. Instead, there will be a new complementary "default client keytab", obtained with krb5_kt_client_default(), with its own set of underlying discovery mechanisms. Unless an administrator sets up a client keytab, automated keytab initiation will not take place, thus minimizing surprise.

(TBD: what discovery mechanisms do we need? Candidates include a revised version of gss_krb5_import_cred with a client keytab argument, a GSS extension parallel to krb5_gss_register_acceptor_identity, a URN for Projects/Credential_Store_extensions, an environment variable parallel to KRB5_KTNAME, a profile relation parallel to default_keytab_name, and a hardcoded default.)

Caching and refreshing

Initial credentials obtained through automated keytab initiation will be cached in the default ccache or, if the default ccache type supports it, the associated collection. The new ccache will remember, using ccache config entries, the time of the last attempt to refresh credentials from the client keytab (or a distinguished value if there has been no attempt yet). The gss-krb5 initiator code will attempt to refresh the cache with the keytab again if (1) the credentials are at least halfway to being expired, and (2) the last recorded attempt to refresh the cache was more than a minimum delta of time in the past.

Code changes

Introducing a client keytab requires a careful re-evaluation of the lifetime of an initiator credential, which has three or four stages:

  1. acquire_init_cred, called from gss_acquire_cred, records the information given by the caller (which may include client principal, ccache, client keytab, and/or password), infers a ccache from the supplied client principal or vice versa if either is given, detects errors based on the information supplied, and acquires initial credentials if necessary and possible. If neither client principal nor ccache was specified, resolution of the client principal is deferred until the next stage.
  2. kg_cred_resolve, called from gss_init_sec_context or gss_inquire_cred, forces resolution of the client principal, krb5_cc_select if the target principal is known. A ccache is then chosen if necessary, and initial credentials acquired if necessary and possible.
  3. If the IAKERB mechanism was requested, iakerb_get_initial_state sets up an AS request for getting initial credentials or a TGS request for the service ticket.
  4. get_credentials, called from gss_init_sec_context, gets a service ticket from the ccache (making a TGS request if necessary, in the non-IAKERB case).

The client principal is determined by, in order of preference:

  • (Stage 1) The caller's desired_name parameter if given.
  • (Stage 1) The principal of the caller-specified ccache, if it is initialized.
  • (Stage 2) The principal determined by krb5_cc_select using the target principal.
  • (Stage 2) The principal of the default ccache, if it exists.
  • (Stage 1 or 2) The first principal listed in the client keytab, if we have one. (If we choose this, we need to re-check the collection for an existing ccache for this principal.) This choice is used in stage 1 if the caller specifies an uninitialized ccache and no client principal, since it is not possible to use the cache collection in that case.
  • Give up and return an error

If it necessary to choose a ccache based on the client principal, the following methods are used in order of preference. An uninitialized ccache is only chosen if we detect that we can acquire initial credentials for the client principal, either with a caller-supplied password or with the client keytab.

  • An existing ccache in the collection for the client principal.
  • The uninitialized default cache, if it is not collection-enabled or if credentials are to be obtained by password.
  • A new unique ccache within the collection.

We return an error in stage 1 or 2 if:

  • Client principal and ccache are caller-specified, and ccache contains creds for a different principal
  • Client principal is known, there is a default ccache which is not collection-enabled, and it contains creds for a different principal
  • Client principal is known, there are no creds available for it in the collection (or caller-specified ccache), and we have no way to acquire creds for it
  • ccache is known but is empty, and we have no way to acquire creds
  • There are no creds at all in the collection and we have no way to acquire creds for any principal

Initial credentials are acquired in stage 1 or 2, after the client principal and ccache are known, if:

  • ccache contains a config variable indicating that it was derived from the client keytab, and it is time for a refresh. (If this fails, we will continue on and try to use ccache if it contains current creds.)
  • ccache doesn't contain a current TGT and we have a password
  • ccache doesn't contain a current TGT and we have a client keytab containing a key for the client principal

(Note: as of krb5 1.10, getting initial credentials with a password is deferred until get_credentials, even if IAKERB is not in use. Heimdal does not defer this, and we will no longer defer this after the restructuring.)