Macintosh Development |
[Home]
[About Us]
[People]
[Information Systems]
[Kerberos for Macintosh]
[Applications]
[Miscellaneous Documentation]
Credentials Cache API v3 Specification |
- Abstract
- New in revision 6
- Constants
- Types and functions
- Implementation requirements
- Revision history
Abstract
This is the specification for an API which provides Credentials Cache services for both Kerberos v5 and v4. The idea behind this API is that multiple Kerberos implementations can share a single collection of credentials caches, mediated by this API specification. On the Mac OS and Microsoft Windows platforms this will allow single-login, even when more than one Kerberos shared library is in use on a particular system.
Abstractly, a credentials cache collection contains one or more credentials caches, or ccaches. A ccache is uniquely identified by its name, which is a string internal to the API and not intended to be presented to users. The user presentable identifier of a ccache is its principal.
Unlike the previous versions of the API, version 3 of the API stores both Kerberos v4 and v5 credentials in the same ccache.
At any given time, one ccache is the "default" ccache. The exact meaning of a default ccache is OS-specific; refer to implementation requirements for details.
New in revision 7 (API Version 3 second draft)
March 11, 2000, by meeroh
- Opaque types are not pointers as the should have been
- Kerberos versions are now a bitfield
- Lock type agrument broken up
- Error constant explanations tweaked
- Added an example of changing and extending the API
- Specified API behavior on error returns
- Clarified
cc_context_open_default_ccache
- Fixed a bunch of typos and pasteos
- Moved API behavior specification near the top
- Added
cc_v4_key_length
- Added
skip
,clone
, andreset
to iterators- Added
clone
to ccaches- Changed iterators to lock the iteration object on creation and release it when released.
New in revision 6 (API Version 3 draft)
October 11, 1999, by meeroh
- Renamed "NCs" back to credentials caches. Despite good intentions on Steve's part, noone really called them NCs. Much better to rename the agglomerate object (now a "collection"), to which very few references are made.
- Renamed iterator functions for consistency
- Changed all opaque types to new consistent names and one fewer level of indirection
- Renamed most other types for consistency
- Added "Columbia special" string-to-key type (Columbia University has some weird case where they want to truncate the password at 8th character before hashing it with the MIT hash.)
- Changed the abstraction of a ccache to hold v4 and v5
- Added the default ccache API
- Changed the API to object-like approach to allow for easier future extensions
- Added
cc_context_get_version()
,cc_context_clone()
,cc_ccache_get_change_time
- Added specification for locking
- Added change time and default time accessors to ccaches
- Changed credentials removal to remove exact credentials
- Added
cc_ccache_move()
- Added
ccErrCCacheNotFound
errors to all ccache functionsAlso see the revision history for previous versions
Constants
CCache API version constants
// enums for API versions used in cc_initialize() enum { ccapi_version_2 = 2, ccapi_version_3 = 3 };These constants are passed into
cc_initialize()
to indicate the version of the API the caller wants to use.CCache API v1 and v2 are incompatible, and therefore the v1 version number has been removed. Clients shouldn't be using the v1 API.
Credentials versions constants
enum { cc_credentials_v4 = 1, // Kerberos v4 credentials cc_credentials_v5 = 2, // Kerberos v5 credentials cc_credentials_v4_v5 = cc_credentials_v4 | cc_credentials_v5 // Kerberos v4 and v5 credentials };These constants are used in several places in the API to discern between Kerberos v4 and Kerberos v5. Not all values are valid inputs and outputs for all functions; function specifications below detail the allowed values.
Kerberos version constants will always be a bit-field, and can be tested as such; for example:
if ((ccacheVersion & cc_credentials_v5) != 0) /* ccache has v5 credentials */
Lock types
enum cc_lock_type { cc_lock_read = 0, cc_lock_write = 1, cc_lock_block = 2, cc_lock_noblock = 3, };These constants are used in locking functions to describe the type of lock requested. Read locks, when granted, give the owner of the lock the ability to inspect the locked object. Write locks, when granted, give the owner of the lock the ability to modify the locked object. Attempting to acquire a lock with a non-blocking call will result in an error if the lock cannot be acquired; otherwise, the call will block until the lock can be acquired.
Error constants
0 ccNoError
Successful return 201 ccIteratorEnd
Iterator is done iterating 202 ccErrBadParam
Bad parameter (NULL or invalid pointer where valid pointer expected) 203 ccErrNoMem
Not enough memory to complete the operation 204 ccErrInvalidContext
Context is invalid (e.g., it was released) 205 ccErrInvalidCCache
CCache is invalid (e.g., it was released or destroyed) 206 ccErrInvalidString
String is invalid (e.g., it was released) 207 ccErrInvalidCredentials
Credentials are invalid (e.g., they were released), or they have a bad version 208 ccErrInvalidCCacheIterator
CCache iterator is invalid (e.g., it was released) 209 ccErrInvalidCredentialsIterator
Credentials iterator is invalid (e.g., it was released) 210 ccErrInvalidLock
Lock is invalid (e.g., it was released) 211 ccErrBadName
Bad credential cache name format 212 ccErrBadCredentialsVersion
Credentials version is invalid 213 ccErrBadAPIVersion
Unsupported API version 214 ccErrContextLocked
Context is already locked 215 ccErrContextUnlocked
Context is not locked by the caller 216 ccErrCCacheLocked
CCache is already locked 217 ccErrCCacheUnlocked
CCache is not locked by the caller 218 ccErrBadLockType
Bad lock type 219 ccErrNeverDefault
CCache was never default 220 ccErrCredentialsNotFound
Matching credentials not found in the ccache 221 ccErrCCacheNotFound
Matching ccache not found in the collection (either a name was supplied to a function, and no ccache with that name exists, or a cc_ccache_t
was supplied and the corresponding ccache has been destroyed).API behavior
Error handling
All functions of the API return some of the error constants listed above; the exact list of error constants returned by any API function is provided in the function descriptions below.
When returning an error constant other than
ccNoError
orccIteratorEnd
, API functions never modify any of the values passed in by reference.Synchronization and atomicity
Every function in the API is atomic. Every function acquires a lock before accessing any ccache or the collection, and releases the lock before returning; the scope of the lock is the smallest possible i.e. only as few individual ccaches as needed are locked; otherwise, the entire collection is locked. The restrictions of the lock are the narrowest possible, i.e. the lock is a read lock unless the ccache or the collection need to be modified.
Iterators, in addition to every function being atomic, iterate over ccacches or credentials atomically. That means that the caller is guaranteed that the set of ccaches or credentials that is iterated over will not change during the lifetime of the iterator (except as noted below). The lock is acquired when the iterator is created. The lock is released when the iterator is released. The lock is a reader lock, which means that if you intend to make modifications to the iteration set while iterating, you need to upgrade to a writer lock first.
The only case when the iteration set will be modified while the iterator is active is when the owner of the iterator makes modifications. The only guarantee made in this case is that deleting an element on the iteration set has no effect on which elements will be subsequently returned by the iterator (note that their order can be affected, however). This allows one to iterate over an iteration set and delete all its elements.
Locking implementation should not use copy-on-write techniques to implement locks, because those techniques imply that same parts of the ccache collection remain visible to some callers even though they are not present in the collection, which is a potential security risk. For example, a copy-on-write technique might make a copy of the entire collection when a read lock is acquired, so as to allow the owner of the lock to access the collection in an apparently unmodified state, while also allowing others to make modifications to the collection. However, this would also enable the owner of the lock to indefinitely (until the expiration time) use credentials that have actually been deleted from the collection.
Object lifetimes and management
The lifetime of an object returned by the API is until
release()
is called for it. Releasing one object has no effect on existence of any other object. For example, a ccache obtained within a context continue to exist when the context is released.Every object returned by the API (
cc_context_t
,cc_ccache_t
,cc_ccache_iterator_t
,cc_credentials_t
,cc_credentials_iterator_t
,cc_string_t
) is owned by the caller of the API, and it is the responsibility of the caller to callrelease()
for every object to prevent memory leaks.Platform-specific behaviors and requirements
Mac OS
It is an error to hold any lock across a call to
WaitNextEvent()
under Mac OS, whether the lock is explicit (acquired by callinglock()
) or implicit (acquired by an iterator or other API functions). If you do that, all your locks might be automatically unlocked, to allow other processes to access the cache. (In other words, blocking locks can't be used on Mac OS for inter-process synchronization.)Under Mac OS 7, 8, and 9, the default cache is maintained on a system-wide basis, since all the processes running on the machine have the same privileges anyway (the privileges of the currently logged in user).
For Mac OS X Server, see the UNIX section below.
MS Windows
DLLs should be named KrbCC16.dll and KrbCC32.dll.
The semantics of default ccaches under MS Windows are unspecified so far (will be fixed before final version of the API specification).
UNIX
The semantics of default ccaches on various variant of UNIX are unspecified so far (will be fixed before final version of the API specification).
Types and functions
Basic types
The
cc_int32
andcc_uint32
are the signed and unsigned 32-bit integer types.cc_uint32
isunsigned int
on platforms where4 <= sizeof (unsigned int) < sizeof (unsigned long)
andlong
on all other platforms.cc_int32
isint
on platforms where4 <= sizeof (int) < sizeof (long)
andlong
on all other platforms.typedef cc_int32 cc_time_t;The
cc_time_t
type is used to represent a time in seconds. The time must be stored as the number of seconds since midnight GMT on January 1, 1970.Opaque types
All of the opaque high-level types in CCache API are implemented as structures of function pointers and private data. To perform some operation on a type, the caller of the API has to first obtain an instance of that type, and then call the appropriate function pointer from that instance. For example, to call
get_change_time()
on acc_context_t
, one would callcc_initialize()
(which creates a newcc_context_t
) and then call itsget_change_time()
, like this:cc_context_t context; cc_int32 err = cc_initialize (&context, ccapi_version_3, nil, nil); if (err == ccNoError) time = context -> functions -> get_change_time (context)All API functions also have convenience preprocessor macros, which make the API seem completely function-based. For example,
cc_context_get_change_time (context, time)
is equivalent tocontext -> functions -> get_change_time (context, time)
. The convenience macros follow the following naming convention: the function callcc_type_t opaque_pointer; result = opaque_pointer -> functions -> somefunction (opaque_pointer, args)can be written using a convenience macro as:
cc_type_t opaque_pointer; result = cc_type_somefunction (opaque_pointer, args)The specifications below include the names for both the functions and the convenience macros, in that order. For clarity, it is recommended that clients using the API use the convenience macros, but that is merely a stylistic choice.
Implementing the API in this manner allows us to extend and change the interface in the future, while preserving compatibility with older clients.
For example, consider the case when the signature or the semantics of a
cc_ccache_t
function is changed. The API version number is incremented. The library implementation contains both a function with the old signature and semantics and a function with the new signature and semantics. When a context is created, the API version number used in that context is stored in the context, and therefore it can be used whenever a ccache is created in that context. When a ccache is created in a context with the old API version number, the function pointer structure for the ccache is filled with pointers to functions implementing the old semantics; when a ccache is created in a context with the new API version number, the function pointer structure for the ccache is filled with poitners to functions implementing the new semantics.Similarly, if a function is added to the API, the version number in the context can be used to decide whether to include the implementation of the new function in the appropriate function pointer structure or not.
cc_context_ttypedef struct { cc_int32 (*release) ( cc_context_t context); cc_int32 (*get_version) ( cc_context_t context, cc_int32* version); cc_int32 (*get_change_time) ( cc_context_t context, cc_time_t* time); cc_int32 (*get_default_ccache_name) ( cc_context_t context, cc_string_t* name); cc_int32 (*open_ccache) ( cc_context_t context, const char* name, cc_ccache_t* ccache); cc_int32 (*open_default_ccache) ( cc_context_t context, cc_ccache_t* ccache); cc_int32 (*create_ccache) ( cc_context_t context, const char* name, cc_int_32 cred_vers, const char* principal, cc_ccache_t* ccache); cc_int32 (*create_default_ccache) ( cc_context_t context, cc_int_32 cred_vers, const char* principal, cc_ccache_t* ccache); cc_int32 (*create_new_ccache) ( cc_context_t context, cc_int_32 cred_vers, const char* principal, cc_ccache_t* ccache); cc_int32 (*new_ccache_iterator) ( cc_context_t context, cc_ccache_iterator_t* iterator); cc_uint32 (*lock) ( cc_context_t context, cc_uint32 lock_type, cc_uint32 block); cc_uint32 (*unlock) ( cc_context_t context); } cc_context_f; typedef struct { const cc_context_f* functions; }* cc_context_t;The
cc_context_t
type gives the caller access to a ccache collection. Before being able to call any functions in the CCache API, the caller needs to acquire an instance ofcc_context_t
by callingcc_initialize
orcc_context_clone
. Thecc_context_t
type has the following functions:cc_initialize
cc_int32 cc_initialize ( cc_context_t* cc_context, cc_int32 api_version, cc_int32* api_supported, char** vendor)This function performs any initialization required by the API. It must be called before any other function in the API is called.
The application must pass in the maximum version number of the API it supports in the
api_version
parameter.If
api_supported
is non-NULL, thencc_initialize
will store the maximum API version number supported by the library implementing the API there.If the version requested by
api_version
is not equal to a version supported by the library,ccErrBadAPIVersion
will be returned as the error code (along with the version the library does support inapi_supported
) andcc_initialize()
will not allocate any memory.If
vendor
is non-NULL, thencc_initialize()
will store in*vendor
a pointer to a read-only C string which contains a string describing the vendor which implemented the credentials cache API.Possible return values:
ccNoError
,ccErrNoMem
,ccErrBadAPIVersion
,ccErrBadParam
cc_context_get_version
cc_int32 get_version ( cc_context_t cc_context, cc_int32* api_version) cc_int32 cc_context_get_version ( cc_context_t cc_context, cc_int32* api_version)This function returns the API version with which a context was initialized.
This is useful for cases where a context is passed between different pieces of code (an application and a library, for example), and the recipient of a context wants to ascertain that the context was initialized with the appropriate version of the API.
Possible return values:
ccNoError
,ccErrInvalidContext
,ccErrBadParam
cc_context_release
cc_int32 release ( cc_context_t cc_context) cc_int32 cc_context_release ( cc_context_t cc_context)This function releases the context and performs any cleanup required by the API.
Possible return values:
ccNoError
,ccErrInvalidContext
cc_context_get_change_time
cc_int32 get_change_time ( cc_context_t cc_context, cc_time_t* time) cc_int32 cc_context_get_change_time ( cc_context_t cc_context, cc_time_t* time)This function returns the time of the most recent change for the entire ccache collection. By maintaining a local copy the caller can deduce whether the ccache collection has been modified since the previous call to
cc_context_get_change_time()
or not.The time returned by
cc_context_get_changed_time()
increases whenever:
- a ccache is created
- a ccache is destroyed
- a credential is stored
- a credential is removed
- a ccache principal is changed
- the default ccache is changed
Possible return values:
ccNoError
,ccErrInvalidContext
,ccBadParam
cc_context_get_default_ccache_name
cc_int32 get_default_ccache_name ( cc_context_t cc_context, cc_string_t* name) cc_int32 cc_context_get_default_ccache_name ( cc_context_t cc_context, cc_string_t* name)This function returns the name of the default ccache. When the default ccache exists, its name is returned. If there are no ccaches in the collection, and thus there is no default ccache, the name that the default ccache should have is returned. The ccache with that name will be used as the default ccache by all processes which initialized Kerberos libraries before the ccache was created.
If there is no default ccache, and the client is creating a new ccache, it should be created with the default name. If there already is a default ccache, and the client wants to create a new ccache (as opposed to reusing an existing ccache), it should be created with any unique name;
cc_context_create_new_ccache()
can be used to accomplish that more easily.If the first ccache is created with a name other than the default name, then the processes already running will not notice the credentials stored in the new ccache, which is normally undesirable.
Possible return values:
ccNoError
,ccErrInvalidContext
,ccBadParam
,ccErrNoMem
cc_context_open_ccache
cc_int32 open_ccache ( cc_context_t cc_context, const char* name, cc_ccache_t* ccache) cc_int32 cc_context_open_ccache ( cc_context_t cc_context, const char* name, cc_ccache_t* ccache)Opens an already existing ccache identified by its name. It returns a reference to the ccache in
*ccache
.The list of all ccache names, principals, and credentials versions may be retrieved by calling
cc_context_new_cache_iterator()
,cc_ccache_get_name()
,cc_ccache_get_principal()
, andcc_ccache_get_cred_version()
.Possible error codes:
ccNoError
,ccErrBadName
,ccErrInvalidContext
,ccErrNoMem
,ccErrCCacheNotFound
,ccErrBadParam
cc_context_open_default_ccache
cc_int32 open_default_ccache ( cc_context_t cc_context, cc_ccache_t* ccache) cc_int32 cc_context_open_default_ccache ( cc_context_t cc_context, cc_ccache_t* ccache)Opens the default ccache. It returns a reference to the ccache in
*ccache
.This function performs the same function as calling
cc_context_get_default_ccache_name
followed bycc_context_open_ccache
, but it performs it atomically.Possible error codes:
ccNoError
,ccErrInvalidContext
,ccErrNoMem
,ccErrCCacheNotFound
,ccErrBadParam
cc_context_create_ccache
cc_int32 create_ccache ( cc_context_t cc_context, const char* name, cc_int32 cred_vers, const char* principal, cc_ccache_t* ccache) cc_int32 cc_context_create_ccache ( cc_context_t cc_context, const char* name, cc_int32 cred_vers, const char* principal, cc_ccache_t* ccache)Create a new credentials cache. The ccache is uniquely identified by its name. The principal given is also associated with the ccache and the credentials version specified. A NULL name is not allowed (and
ccErrBadName
is returned if one is passed in). Onlycc_credentials_v4
andcc_credentials_v5
are valid input values forcred_vers
. If you want to create a new ccache that will hold both versions of credentials, callcc_context_create_ccache()
with one version, and thencc_ccache_set_principal()
with the other version.If you want to create a new ccache (with a unique name), you should use
cc_context_create_new_ccache()
instead. If you want to create or reinitialize the default cache, you should usecc_context_create_default_ccache()
.If name is non-NULL and there is already a ccache named
name
:
- the credentials in the ccache whose version is
cred_vers
are removed- the principal (of the existing ccache) associated with
cred_vers
is set toprincipal
- a handle for the existing ccache is returned and all existing handles for the ccache remain valid
If no ccache named name already exists:
- a new empty ccache is created
- the principal of the new ccache associated with
cred_vers
is set toprincipal
- a handle for the new ccache is returned
For a new ccache, the name should be any unique string. The name is not intended to be presented to users.
If the created ccache is the first ccache in the collection, it is made the default ccache. Note that normally it is undesirable to create the first ccache with a name different from the default ccache name (as returned by
cc_context_get_default_ccache_name()
); see the description ofcc_context_get_default_ccache_name()
for details.The principal should be a C string containing an unparsed Kerberos principal in the format of the appropriate Kerberos version, i.e. foo.bar@BAZ for Kerberos v4 and foo/bar@BAZ for Kerberos v5.
Possible error codes:
ccNoError
,ccErrorBadName
,ccErrBadParam
,ccErrInvalidContext
,ccErrNoMem
,ccErrBadCredentialsVersion
cc_context_create_default_ccache
cc_int32 create_default_ccache ( cc_context_t cc_context, cc_int32 cred_vers, const char* principal, cc_ccache_t* ccache) cc_int32 cc_context_create_default_ccache ( cc_context_t cc_context, cc_int32 cred_vers, const char* principal, cc_ccache_t* ccache)Create the default credentials cache. The behavior of this function is similar to that of
cc_create_ccache()
. If there is a default ccache (which is always the case except when there are no ccaches at all in the collection), it is initialized with the specified credentials version and principal, as percc_create_ccache()
; otherwise, a new ccache is created, and its name is the name returned bycc_context_get_default_ccache_name()
.Possible error codes:
ccNoError
,ccErrBadName
,ccErrBadParam
,ccErrInvalidContext
,ccErrNoMem
,ccErrBadCredentialsVersion
cc_context_create_new_ccache
cc_int32 create_new_ccache ( cc_context_t cc_context, cc_int32 cred_vers, const char* principal, cc_ccache_t* ccache) cc_int32 cc_context_create_new_ccache ( cc_context_t cc_context, cc_int32 cred_vers, const char* principal, cc_ccache_t* ccache)Create a new unique credentials cache. The behavior of this function is similar to that of
cc_create_ccache()
. If there are no ccaches, and therefore no default ccache, the new ccache is created with the default ccache name as would be returned byget_default_ccache_name()
. If there are some ccaches, and therefore there is a default ccache, the new ccache is created with a new unique name. Clearly, this function never reinitializes a ccache, since it always uses a unique name.Possible error codes:
ccNoError
,ccErrBadName
,ccErrBadParam
,ccErrInvalidContext
,ccErrNoMem
,ccErrBadCredentialsVersion
cc_context_new_ccache_iterator
cc_int32 new_ccache_iterator ( cc_context_t cc_context, cc_ccache_iterator_t* iterator) cc_int32 cc_context_new_ccache_iterator ( cc_context_t cc_context, cc_ccache_iterator_t* iterator)Used to allocate memory and initialize
iterator
. Successive calls toiterator
'snext()
function will return ccaches in the collection.If changes are made to the collection while an iterator is being used on it, the iterator must return at least the intersection, and at most the union, of the set of ccaches that were present when the iteration began and the set of ccaches that are present when it ends.
Possible error codes:
ccNoError
,ccBadParam
,ccErrNoMem
,ccErrInvalidContext
cc_context_lock
cc_int32 lock ( cc_context_t context, cc_int32 lock_type, cc_int32 block) cc_int32 cc_context_lock ( cc_context_t context, cc_int32 lock_type, cc_int32 block)Attempts to acquire a lock for the ccache collection. Allowed values for
lock_type
are:
cc_lock_read
: if acquired, the lock is a read lock, and the owner of the lock is guaranteed that the context will not be modified until the lock is released.cc_lock_write
: if acquired, the lock is a write lock, and the owner of the lock is guaranteed that noone else will be allowed to inspect or modify the context until the lock is releasedIf
block
iscc_lock_block
,lock()
will not return until the lock is acquired. Ifblock
iscc_lock_noblock
,lock()
will return immediately, either acquiring the lock and returningccNoError
, or failing to acquire the lock and returningccErrContextLocked
.Attempting to acquire a write lock on a context that is already read-locked is allowed; if successful, the context acquires two different locks (a read and a write lock), which is the same as having just a write lock. To release them,
cc_lock_release()
should be called twice. If unsuccessful, the context still has one read lock.To avoid having to deal with differences between thread semantics on different platforms, locks are granted per context, rather than per thread or per process. That means that different threads of execution have to acquire separate contexts in order to be able to synchronize with each other.
The lock should be unlocked by using
cc_context_unlock()
.Possible error codes:
ccNoError
,ccErrContextLocked
,ccErrBadLockType
,ccErrInvalidContext
,ccErrNoMem
cc_context_unlock
cc_int32 unlock ( cc_context_t context); cc_int32 cc_context_lock ( cc_context_t context);Attempts to release a lock for the ccache collection.
The lock released is the last lock acquired on the context.
Possible error codes:
ccNoError
,ccErrContextUnlocked
,ccErrInvalidContext
,ccErrNoMem
cc_ccache_ttypedef struct { cc_int32 (*release) ( cc_ccache_t ccache); cc_int32 (*destroy) ( cc_ccache_t ccache); cc_int32 (*set_default) ( cc_ccache_t ccache); cc_int32 (*get_credentials_version) ( cc_ccache_t ccache, cc_int32* credentials_version); cc_int32 (*get_name) ( cc_ccache_t ccache, cc_string_t* name); cc_int32 (*get_principal) ( cc_ccache_t ccache, cc_int32 credentials_version, cc_string_t* principal); cc_int32 (*set_principal) ( cc_ccache_t ccache, cc_int32 credentials_version, const char* principal); cc_int32 (*store_credentials) ( cc_ccache_t ccache, const cc_credentials_union* credentials); cc_int32 (*remove_credentials) ( cc_ccache_t ccache, cc_credentials_t credentials); cc_int32 (*new_credentials_iterator) ( cc_ccache_t ccache, cc_credentials_iterator_t* iterator); cc_int32 (*lock) ( cc_ccache_t ccache, cc_uint32 lock_type, cc_uint32 block); cc_uint32 (*unlock) ( cc_ccache_t context); cc_int_32 (*get_last_default_time) ( cc_ccache_t ccache, cc_time_t* time); cc_int_32 (*get_change_time) ( cc_ccache_t ccache, cc_time_t* time); cc_int_32 (*move) ( cc_ccache_t source, cc_ccache_t destination); } cc_ccache_f; typedef struct { const cc_ccache_f* functions; }* cc_ccache_t;The
cc_ccache_t
type represents a reference to a ccache. Callers can access a ccache and the credentials stored in it via acc_ccache_t.
Acc_ccache_t
can be acquired viacc_context_open_ccache()
,cc_context_open_default_ccache()
, orcc_ccache_iterator_next()
. The functions in acc_ccache_t
are:cc_ccache_release
cc_int32 release ( cc_ccache_t ccache) cc_int32 cc_ccache_release ( cc_ccache_t ccache)Close the ccache reference. Memory associated with the ccache reference is deallocated; the ccache itself remains unchanged. The reference is invalid after being released.
Possible return values:
ccNoError
,ccErrInvalidCCache
cc_ccache_destroy
cc_int32 destroy ( cc_ccache_t ccache) cc_int32 cc_ccache_destroy ( cc_ccache_t ccache)Destroy the ccache referenced by the ccache reference. All credentials in the ccache are removed. The associated memory is deallocated. The reference itself is released at the same time, and is therefore invalid after the call to
cc_ccache_destroy()
.If the default ccache is destroyed, the ccache that was most recently default before it is made the default ccache, unless the default ccache was the only ccache in the collection; in that case, no ccache is made default, as there are no ccaches left.
Possible return values:
ccNoError
,ccErrInvalidCCache
,ccErrCCacheNotFound
cc_ccache_set_default_ccache
cc_int32 set_default ( cc_ccache_t ccache) cc_int32 cc_ccache_set_default ( cc_ccache_t ccache)Makes the ccache referenced the default ccache.
Possible return values:
ccNoError
,ccErrInvalidCCache
,ccErrCCacheNotFound
cc_cache_get_credentials_version
cc_int32 get_credentials_version ( cc_ccache_t ccache, cc_int32* credentials_version) cc_int32 cc_ccache_get_credentials_version ( cc_ccache_t ccache, cc_int32* credentials_version)
cc_get_credentials_version()
returns one value of the enumerated typecc_credentials_vers
. The possible return values arecc_credentials_v4
(if ccache's v4 principal has been set),cc_credentials_v5
(if ccache's v5 principal has been set), orcc_credentials_v4_v5
(if both ccache's v4 and v5 principals have been set). A ccache's principal is set with one ofcc_context_create_ccache()
,cc_context_create_new_ccache()
,cc_create_default_ccache()
, orcc_ccache_set_principal()
.Possible return values:
ccNoError
,ccErrInvalidCCache
,ccErrBadParam
,ccErrCCacheNotFound
cc_ccache_get_name
cc_int32 get_name ( cc_ccache_t ccache, cc_string_t* name) cc_int32 cc_ccache_get_name ( cc_ccache_t ccache, cc_string_t* name)
get_name()
returns the name of the ccache. The name can be used incc_context_open_ccache()
orcc_context_create_ccache()
. The name uniquely identifies a ccache. The returned name should be freed via thecc_string_release()
function.Possible error codes:
ccNoError
,ccErrNoMem
,ccErrBadParam
,ccErrInvalidCCache
,ccErrCCacheNotFound
cc_ccache_get_principal
cc_int32 get_principal ( cc_ccache_t ccache, cc_int32 cred_vers, cc_string_t* principal) cc_int32 cc_ccache_get_principal ( cc_ccache_t ccache, cc_int32 cred_vers, cc_string_t* principal)Return the principal for the ccache that was set via
cc_context_create_ccache()
,cc_context_create_default_ccache()
,cc_context_create_new_ccache()
, orcc_ccache_set_principal()
. The returned principal should be freed via thecc_string_release()
function. Principals for v4 and v5 are separate, but should be kept synchronized for each ccache; they can be retrieved by passingcc_credentials_v4
orcc_credentials_v5
incred_vers
. Passingcc_credentials_v4_v5
is an error (ccErrBadCredentialsVersion
).Possible error codes:
ccNoError
,ccErrNoMem
,ccErrBadCredentialsVersion
,ccErrBadParam
,ccErrInvalidCCache
,ccErrCCacheNotFound
cc_ccache_set_principal
cc_int32 set_principal ( cc_ccache_t ccache, cc_int32 cred_vers, const char* principal) cc_int32 cc_ccache_set_principal ( cc_ccache_t ccache, cc_int32 cred_vers, const char* principal)Set the a principal for
ccache
. The v4 and v5 principals can be set independently, but they should always be kept equal, up to differences in string representation between v4 and v5. Passingcc_credentials_v4_v5
incred_vers
is an error (ccErrBadCredentialsVersion
).
principal
points to a nul-terminated string that will be copied into the ccache. This new principal will be returned if you callcc_ccache_get_principal()
for this ccache.Possible error codes:
ccNoError
,ccErrNoMem
,ccErrInvalidCCache
,ccErrBadCredentialsVersion
,ccErrBadParam
,ccErrCCacheNotFound
cc_ccache_store_credentials
cc_int32 store_credentials ( cc_ccache_t ccache, const cc_credentials_union* credentials) cc_int32 cc_ccache_store_credentials ( cc_ccache_t ccache, const cc_credentials_union* credentials)Store a copy of
credentials
in the ccache.See the description of the credentials types for the meaning of
cc_credentials_union
fields.Before credentials of a specific credential type can be stored in a ccache, the corresponding principal version has to be set. I.e., before you can store Kerberos v4 credentials in a ccache, the Kerberos v4 principal has to be set either by
cc_context_create_ccache()
,cc_context_create_default_ ccache()
,cc_context_create_new_ccache()
, orcc_set_principal()
; likewise for Kerberos v5. Otherwise,ccErrBadCredentialsVersion
is returned.Possible error codes:
ccNoError
,ccErrInvalidCCache
,ccErrInvalidCredentials
,ccErrBadCredentialsVersion
,ccErrCCacheNotFound
cc_ccache_remove_credentials
cc_int32 remove_credentials ( cc_ccache_t ccache, cc_credentials_t credentials) cc_int32 cc_ccache_remove_credentials ( cc_ccache_t ccache, cc_credentials_t credentials)Removes
credentials
from a ccache. Note that credentials must be previously acquired from the CCache API; only exactly matching credentials will be removed. (This places the burden of determining exactly which credentials to remove on the caller, but ensures there is no ambigity about which credentials will be removed.)If found, the credentials are removed from the ccache. The
credentials
parameter is not modified and should be freed by the caller. It is legitimate to call this function while an iterator is traversing the ccache, and the deletion of a credential already returned bycc_credentials_iterator_next()
will not disturb sequence of credentials returned bycc_credentials_iterator_next()
.Possible error codes:
ccNoError
,ccErrInvalidCCache
,ccErrInvalidCredentials
,ccErrCredentialsNotFound
,ccErrCCacheNotFound
cc_ccache_new_credentials_iterator
cc_int32 new_credentials_iterator ( cc_ccache_t ccache, cc_creds_iterator_t* iterator) cc_int32 cc_cccache_new_credentials_iterator ( cc_ccache_t ccache, cc_creds_iterator_t* iterator)Allocates memory for
iterator
and initializes it. Successive calls tocc_credentials_iterator_next()
will return credentials from the ccache.If changes are made to the ccache while an iterator is being used on it, the iterator must return at least the intersection, and at most the union, of the set of credentials that were in the ccache when the iteration began and the set of credentials that are in the ccache when it ends.
Possible error codes:
ccNoError
,ccErrBadParam
,ccErrNoMem
,ccErrCCacheNotFound
cc_ccache_lock
cc_int32 lock ( cc_ccache_t ccache, cc_int32 lock_type, cc_uint32 block) cc_int32 cc_ccache_lock ( cc_ccache_t ccache, cc_int32 lock_type, cc_uint32 block)Attempts to acquire a lock for the ccache. Allowed values for
lock_type
are:
cc_lock_read
: if acquired, the lock is a read lock, and the owner of the lock is guaranteed that the ccache will not be modified until the lock is released.cc_lock_write
: if acquired, the lock is a write lock, and the owner of the lock is guaranteed that noone else will be allowed to inspect or modify the ccache until the lock is releasedIf
block
iscc_lock_block
,lock()
will not return until the lock is acquired. Ifblock
iscc_lock_noblock
,lock()
will return immediately, either acquiring the lock and returningccNoError
, or failing to acquire the lock and returningccErrCCacheLocked
.Attempting to acquire a write lock on a ccache that is already read-locked is allowed; if successful, the context acquires two different locks (a read and a write lock), which is the same as having just a write lock. To release them,
cc_lock_release()
should be called twice. If unsuccessful, the context still has one read lock.To avoid having to deal with differences between thread semantics on different platforms, locks are granted per context, rather than per thread or per process. That means that different threads of execution have to acquire separate contexts in order to be able to synchronize with each other.
The lock object is returned in the lock parameter, and should be unlocked by using
cc_lock_release()
.Possible error codes:
ccNoError
,ccErrCCacheLocked
,ccErrBadLockType
,ccErrNoMem
,ccErrCCacheNotFound
cc_ccache_unlock
cc_int32 unlock ( cc_ccache_t ccache); cc_int32 cc_ccache_lock ( cc_ccache_t ccache);Attempts to release a lock for the ccache.
The lock released is the last lock acquired on the ccache.
Possible error codes:
ccNoError
,ccErrCCacheUnlocked
,ccErrInvalidCCache
,ccErrNoMem
cc_ccache_get_change_time
cc_int32 get_change_time ( cc_ccache_t ccache, cc_time_t* time) cc_int32 cc_ccache_get_change_time ( cc_ccache_t ccache, cc_time_t* time)This function returns the time of the most recent change for the ccache. By maintaining a local copy the caller can deduce whether the ccache has been modified since the previous call to
cc_ccache_get_change_time()
or not.The time returned by
cc_ccache_get_changed_time()
increases whenever:
- the ccache is created
- a credential is stored
- a credential is removed
- a ccache principal is changed
- the ccache is made default or not-default
Possible return values:
ccNoError
,ccErrInvalidCCache
,ccBadParam
,ccErrCCacheNotFound
cc_ccache_get_last_default_time
cc_int32 get_last_default_time ( cc_ccache_t ccache, cc_time_t* time) cc_int32 cc_ccache_get_last_default_time ( cc_ccache_t ccache, cc_time_t* time)This function returns the last time when the ccache was made the default ccache. This allows clients to sort the ccaches by how recently they were default, which is useful for user listing of ccaches. If the ccache was never default,
ccErrNeverDefault
is returned.Possible return values:
ccNoError
,ccErrInvalidCCache
,ccBadParam
,ccErrNeverDefault
,ccErrCCacheNotFound
cc_ccache_move
cc_int32 move ( cc_ccache_t source, cc_ccache_t destination) cc_int32 cc_ccache_move ( cc_ccache_t source, cc_ccache_t destination)This function takes one ccache (the source) and moves all of its credentials and all of its principals to a different ccache (the destination). All the credentials in the destination are destroyed; both principals of the destination are reset to the corresponding principals of the source ccache.
Assuming that the ccaches are valid, the function cannot fail. This makes it extremely useful for callers that want to atomically and safely replace all the credentials in a ccache -- for example, to renew user's credentials. The new credentials can be placed in a new ccache, and when they are all available, atomically placed into the destination ccache.
All ccache handles for the source ccache, including the one passed to
cc_ccache_move()
, become invalid, just ascc_ccache_destroy
had been called.Any locks held on the source ccache are transferred to the destination ccache; this is okay because those locks must be held by the caller.
Possible return values:
ccNoError
,ccErrInvalidCCache
,ccErrCCacheNotFound
cc_ccache_iterator_ttypedef struct { cc_int32 (*release) ( cc_ccache_iterator_t iter); cc_int32 (*clone) ( cc_ccache_iterator_t iter, cc_ccache_iterator_t* new_iter); cc_int32 (*next) ( cc_ccache_iterator_t iter, cc_ccache_t* ccache); } cc_ccache_iterator_f; typedef struct { const cc_ccache_iterator_f* functions; }* cc_ccache_iterator_t;The
cc_ccache_iterator_t
type represents an iterator that iterates over a set of ccaches and returns them in all in some order. A new instance of this type can be obtained by callingcc_context_new_ccache_iterator()
. The type has the following functions:cc_ccache_iterator_release
cc_int32 release ( cc_ccache_iterator_t iterator) cc_int32 cc_ccache_iterator_release ( cc_ccache_iterator_t iterator)Deallocates the memory used by a ccache iterator.
Possible error codes:
ccNoError
,ccErrInvalidCCacheIterator
cc_ccache_iterator_clone
cc_int32 clone ( cc_ccache_iterator_t iter, cc_ccache_iterator_t* new_iter) cc_int32 cc_ccache_iterator_clone ( cc_ccache_iterator_t iter, cc_ccache_iterator_t* new_iter)Creates a new iterator by cloning an existing one.
Since the original iterator acquires a lock on the entire collection when it's created, the newly created iterator will always iterate over exactly the same set of ccaches. The newly created iterator will not return the ccaches that the original iterator had already returned, unless
cc_ccache_iterator_reset()
is called on the new iterator.Possible error codes:
ccNoError
,ccErrNoMem
,ccErrInvalidCCacheIterator
cc_ccache_iterator_next
cc_int32 next ( cc_ccache_iterator_t iterator, cc_ccache_t* ccache) cc_int32 cc_ccache_iterator_next ( cc_ccache_iterator_t iterator, cc_ccache_t* ccache)Used to sequentially open every ccache in the iteration set.
ccache
must be a pointer to acc_ccache_t
. The ccache returned may be used to get information about the ccache by callingcc_ccache_get_name()
,cc_ccache_get_cred_version()
, andcc_ccache_get_principal()
. CCaches returned must be released between or after calls tocc_ccache_iterator_next()
.When the last ccache in the sequence is returned, the return code from
next()
will beccIteratorEnd
.Possible error codes:
ccNoError
,ccIteratorEnd
,ccErrBadParam
,ccErrNoMem
,ccErrInvalidCCacheIterator
,ccErrCCacheNotFound
cc_credentials_iterator_ttypedef struct { void (*release) ( cc_credentials_iterator_t iterator); cc_int32 (*clone) ( cc_credentials_iterator_t iter, cc_credentials_iterator_t* new_iter); cc_int32 (*next) ( cc_credentials_iterator_t iterator, cc_credentials_t* ccache); } cc_credentials_iterator_f; typedef struct { const cc_credentials_iterator_f* functions; }* cc_credentials_iterator_t;The
cc_credentials_iterator_t
type represents an iterator that iterates over a set of credentials. A new instance of this type can be obtained by callingcc_ccache_new_credentials_iterator()
. The type has the following functions:cc_ccache_credentials_iterator_release
cc_int32 release ( cc_credentials_iterator_t iterator) cc_int32 cc_ccache_iterator_release ( cc_credentials_iterator_t iterator)Deallocates memory used by a credentials iterator.
Possible error codes:
ccNoErr
,ccErrInvalidCredentialsIterator
cc_credentials_iterator_clone
cc_int32 clone ( cc_credentials_iterator_t iter, cc_credentials_iterator_t* new_iter) cc_int32 cc_credentials_iterator_clone ( cc_credentials_iterator_t iter, cc_credentials_iterator_t* new_iter)Creates a new iterator by cloning an existing one.
Since the original iterator acquires a lock on the entire ccache when it's created, the newly created iterator will always iterate over exactly the same set of credentials. The newly created iterator will not return the credentials that the original iterator had already returned, unless
cc_credentials_iterator_reset()
is called on the new iterator.Possible error codes:
ccNoError
,ccErrNoMem
,ccErrInvalidCredentialsIterator
cc_credentials_iterator_next
cc_int32 next ( cc_credentials_iterator_t iterator, cc_credentials_t* credentials) cc_int32 cc_credentials_iterator_next ( cc_credentials_iterator_t iterator, cc_credentials_t* credentials)
cc_ccache_creds_iterator_t -> next()
is used to sequentially access a set of credentials. Both Kerberos v4 and v5 credentials are returned by the iterator; callers interested in only one kind need to check the version of the returned credentials and ignore the ones they don't care about.The credentials are returned in a
cc_credentials_t
pointed to bycredentials
.When the last credential in the sequence is returned, the return code from
next()
will beccIteratorEnd
.Possible error codes:
ccNoErr
,ccIteratorEnd
,ccErrBadParam
,ccErrNoMem
,ccErrInvalidCredentialsIterator
cc_credentials_ttypedef struct { cc_int32 version; union { cc_credentials_v4_t* credentials_v4; cc_credentials_v5_t* credentials_v5; } credentials; } cc_credentials_union; typedef struct { cc_int32 (*release) ( cc_credentials_t credentials); } cc_credentials_f; typedef struct { const cc_credentials_union* data; const cc_credentials_f* functions; }* cc_credentials_t;The
cc_credentials_t
type is used to store a single set of credentials for either Kerberos v4 or Kerberos v5. In addition to its only function,release()
, it contains a pointer to acc_credentials_union
structure. Acc_credentials_union
structure contains an integer of the enumerator typecc_credentials_version
, which is eithercc_credentials_v4
orcc_credentials_v5
, and a pointer union, which contains either acc_credentials_v4_t
pointer or acc_credentials_v5_t
pointer, depending on the value inversion
.Variables of the type
cc_credentials_t
are allocated by the CCache implementation, and should be released with theirrelease()
function. API functions which receive credentials structures from the caller always acceptcc_credentials_union
, which is allocated by the caller, and accordingly disposed by the caller.If a
cc_credentials_t
variable is used to store Kerberos v4 credentials, thencredentials.credentials_v4
points to a v4 credentials structure:enum { cc_v4_ticket_size = 1250 cc_v4_name_size = 40, cc_v4_instance_size = 40, cc_v4_realm_size = 40, cc_v4_key_size = 8 }; enum cc_string_to_key_type { cc_v4_stk_unknown = 0, cc_v4_stk_afs = 1, cc_v4_stk_des = 2, cc_v4_stk_columbia_special = 3 }; typedef struct { unsigned char version; char principal[cc_v4_name_size]; char principal_instance[cc_v4_instance_size]; char service[cc_v4_name_size]; char service_instance[cc_v4_instance_size]; char realm[cc_v4_realm_size]; unsigned char session_key[cc_v4_key_size]; cc_int32 kvno; cc_int32 string_to_key; cc_time_t issue_date; cc_int32 lifetime; cc_uint32 address; cc_int32 ticket_size; unsigned char ticket[cc_v4_ticket_size]; } cc_cred_v4;The
realm
,principal
,principal_instance
,service
, andservice_instance
fields should contain (properly quoted) string representation of the realm, the principal, and the instance of the ticket and the service it was issued for. Thesession_key
field should contain the session key for the ticket. Thekvno
field should contain the key version number of the ticket. Thestring_to_key
field should contain a value of the enumerated typecc_string_to_key_type
. Theissue_date
field should contain the issue time of the ticket. Thelifetime
field should contain the lifetime of the ticket in units of 5 minutes. Theaddress
field should contain the IP address that the ticket was issued for as an unsigned 32-bit integer. Theticket
field should contain the ticket itself, and its size should be in theticket_size
field.Otherwise,
cc_credentials_t
is used to store Kerberos v5 credentials, and thencredentials.credentials_v5
points to a a v5 credentials structure. In a v5 credentials structure,cc_data
structures are used to store tagged variable-length binary data. Specifically, forcc_credentials_v5.ticket
andcc_credentials_v5.second_ticket
, thecc_data.type
field must be zero. For thecc_credentials_v5.addresses
,cc_credentials_v5.authdata
, andcc_credentials_v5.keyblock
, thecc_data.type
field should be the address type, authorization data type, and encryption type, as defined by the Kerberos v5 protocol definition.typedef struct { cc_uint32 type; cc_uint32 length; unsigned char* data; } cc_data; typedef struct { char* client; char* server; cc_data keyblock; cc_time_t authtime; cc_time_t starttime; cc_time_t endtime; cc_time_t renew_till; cc_uint32 is_skey; cc_uint32 ticket_flags; cc_data** addresses; cc_data ticket; cc_data second_ticket; cc_data** authdata; } cc_cred_v5;The
client
and theserver
field should contain the client's and the server's principal identifier, respectively, in properly quoted string representation. Thekeyblock
fiels should contain the session encryption key info. Theauthtime
field should contain the time when the ticket was issued. Thestarttime
and theendtime
fields should contain the beginning and the end of the time period during which the credentials are valid. Therenew_till
field should contain the maximal time until which the credentials can be renewed. Theis_skey
field should be set to 1 if the ticket is encrypted in another ticket's key, or 0 otherwise. Theticket_flags
field should contain the ticket flags of the ticket, as presented by the Kerberos v5 API. Theaddresses
field should contain the list of network addresses of hosts that are allowed to authenticate using this ticket. Theticket
field should contain the ticket data, and thesecond_ticket
field should contain the data for the second ticket, if there is one (for example, if the ticket is encrypted in second ticket's key). Theauthdata
field should contain the autorization data.cc_credentials_release
cc_int32 release ( cc_credentials_t credentials) cc_int32 cc_credentials_release ( cc_credentials_t credentials)This function frees all storage associated with a variable of
cc_credentials_t
.Possible error codes:
ccNoError
,ccErrInvalidCredentials
cc_string_ttypedef struct { cc_int32 (*release) ( cc_string_t string); } cc_string_f; typedef struct { const char* data; const cc_string_f* functions; }* cc_string_t;The
cc_string_t
represents a C string returned by the API. It has a pointer to the string data and arelease()
function. This type is used for both principal names and ccache names returned by the API. Principal names may contain UTF-8 encoded strings for internationalization purposes.cc_string_release
cc_int32 release ( cc_string_t string) cc_int32 cc_string_release ( cc_string_t string)This function frees the string returned by an API function.
Possible error codes:
ccNoError
,ccErrInvalidString
Revision History and Notes
Original version (Draft Version 1)
1/27/96 by Theodore Ts'o
Revision 2 (Draft Version 1)
970628 by Steve Rothwell for the V4Cache Team (Paul Hill, Jenny Khuon, Jean Luker, Dave Detlefs, Allan Bjorklund, & Steve Rothwell)
Revision 3 (Draft Version 1)
970725 by Steve Rothwell after initial implementation and alpha release. The term "credentials cache" was previously used to mean both "the main cache" and individual "named cache"s within the main cache. I have started using the term "NC" for "named cache" to make the distinction clearer and to reduce the overloading of the word "cache".
Changes made for revision 3 of this API:
- Added cred version type to cc_create() & cc_open()
- New functions
- cc_get_NC_info(), returns NC_info list for all NCs
- cc_free_NC_info(), frees NC_info list
- cc_get_cred_version(), returns version type of NC
- cc_get_name(), returns name of NC
- cc_free_name(), frees name aquired via cc_get_name()
- cc_seq_fetch_NCs(), iterate over all NCs
- New return codes
CC_BAD_PARAM
- CC_ERR_CACHE_ATTACH
- CC_ERR_CACHE_RELEASE
- CC_ERR_CACHE_FULL
CC_ERR_CRED_VERSION
- Modified functions
- cc_create(), cc_open(), pass version type of NC
- cc_store(), cc_remove(), cc_
- New & Modified typedefs & data structures
- cc_cred_vers { CC_CRED_VUNKNOWN, CC_CRED_V4, CC_CRED_V5 }
- cred_ptr_union : contains pointer to credentials (either V4 or V5)
- cred_union : contains version type and cred_ptr_union
- modified V4Cred_type
- enum StringToKey_Type { STK_AFS or STK_DES }
- copies of the maximum V4 string size indicators KRB_PRINCIPAL_SZ, KRB_SERVICE_SZ, KRB_INSTANCE_SZ, KRB_REALM_SZ, ADDR_SZ
Revision 4 (Draft Version 1)
970908 by Steve Rothwell to incorporate changes initiated by Ted Tso. Further changes are expected in the comments for cc_create() and cc_get_change_time().
Revision 4a (Final Version 1)
980603 by Scott McGuire to correct typographical errors, HTML errors, and minor clarifications. Final API Version 1 spec.
Revision 5 (Draft Version 2)
990201 by Scott McGuire.
- Increased API version number to 2.
- Added enum's defining version numbers.
- Changes to cc_initialize() to specify how to deal with different API version numbers.
- Added description of cc_int32 and cc_uint32 types.
- Change some cc_int32's to cc_uint32's.
- Changed way cc_create() will behave when called on an existing cache.
- Replaced cc_seq_fetch_NCs() with cc_seq_fetch_NCs_begin(), cc_seq_fetch_NCs_next(), and cc_seq_fetch_NCs_end();
- Replaced cc_seq_fetch_creds() with cc_seq_fetch_creds_begin(), cc_seq_fetch_creds_next(), and cc_seq_fetch_creds_end();
- Replaced enum type references in structs and function paramenters with cc_int32 references;
- Replaced int type references in function parameters with cc_int32;
- Added return type of cc_int32 to all functions;
- Removed #ifdef from cred_union structure;
- Constant definitions and changes to V4Cred_type structure;
- Removed incorrect const ccache_p * parameters from cc_store() and cc_remove_cred();
- Added
CC_NO_ERROR
andCC_BAD_PARAM
as possible return codes from all functions (except noCC_BAD_PARAM
from cc_shutdown() );- Added
CC_ERR_CRED_VERSION
as possible return code from cc_open() and cc_create();- Moved infoNC structure definition up to be with rest of structure definitions;
- Changed "struct _infoNC" to "infoNC" in parameter type references.
- cc_free_principal() and cc_free_name() now take char ** instead of char * for final parameter. (This change was made between rev 4a and rev 5, but I'm re-emphasizing it here.)
- Added Implementation Notes section with requirement that all functions must be atomic and name requirements for Windows DLL's.
- Renamed "the proposed changes to this API are" section to "Ideas for Future Versions" -- but removed all items but one because they'd all been done.
- Removed most of the notes about differences with the Win NT/95 implementation of the API -- the differences have been reconciled.
- Removed unnecessary and inconsistent italicizing.
Revision 5a (Final Version 2)
990723 by Scott McGuire.
- cc_create(): Removed text about "expected" form of name. Removed note about "the alpha version does not do this."
- cc_destroy(): Clarified that you do not need to call cc_close() on the cache_pointer after calling this function.
- Removed note about Windows cc_get_instance() and cc_set_instance() functions, they are no longer part of the Windows code!Function definitions
Questions or comments? Send mail to macdev@mit.edu
Last updated on $Date: 2003/11/19 20:42:28 $
Last modified by $Author: smcguire $