Kerberos V5 Credentials Cache DLL draft specification

Last modified 1/27/96 by Theodore Ts'o

This document may be found at http://web.mit.edu/tytso/www/krb5-ccache-proposal.html.

This is a draft specification for a DLL which provides Credentials Cache services for Kerberos V5. The idea behind this DLL is that multiple Kerberos V5 implementations under Windows can share a single Credentials Cache, mediated by this DLL interface specification. This will allow single-signon, even when more than one Kerberos V5 DLL is in use on a particular system. Ideally, this problem could be solved by standardizing the Kerberos V5 API library interface. However, the Kerberos API is complicated enough that this would be hard to accomplish. Standardizing the interface for credentials cache access is much simpler.

Type definitions

typedef struct _cc_creds {
    char *client;		/* client's principal identifier */
    char *server;		/* server's principal identifier */
    cc_data 	keyblock;	/* session encryption key info */
    cc_time_t	authtime;
    cc_time_t	starttime;
    cc_time_t	endime;
    cc_time_t	renew_till;
    int is_skey;			/* true if ticket is encrypted in
					   another ticket's skey */
    cc_int32 ticket_flags;		/* flags in ticket */
    cc_data FAR * FAR *addresses;	/* addrs in ticket */
    cc_data ticket;			/* ticket string itself */
    cc_data second_ticket;		/* second ticket, if related to
					   ticket (via DUPLICATE-SKEY or
					   ENC-TKT-IN-SKEY) */
    cc_data FAR * FAR *authdata;	/* authorization data */
} cc_creds;

typedef struct _cc_data {
    cc_int32 type;
    int length;
    unsigned char FAR *data;
} cc_data;

typedef cc_int32 cc_time_t;

The cc_data structure

The cc_data structure is used to store the following elements:

For cc_creds.ticket and cc_creds.second_ticket, the cc_data.type field MUST be zero. For the cc_creds.addresses, cc_creds.authdata, and cc_data.keyblock, the cc_data.type field should be the address type, authorization data type, and encryption type, as defined by the Kerberos V5 protocol definition.

cc_time_t

The cc_time_t fields are used to represent time. The time should be stored as the number of seconds since midnight GMT on January 1, 1970.

Principal names

Principal names are stored as C strings in this API. The C strings may contain UTF-8 encoded strings for internationalization purposes.

Error Codes Definition

0CC_NOERROR "Successful return"
1CC_BADNAME "Bad credential cache name format"
2CC_NOTFOUD "Matching credential not found"
3CC_END "End of credential cache reached"
4CC_IO "Credentials cache I/O operation failed"
5CC_WRITE "Error writing to credentials cache file"
6CC_NOMEM "No memory"
7CC_FORMAT "Corrupted credentials cache"
8CC_LOCKED "The credentials cache is locked"
9CC_BAD_API_VERSION "Unsupported API version"
10CC_NO_EXIST "Credentials cache does not exist"
11CC_NOT_SUPP "Function not supported"

Function definitions

cc_initialize

cc_initialize(void **cc_ctx, int api_version, int *api_supported, char **vendor)

This function performs any initialization required by the DLL. It must be called before any other functions in the DLL is called. The cc_ctx returned by this function should be passed to all other DLL functions as the first argument.

