From 9e6b0c28712ee77ce878809c8576826a3ba08d95 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Mar 2008 10:17:42 +1100 Subject: Merge lorikeet-heimdal -r 787 into Samba4 tree. Andrew Bartlett (This used to be commit d88b530522d3cef67c24422bd5182fb875d87ee2) --- source4/heimdal/lib/krb5/cache.c | 330 ++++++++++++++++++++++++++++++--------- 1 file changed, 253 insertions(+), 77 deletions(-) (limited to 'source4/heimdal/lib/krb5/cache.c') diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 59aae40d28..5db6d2b2cf 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,12 +33,20 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c 21498 2007-07-11 09:41:43Z lha $"); +RCSID("$Id: cache.c 22127 2007-12-04 00:54:37Z lha $"); -/* +/** * Add a new ccache type with operations `ops', overwriting any * existing one if `override'. - * Return an error code or 0. + * + * @param context a Keberos context + * @param ops type of plugin symbol + * @param override flag to select if the registration is to overide + * an existing ops with the same name. + * + * @return Return an error code or 0. + * + * @ingroup krb5_ccache */ krb5_error_code KRB5_LIB_FUNCTION @@ -101,8 +109,7 @@ _krb5_cc_allocate(krb5_context context, /* * Allocate memory for a new ccache in `id' with operations `ops' - * and name `residual'. - * Return 0 or an error code. + * and name `residual'. Return 0 or an error code. */ static krb5_error_code @@ -122,12 +129,21 @@ allocate_ccache (krb5_context context, return ret; } -/* +/** * Find and allocate a ccache in `id' from the specification in `residual'. * If the ccache name doesn't contain any colon, interpret it as a file name. - * Return 0 or an error code. + * + * @param context a Keberos context. + * @param name string name of a credential cache. + * @param id return pointer to a found credential cache. + * + * @return Return 0 or an error code. In case of an error, id is set + * to NULL. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_resolve(krb5_context context, const char *name, @@ -135,6 +151,8 @@ krb5_cc_resolve(krb5_context context, { int i; + *id = NULL; + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { size_t prefix_len = strlen(context->cc_ops[i].prefix); @@ -153,57 +171,64 @@ krb5_cc_resolve(krb5_context context, } } -/* +/** * Generate a new ccache of type `ops' in `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id) { - krb5_error_code ret; - - ret = _krb5_cc_allocate(context, ops, id); - if (ret) - return ret; - return (*id)->ops->gen_new(context, id); + return krb5_cc_new_unique(context, ops->prefix, NULL, id); } -/* +/** * Generates a new unique ccache of `type` in `id'. If `type' is NULL, * the library chooses the default credential cache type. The supplied * `hint' (that can be NULL) is a string that the credential cache * type can use to base the name of the credential on, this is to make - * its easier for the user to differentiate the credentials. + * it easier for the user to differentiate the credentials. + * + * @return Returns 0 or an error code. * - * Returns 0 or an error code. + * @ingroup krb5_ccache */ krb5_error_code KRB5_LIB_FUNCTION krb5_cc_new_unique(krb5_context context, const char *type, const char *hint, krb5_ccache *id) { - const krb5_cc_ops *ops; - - if (type == NULL) - type = KRB5_DEFAULT_CCNAME; + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + krb5_error_code ret; - ops = krb5_cc_get_prefix_ops(context, type); - if (ops == NULL) { - krb5_set_error_string(context, "Credential cache type %s is unknown", - type); - return KRB5_CC_UNKNOWN_TYPE; + if (type) { + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, + "Credential cache type %s is unknown", type); + return KRB5_CC_UNKNOWN_TYPE; + } } - return krb5_cc_gen_new(context, ops, id); + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + return (*id)->ops->gen_new(context, id); } -/* +/** * Return the name of the ccache `id' + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_get_name(krb5_context context, krb5_ccache id) @@ -211,10 +236,13 @@ krb5_cc_get_name(krb5_context context, return id->ops->get_name(context, id); } -/* +/** * Return the type of the ccache `id'. + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_get_type(krb5_context context, krb5_ccache id) @@ -222,12 +250,15 @@ krb5_cc_get_type(krb5_context context, return id->ops->prefix; } -/* +/** * Return the complete resolvable name the ccache `id' in `str´. * `str` should be freed with free(3). * Returns 0 or an error (and then *str is set to NULL). + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_full_name(krb5_context context, krb5_ccache id, @@ -257,10 +288,13 @@ krb5_cc_get_full_name(krb5_context context, return 0; } -/* +/** * Return krb5_cc_ops of a the ccache `id'. + * + * @ingroup krb5_ccache */ + const krb5_cc_ops * krb5_cc_get_ops(krb5_context context, krb5_ccache id) { @@ -348,6 +382,10 @@ environment_changed(krb5_context context) { const char *e; + /* if the cc name was set, don't change it */ + if (context->default_cc_name_set) + return 0; + if(issuid()) return 0; @@ -367,10 +405,13 @@ environment_changed(krb5_context context) return 0; } -/* +/** * Set the default cc name for `context' to `name'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_default_name(krb5_context context, const char *name) { @@ -392,14 +433,23 @@ krb5_cc_set_default_name(krb5_context context, const char *name) if (e == NULL) { e = krb5_config_get_string(context, NULL, "libdefaults", "default_cc_name", NULL); - if (e == NULL) - e = KRB5_DEFAULT_CCNAME; - ret = _krb5_expand_default_cc_name(context, e, &p); - if (ret) - return ret; + if (e) { + ret = _krb5_expand_default_cc_name(context, e, &p); + if (ret) + return ret; + } + if (e == NULL) { + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + ret = (*ops->default_name)(context, &p); + if (ret) + return ret; + } } - } else + context->default_cc_name_set = 0; + } else { p = strdup(name); + context->default_cc_name_set = 1; + } if (p == NULL) { krb5_set_error_string(context, "malloc - out of memory"); @@ -414,11 +464,16 @@ krb5_cc_set_default_name(krb5_context context, const char *name) return ret; } -/* +/** * Return a pointer to a context static string containing the default * ccache name. + * + * @return String to the default credential cache name. + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_default_name(krb5_context context) { @@ -428,11 +483,15 @@ krb5_cc_default_name(krb5_context context) return context->default_cc_name; } -/* +/** * Open the default ccache in `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_default(krb5_context context, krb5_ccache *id) @@ -446,11 +505,15 @@ krb5_cc_default(krb5_context context, return krb5_cc_resolve(context, p, id); } -/* +/** * Create a new ccache in `id' for `primary_principal'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_initialize(krb5_context context, krb5_ccache id, @@ -460,11 +523,15 @@ krb5_cc_initialize(krb5_context context, } -/* +/** * Remove the ccache `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_destroy(krb5_context context, krb5_ccache id) @@ -476,11 +543,15 @@ krb5_cc_destroy(krb5_context context, return ret; } -/* +/** * Stop using the ccache `id' and free the related resources. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_close(krb5_context context, krb5_ccache id) @@ -491,11 +562,15 @@ krb5_cc_close(krb5_context context, return ret; } -/* +/** * Store `creds' in the ccache `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_store_cred(krb5_context context, krb5_ccache id, @@ -504,13 +579,17 @@ krb5_cc_store_cred(krb5_context context, return (*id->ops->store)(context, id, creds); } -/* +/** * Retrieve the credential identified by `mcreds' (and `whichfields') * from `id' in `creds'. 'creds' must be free by the caller using * krb5_free_cred_contents. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_retrieve_cred(krb5_context context, krb5_ccache id, @@ -526,7 +605,9 @@ krb5_cc_retrieve_cred(krb5_context context, mcreds, creds); } - krb5_cc_start_seq_get(context, id, &cursor); + ret = krb5_cc_start_seq_get(context, id, &cursor); + if (ret) + return ret; while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){ if(krb5_compare_creds(context, whichfields, mcreds, creds)){ ret = 0; @@ -538,11 +619,15 @@ krb5_cc_retrieve_cred(krb5_context context, return ret; } -/* +/** * Return the principal of `id' in `principal'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_principal(krb5_context context, krb5_ccache id, @@ -551,12 +636,16 @@ krb5_cc_get_principal(krb5_context context, return (*id->ops->get_princ)(context, id, principal); } -/* +/** * Start iterating over `id', `cursor' is initialized to the * beginning. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_start_seq_get (krb5_context context, const krb5_ccache id, @@ -565,12 +654,16 @@ krb5_cc_start_seq_get (krb5_context context, return (*id->ops->get_first)(context, id, cursor); } -/* +/** * Retrieve the next cred pointed to by (`id', `cursor') in `creds' * and advance `cursor'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_next_cred (krb5_context context, const krb5_ccache id, @@ -580,7 +673,12 @@ krb5_cc_next_cred (krb5_context context, return (*id->ops->get_next)(context, id, cursor, creds); } -/* like krb5_cc_next_cred, but allow for selective retrieval */ +/** + * Like krb5_cc_next_cred, but allow for selective retrieval + * + * @ingroup krb5_ccache + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_next_cred_match(krb5_context context, @@ -601,10 +699,13 @@ krb5_cc_next_cred_match(krb5_context context, } } -/* +/** * Destroy the cursor `cursor'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_end_seq_get (krb5_context context, const krb5_ccache id, @@ -613,10 +714,13 @@ krb5_cc_end_seq_get (krb5_context context, return (*id->ops->end_get)(context, id, cursor); } -/* +/** * Remove the credential identified by `cred', `which' from `id'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_remove_cred(krb5_context context, krb5_ccache id, @@ -632,10 +736,13 @@ krb5_cc_remove_cred(krb5_context context, return (*id->ops->remove_cred)(context, id, which, cred); } -/* +/** * Set the flags of `id' to `flags'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_flags(krb5_context context, krb5_ccache id, @@ -644,10 +751,13 @@ krb5_cc_set_flags(krb5_context context, return (*id->ops->set_flags)(context, id, flags); } -/* +/** * Copy the contents of `from' to `to'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_copy_cache_match(krb5_context context, const krb5_ccache from, @@ -689,6 +799,13 @@ krb5_cc_copy_cache_match(krb5_context context, return ret; } +/** + * Just like krb5_cc_copy_cache_match, but copy everything. + * + * @ingroup krb5_ccache + */ + + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_copy_cache(krb5_context context, const krb5_ccache from, @@ -697,10 +814,13 @@ krb5_cc_copy_cache(krb5_context context, return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL); } -/* +/** * Return the version of `id'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_version(krb5_context context, const krb5_ccache id) @@ -711,23 +831,30 @@ krb5_cc_get_version(krb5_context context, return 0; } -/* +/** * Clear `mcreds' so it can be used with krb5_cc_retrieve_cred + * + * @ingroup krb5_ccache */ + void KRB5_LIB_FUNCTION krb5_cc_clear_mcred(krb5_creds *mcred) { memset(mcred, 0, sizeof(*mcred)); } -/* +/** * Get the cc ops that is registered in `context' to handle the * `prefix'. `prefix' can be a complete credential cache name or a * prefix, the function will only use part up to the first colon (:) - * if there is one. Returns NULL if ops not found. + * if there is one. + * Returns NULL if ops not found. + * + * @ingroup krb5_ccache */ + const krb5_cc_ops * krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) { @@ -761,12 +888,16 @@ struct krb5_cc_cache_cursor_data { krb5_cc_cursor cursor; }; -/* +/** * Start iterating over all caches of `type'. If `type' is NULL, the * default type is * used. `cursor' is initialized to the beginning. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_get_first (krb5_context context, const char *type, @@ -807,12 +938,16 @@ krb5_cc_cache_get_first (krb5_context context, return ret; } -/* +/** * Retrieve the next cache pointed to by (`cursor') in `id' * and advance `cursor'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_next (krb5_context context, krb5_cc_cache_cursor cursor, @@ -821,10 +956,15 @@ krb5_cc_cache_next (krb5_context context, return cursor->ops->get_cache_next(context, cursor->cursor, id); } -/* +/** * Destroy the cursor `cursor'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_end_seq_get (krb5_context context, krb5_cc_cache_cursor cursor) @@ -836,14 +976,18 @@ krb5_cc_cache_end_seq_get (krb5_context context, return ret; } -/* +/** * Search for a matching credential cache of type `type' that have the * `principal' as the default principal. If NULL is used for `type', * the default type is used. On success, `id' needs to be freed with - * krb5_cc_close or krb5_cc_destroy. On failure, error code is - * returned and `id' is set to NULL. + * krb5_cc_close or krb5_cc_destroy. + * + * @return On failure, error code is returned and `id' is set to NULL. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_match (krb5_context context, krb5_principal client, @@ -895,3 +1039,35 @@ krb5_cc_cache_match (krb5_context context, return 0; } +/** + * Move the content from one credential cache to another. The + * operation is an atomic switch. + * + * @param context a Keberos context + * @param from the credential cache to move the content from + * @param to the credential cache to move the content to + + * @return On sucess, from is freed. On failure, error code is + * returned and from and to are both still allocated. + * + * @ingroup krb5_ccache + */ + +krb5_error_code +krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret; + + if (strcmp(from->ops->prefix, to->ops->prefix) != 0) { + krb5_set_error_string(context, "Moving credentials between diffrent " + "types not yet supported"); + return KRB5_CC_NOSUPP; + } + + ret = (*to->ops->move)(context, from, to); + if (ret == 0) { + memset(from, 0, sizeof(*from)); + free(from); + } + return ret; +} -- cgit