diff options
Diffstat (limited to 'lib/krb5/acache.c')
-rw-r--r-- | lib/krb5/acache.c | 212 |
1 files changed, 111 insertions, 101 deletions
diff --git a/lib/krb5/acache.c b/lib/krb5/acache.c index 9d33df133c27..63d56c400bf5 100644 --- a/lib/krb5/acache.c +++ b/lib/krb5/acache.c @@ -35,9 +35,6 @@ #include "krb5_locl.h" #include <krb5_ccapi.h> -#ifdef HAVE_DLFCN_H -#include <dlfcn.h> -#endif #ifndef KCM_IS_API_CACHE @@ -52,6 +49,7 @@ static void *cc_handle; typedef struct krb5_acc { char *cache_name; + char *cache_subsidiary; cc_context_t context; cc_ccache_t ccache; } krb5_acc; @@ -90,6 +88,7 @@ static krb5_error_code init_ccapi(krb5_context context) { const char *lib = NULL; + char *explib = NULL; HEIMDAL_MUTEX_lock(&acc_mutex); if (init_func) { @@ -106,40 +105,25 @@ init_ccapi(krb5_context context) if (lib == NULL) { #ifdef __APPLE__ lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos"; -#elif defined(KRB5_USE_PATH_TOKENS) && defined(_WIN32) +#elif defined(_WIN32) lib = "%{LIBDIR}/libkrb5_cc.dll"; #else - lib = "/usr/lib/libkrb5_cc.so"; + lib = "%{LIBDIR}/libkrb5_cc.so"; #endif } #ifdef HAVE_DLOPEN -#ifndef RTLD_LAZY -#define RTLD_LAZY 0 -#endif -#ifndef RTLD_LOCAL -#define RTLD_LOCAL 0 -#endif - -#ifdef KRB5_USE_PATH_TOKENS - { - char * explib = NULL; - if (_krb5_expand_path_tokens(context, lib, 0, &explib) == 0) { - cc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL); - free(explib); - } + if (_krb5_expand_path_tokens(context, lib, 0, &explib) == 0) { + cc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL|RTLD_GROUP); + free(explib); } -#else - cc_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL); -#endif if (cc_handle == NULL) { HEIMDAL_MUTEX_unlock(&acc_mutex); - if (context) - krb5_set_error_message(context, KRB5_CC_NOSUPP, - N_("Failed to load API cache module %s", "file"), - lib); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + N_("Failed to load API cache module %s", "file"), + lib); return KRB5_CC_NOSUPP; } @@ -150,10 +134,9 @@ init_ccapi(krb5_context context) dlsym(cc_handle, "krb5_ipc_client_clear_target"); HEIMDAL_MUTEX_unlock(&acc_mutex); if (init_func == NULL) { - if (context) - krb5_set_error_message(context, KRB5_CC_NOSUPP, - N_("Failed to find cc_initialize" - "in %s: %s", "file, error"), lib, dlerror()); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + N_("Failed to find cc_initialize" + "in %s: %s", "file, error"), lib, dlerror()); dlclose(cc_handle); return KRB5_CC_NOSUPP; } @@ -161,9 +144,8 @@ init_ccapi(krb5_context context) return 0; #else HEIMDAL_MUTEX_unlock(&acc_mutex); - if (context) - krb5_set_error_message(context, KRB5_CC_NOSUPP, - N_("no support for shared object", "")); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + N_("no support for shared object", "")); return KRB5_CC_NOSUPP; #endif } @@ -452,41 +434,51 @@ get_cc_name(krb5_acc *a) } -static const char* KRB5_CALLCONV -acc_get_name(krb5_context context, - krb5_ccache id) +static krb5_error_code KRB5_CALLCONV +acc_get_name_2(krb5_context context, + krb5_ccache id, + const char **name, + const char **colname, + const char **subsidiary) { + krb5_error_code ret = 0; krb5_acc *a = ACACHE(id); int32_t error; - if (a->cache_name == NULL) { - krb5_error_code ret; - krb5_principal principal; - char *name; + if (name) + *name = NULL; + if (colname) + *colname = NULL; + if (subsidiary) + *subsidiary = NULL; + if (a->cache_subsidiary == NULL) { + krb5_principal principal = NULL; ret = _krb5_get_default_principal_local(context, &principal); - if (ret) - return NULL; - - ret = krb5_unparse_name(context, principal, &name); + if (ret == 0) + ret = krb5_unparse_name(context, principal, &a->cache_subsidiary); krb5_free_principal(context, principal); if (ret) - return NULL; - - error = (*a->context->func->create_new_ccache)(a->context, - cc_credentials_v5, - name, - &a->ccache); - krb5_xfree(name); - if (error) - return NULL; - - error = get_cc_name(a); - if (error) - return NULL; + return ret; } - return a->cache_name; + if (a->cache_name == NULL) { + error = (*a->context->func->create_new_ccache)(a->context, + cc_credentials_v5, + a->cache_subsidiary, + &a->ccache); + if (error == ccNoError) + error = get_cc_name(a); + if (error != ccNoError) + ret = translate_cc_error(context, error); + } + if (name) + *name = a->cache_name; + if (colname) + *colname = ""; + if (subsidiary) + *subsidiary = a->cache_subsidiary; + return ret; } static krb5_error_code KRB5_CALLCONV @@ -507,6 +499,10 @@ acc_alloc(krb5_context context, krb5_ccache *id) } a = ACACHE(*id); + a->cache_subsidiary = NULL; + a->cache_name = NULL; + a->context = NULL; + a->ccache = NULL; error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL); if (error) { @@ -514,17 +510,17 @@ acc_alloc(krb5_context context, krb5_ccache *id) return translate_cc_error(context, error); } - a->cache_name = NULL; - return 0; } static krb5_error_code KRB5_CALLCONV -acc_resolve(krb5_context context, krb5_ccache *id, const char *res) +acc_resolve_2(krb5_context context, krb5_ccache *id, const char *res, const char *sub) { krb5_error_code ret; + cc_time_t offset; cc_int32 error; krb5_acc *a; + char *s = NULL; ret = acc_alloc(context, id); if (ret) @@ -532,49 +528,60 @@ acc_resolve(krb5_context context, krb5_ccache *id, const char *res) a = ACACHE(*id); - error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); - if (error == ccNoError) { - cc_time_t offset; - error = get_cc_name(a); - if (error != ccNoError) { + if (sub) { + /* + * For API there's no such thing as a collection name, there's only the + * default collection. Though we could perhaps put a CCAPI shared + * object path in the collection name. + * + * So we'll treat (res && !sub) and (!res && sub) as the same cases. + * + * See also the KCM ccache type, where we have similar considerations. + */ + if (asprintf(&s, "%s%s%s", res && *res ? res : "", + res && *res ? ":" : "", sub) == -1 || s == NULL || + (a->cache_subsidiary = strdup(sub)) == NULL) { acc_close(context, *id); - *id = NULL; - return translate_cc_error(context, error); - } - - error = (*a->ccache->func->get_kdc_time_offset)(a->ccache, - cc_credentials_v5, - &offset); - if (error == 0) - context->kdc_sec_offset = offset; + free(s); + return krb5_enomem(context); + } + res = s; + /* + * XXX With a bit of extra refactoring we could use the collection name + * as the path to the shared object implementing CCAPI... For now we + * ignore the collection name. + */ + } - } else if (error == ccErrCCacheNotFound) { - a->ccache = NULL; - a->cache_name = NULL; - } else { - *id = NULL; - return translate_cc_error(context, error); + error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); + if (error == ccErrCCacheNotFound) { + a->ccache = NULL; + a->cache_name = NULL; + free(s); + return 0; + } + if (error == ccNoError) + error = get_cc_name(a); + if (error != ccNoError) { + acc_close(context, *id); + *id = NULL; + free(s); + return translate_cc_error(context, error); } + error = (*a->ccache->func->get_kdc_time_offset)(a->ccache, + cc_credentials_v5, + &offset); + if (error == 0) + context->kdc_sec_offset = offset; + free(s); return 0; } static krb5_error_code KRB5_CALLCONV acc_gen_new(krb5_context context, krb5_ccache *id) { - krb5_error_code ret; - krb5_acc *a; - - ret = acc_alloc(context, id); - if (ret) - return ret; - - a = ACACHE(*id); - - a->ccache = NULL; - a->cache_name = NULL; - - return 0; + return acc_alloc(context, id); } static krb5_error_code KRB5_CALLCONV @@ -978,6 +985,7 @@ acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) static krb5_error_code KRB5_CALLCONV acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) { + krb5_error_code ret; krb5_acc *afrom = ACACHE(from); krb5_acc *ato = ACACHE(to); int32_t error; @@ -1001,10 +1009,10 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) } error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache); - - acc_destroy(context, from); - - return translate_cc_error(context, error); + ret = translate_cc_error(context, error); + if (ret == 0) + krb5_cc_destroy(context, from); + return ret; } static krb5_error_code KRB5_CALLCONV @@ -1086,10 +1094,10 @@ acc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime) */ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_acc_ops = { - KRB5_CC_OPS_VERSION, + KRB5_CC_OPS_VERSION_5, "API", - acc_get_name, - acc_resolve, + NULL, + NULL, acc_gen_new, acc_initialize, acc_destroy, @@ -1112,6 +1120,8 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_acc_ops = { acc_lastchange, NULL, NULL, + acc_get_name_2, + acc_resolve_2 }; #endif |