The api_version field must be CC_API_VER_1 (which is #defined to be 1).

If api_supported non-NULL, then cc_initialize shall store the maximum API version number supported by the application there.

If the vendor is non-NULL, then cc_initialize shall store a pointer to a read/only C string which contains a string describing the vendor which implemented the credentials cache DLL.

Possible error codes: CC_NOMEM, CC_BAD_API_VERSION

cc_shutdown

cc_shutdown(void *cc_ctx)

This function performs any cleanup required by the DLL. No DLL functions should be called with the passed-in cc_ctx argument after this function returns. The application prorgram must call cc_initialize() again before making any credentails cache DLL calls.

Possible error codes: none

cc_open

cc_open(void *cc_ctx, char *name, int cc_flags, void **handle)

Opens an already credentials cache named name, and fills in the parameter **handle with a handle to the credentials cache.

Possible error codes: CC_BADNAME, CC_NO_EXIST, CC_NOMEM

cc_create

cc_create(void *cc_ctx, char *name, char *principal, int cc_flags, void **handle)

Create a new credentials cache; if the name is NULL, create it with a unique name. If name is non-null and there is already a credentials cache named name, the old credentials cache is destroyed and a new one created with that name. The credentials cache is created with a primary principal specified by principal.

Possible error codes: CC_BADNAME, CC_NOMEM

cc_close

cc_close(void *cc_ctx, void *handle)

Close the credentials cache. The handle is dellocated, and is no longer valid after this call returns.

Possible error codes: none

cc_destroy

cc_destroy(void *cc_ctx, void *handle)

Destroy the credentials cache pointed to by handle. The handle is dellocated, and is no longer valid after this call returns.

Possible error codes: none

cc_store

cc_store(void *cc_ctx, void *handle, cc_creds *creds)

Store cred into the ccache pointed to by handle.

Possible error codes: none

cc_get_principal

cc_get_principal(void *cc_ctx, void *handle, char **principal)

Return the primary principal for the credentials cache. The principal should be freed using the call cc_free_principal

Possible error codes: CC_NOMEM

cc_seq_fetch

cc_seq_fetch(void *cc_ctx, void *handle, cc_creds * creds, void **cursor)

cc_seq_fetch is used to sequentially read every set of cached credentials. It requires that handle identify a valid credentials cache. Cursor should be a pointer to a void * variable provided by the calling application and which is used by cc_seq_fetch to determine the next cached credential to return. To fetch the first cached credentials, the void * variable should be initialized to NULL.

The credentials are filled into the cc_creds structure pointed to by creds. Note that the credentials structure contains elements which are dynamically allocated which must be freed using cc_free_creds.

When the calling application is finished with a sequential scan of the credentials cache, it should call cc_seq_fetch one last time with the creds set to NULL. This will instruct cc_seq_fetch to invalidate cursor and free any memory associated with the cursor. This is also implicitly done when cc_seq_fetch returns the CC_END error.

Possible error codes: CC_NOMEM, CC_END

cc_remove_cred

cc_remove_cred(void *cc_ctx, void *handle, cc_creds *cred)

Removes the credential cred from handle. It is legitimate to call this function during a sequential fetch, and the deletion of a credential already returned by cc_seq_fetch() should not disturb sequence of credentials returned by cc_seq_fectch.

cc_lock_request

cc_lock_request(void *cc_ctx, void *cc_ctx, void *handle, int lock_type)

This function will lock or unlock the credentials cache based on the argument value of lock_type:

	CC_LOCK_UNLOCK	1	Unlock the credentials cache
	CC_LOCK_READER	2	Lock the credentials cache for reading
	CC_LOCK_WRITER	3	Lock the credentials cache for writing

	CC_LOCK_NOBLOCK	16	Don't block, but return an error code if
				the request cannot be satisfied.

Locking is done on a per-thread basis. At most one thread may have the credentials locked for writing; if so, there must not be any threads which have the credentials locked for reading.

Multiple threads may have the cache locked for reading, as long as there is not a writer lock asserted on the cache.

If a thread has a cache locked for reading, that lock may be upgraded to a writer lock by calling cc_lock_request() with a lock_type of CC_LOCK_WRITER. If a thread has the cache lcoked for reading or writing, a request to cc_lock_request() for a reader or writer lock, respectively, is a no-op. If a thread does not have the cache locked, and calls cc_lock_request with a lock_type of CC_LOCK_UNLOCK, this is also a no-op.

A request for CC_LOCK_READER and CC_LOCK_WRITER may be made non-blocking by logical or'ing the value CC_LOCK_NOBLOCK. In that case, if it is not possible to satisfy the lock request, the error CC_LOCKED will be returned.

cc_free_principal

cc_free_principal(void *cc_ctx, char *principal)

This function frees the principal returned by cc_get_principal.

cc_free_creds

cc_free_creds(void *cc_ctx, cc_creds *creds)

This function frees the creds returned by cc_seq_fetch.