diff options
Diffstat (limited to 'kcm/cache.c')
| -rw-r--r-- | kcm/cache.c | 325 |
1 files changed, 182 insertions, 143 deletions
diff --git a/kcm/cache.c b/kcm/cache.c index aeb30cca1fe9..1bd220c8a70a 100644 --- a/kcm/cache.c +++ b/kcm/cache.c @@ -2,6 +2,8 @@ * Copyright (c) 2005, PADL Software Pty Ltd. * All rights reserved. * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -32,11 +34,9 @@ #include "kcm_locl.h" -RCSID("$Id: cache.c 14566 2005-02-06 01:22:49Z lukeh $"); - -static HEIMDAL_MUTEX ccache_mutex = HEIMDAL_MUTEX_INITIALIZER; -static kcm_ccache_data *ccache_head = NULL; -static unsigned int ccache_nextid = 0; +HEIMDAL_MUTEX ccache_mutex = HEIMDAL_MUTEX_INITIALIZER; +kcm_ccache_data *ccache_head = NULL; +static unsigned int ccache_nextid = 0; char *kcm_ccache_nextid(pid_t pid, uid_t uid, gid_t gid) { @@ -47,15 +47,15 @@ char *kcm_ccache_nextid(pid_t pid, uid_t uid, gid_t gid) n = ++ccache_nextid; HEIMDAL_MUTEX_unlock(&ccache_mutex); - asprintf(&name, "%d:%u", uid, n); + asprintf(&name, "%ld:%u", (long)uid, n); return name; } -static krb5_error_code -kcm_ccache_resolve_internal(krb5_context context, - const char *name, - kcm_ccache *ccache) +krb5_error_code +kcm_ccache_resolve(krb5_context context, + const char *name, + kcm_ccache *ccache) { kcm_ccache p; krb5_error_code ret; @@ -85,6 +85,66 @@ kcm_ccache_resolve_internal(krb5_context context, return ret; } +krb5_error_code +kcm_ccache_resolve_by_uuid(krb5_context context, + kcmuuid_t uuid, + kcm_ccache *ccache) +{ + kcm_ccache p; + krb5_error_code ret; + + *ccache = NULL; + + ret = KRB5_FCC_NOFILE; + + HEIMDAL_MUTEX_lock(&ccache_mutex); + + for (p = ccache_head; p != NULL; p = p->next) { + if ((p->flags & KCM_FLAGS_VALID) == 0) + continue; + if (memcmp(p->uuid, uuid, sizeof(uuid)) == 0) { + ret = 0; + break; + } + } + + if (ret == 0) { + kcm_retain_ccache(context, p); + *ccache = p; + } + + HEIMDAL_MUTEX_unlock(&ccache_mutex); + + return ret; +} + +krb5_error_code +kcm_ccache_get_uuids(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *sp) +{ + krb5_error_code ret; + kcm_ccache p; + + ret = KRB5_FCC_NOFILE; + + HEIMDAL_MUTEX_lock(&ccache_mutex); + + for (p = ccache_head; p != NULL; p = p->next) { + if ((p->flags & KCM_FLAGS_VALID) == 0) + continue; + ret = kcm_access(context, client, opcode, p); + if (ret) { + ret = 0; + continue; + } + krb5_storage_write(sp, p->uuid, sizeof(p->uuid)); + } + + HEIMDAL_MUTEX_unlock(&ccache_mutex); + + return ret; +} + + krb5_error_code kcm_debug_ccache(krb5_context context) { kcm_ccache p; @@ -108,7 +168,7 @@ krb5_error_code kcm_debug_ccache(krb5_context context) krb5_unparse_name(context, p->client, &cpn); if (p->server != NULL) krb5_unparse_name(context, p->server, &spn); - + kcm_log(7, "cache %08x: name %s refcnt %d flags %04x mode %04o " "uid %d gid %d client %s server %s ncreds %d", p, p->name, p->refcnt, p->flags, p->mode, p->uid, p->gid, @@ -125,10 +185,48 @@ krb5_error_code kcm_debug_ccache(krb5_context context) return 0; } -static krb5_error_code -kcm_ccache_destroy_internal(krb5_context context, const char *name) +static void +kcm_free_ccache_data_internal(krb5_context context, + kcm_ccache_data *cache) { - kcm_ccache *p; + KCM_ASSERT_VALID(cache); + + if (cache->name != NULL) { + free(cache->name); + cache->name = NULL; + } + + if (cache->flags & KCM_FLAGS_USE_KEYTAB) { + krb5_kt_close(context, cache->key.keytab); + cache->key.keytab = NULL; + } else if (cache->flags & KCM_FLAGS_USE_CACHED_KEY) { + krb5_free_keyblock_contents(context, &cache->key.keyblock); + krb5_keyblock_zero(&cache->key.keyblock); + } + + cache->flags = 0; + cache->mode = 0; + cache->uid = -1; + cache->gid = -1; + cache->session = -1; + + kcm_zero_ccache_data_internal(context, cache); + + cache->tkt_life = 0; + cache->renew_life = 0; + + cache->next = NULL; + cache->refcnt = 0; + + HEIMDAL_MUTEX_unlock(&cache->mutex); + HEIMDAL_MUTEX_destroy(&cache->mutex); +} + + +krb5_error_code +kcm_ccache_destroy(krb5_context context, const char *name) +{ + kcm_ccache *p, ccache; krb5_error_code ret; ret = KRB5_FCC_NOFILE; @@ -142,11 +240,18 @@ kcm_ccache_destroy_internal(krb5_context context, const char *name) break; } } - if (ret) goto out; - kcm_release_ccache(context, p); + if ((*p)->refcnt != 1) { + ret = EAGAIN; + goto out; + } + + ccache = *p; + *p = (*p)->next; + kcm_free_ccache_data_internal(context, ccache); + free(ccache); out: HEIMDAL_MUTEX_unlock(&ccache_mutex); @@ -182,29 +287,21 @@ kcm_ccache_alloc(krb5_context context, goto out; /* - * Then try and find an empty slot - * XXX we need to recycle slots for this to actually do anything + * Create an enpty slot for us. */ if (slot == NULL) { - for (; p != NULL; p = p->next) { - if ((p->flags & KCM_FLAGS_VALID) == 0) { - slot = p; - break; - } - } - + slot = (kcm_ccache_data *)malloc(sizeof(*slot)); if (slot == NULL) { - slot = (kcm_ccache_data *)malloc(sizeof(*slot)); - if (slot == NULL) { - ret = KRB5_CC_NOMEM; - goto out; - } - slot->next = ccache_head; - HEIMDAL_MUTEX_init(&slot->mutex); - new_slot = 1; + ret = KRB5_CC_NOMEM; + goto out; } + slot->next = ccache_head; + HEIMDAL_MUTEX_init(&slot->mutex); + new_slot = 1; } + RAND_bytes(slot->uuid, sizeof(slot->uuid)); + slot->name = strdup(name); if (slot->name == NULL) { ret = KRB5_CC_NOMEM; @@ -219,8 +316,6 @@ kcm_ccache_alloc(krb5_context context, slot->client = NULL; slot->server = NULL; slot->creds = NULL; - slot->n_cursor = 0; - slot->cursors = NULL; slot->key.keytab = NULL; slot->tkt_life = 0; slot->renew_life = 0; @@ -247,7 +342,6 @@ kcm_ccache_remove_creds_internal(krb5_context context, kcm_ccache ccache) { struct kcm_creds *k; - struct kcm_cursor *c; k = ccache->creds; while (k != NULL) { @@ -260,20 +354,6 @@ kcm_ccache_remove_creds_internal(krb5_context context, } ccache->creds = NULL; - /* remove anything that would have pointed into the creds too */ - - ccache->n_cursor = 0; - - c = ccache->cursors; - while (c != NULL) { - struct kcm_cursor *old; - - old = c; - c = c->next; - free(old); - } - ccache->cursors = NULL; - return 0; } @@ -326,44 +406,6 @@ kcm_zero_ccache_data(krb5_context context, return ret; } -static krb5_error_code -kcm_free_ccache_data_internal(krb5_context context, - kcm_ccache_data *cache) -{ - KCM_ASSERT_VALID(cache); - - if (cache->name != NULL) { - free(cache->name); - cache->name = NULL; - } - - if (cache->flags & KCM_FLAGS_USE_KEYTAB) { - krb5_kt_close(context, cache->key.keytab); - cache->key.keytab = NULL; - } else if (cache->flags & KCM_FLAGS_USE_CACHED_KEY) { - krb5_free_keyblock_contents(context, &cache->key.keyblock); - krb5_keyblock_zero(&cache->key.keyblock); - } - - cache->flags = 0; - cache->mode = 0; - cache->uid = -1; - cache->gid = -1; - - kcm_zero_ccache_data_internal(context, cache); - - cache->tkt_life = 0; - cache->renew_life = 0; - - cache->next = NULL; - cache->refcnt = 0; - - HEIMDAL_MUTEX_unlock(&cache->mutex); - HEIMDAL_MUTEX_destroy(&cache->mutex); - - return 0; -} - krb5_error_code kcm_retain_ccache(krb5_context context, kcm_ccache ccache) @@ -378,26 +420,21 @@ kcm_retain_ccache(krb5_context context, } krb5_error_code -kcm_release_ccache(krb5_context context, - kcm_ccache *ccache) +kcm_release_ccache(krb5_context context, kcm_ccache c) { - kcm_ccache c = *ccache; krb5_error_code ret = 0; KCM_ASSERT_VALID(c); HEIMDAL_MUTEX_lock(&c->mutex); if (c->refcnt == 1) { - ret = kcm_free_ccache_data_internal(context, c); - if (ret == 0) - free(c); + kcm_free_ccache_data_internal(context, c); + free(c); } else { c->refcnt--; HEIMDAL_MUTEX_unlock(&c->mutex); } - *ccache = NULL; - return ret; } @@ -442,38 +479,15 @@ kcm_ccache_new(krb5_context context, } krb5_error_code -kcm_ccache_resolve(krb5_context context, - const char *name, - kcm_ccache *ccache) -{ - krb5_error_code ret; - - ret = kcm_ccache_resolve_internal(context, name, ccache); - - return ret; -} - -krb5_error_code -kcm_ccache_destroy(krb5_context context, - const char *name) -{ - krb5_error_code ret; - - ret = kcm_ccache_destroy_internal(context, name); - - return ret; -} - -krb5_error_code kcm_ccache_destroy_if_empty(krb5_context context, kcm_ccache ccache) { krb5_error_code ret; KCM_ASSERT_VALID(ccache); - + if (ccache->creds == NULL) { - ret = kcm_ccache_destroy_internal(context, ccache->name); + ret = kcm_ccache_destroy(context, ccache->name); } else ret = 0; @@ -490,7 +504,7 @@ kcm_ccache_store_cred(krb5_context context, krb5_creds *tmp; KCM_ASSERT_VALID(ccache); - + HEIMDAL_MUTEX_lock(&ccache->mutex); ret = kcm_ccache_store_cred_internal(context, ccache, creds, copy, &tmp); HEIMDAL_MUTEX_unlock(&ccache->mutex); @@ -498,6 +512,22 @@ kcm_ccache_store_cred(krb5_context context, return ret; } +struct kcm_creds * +kcm_ccache_find_cred_uuid(krb5_context context, + kcm_ccache ccache, + kcmuuid_t uuid) +{ + struct kcm_creds *c; + + for (c = ccache->creds; c != NULL; c = c->next) + if (memcmp(c->uuid, uuid, sizeof(c->uuid)) == 0) + return c; + + return NULL; +} + + + krb5_error_code kcm_ccache_store_cred_internal(krb5_context context, kcm_ccache ccache, @@ -511,10 +541,11 @@ kcm_ccache_store_cred_internal(krb5_context context, for (c = &ccache->creds; *c != NULL; c = &(*c)->next) ; - *c = (struct kcm_creds *)malloc(sizeof(struct kcm_creds)); - if (*c == NULL) { + *c = (struct kcm_creds *)calloc(1, sizeof(**c)); + if (*c == NULL) return KRB5_CC_NOMEM; - } + + RAND_bytes((*c)->uuid, sizeof((*c)->uuid)); *credp = &(*c)->cred; @@ -529,25 +560,9 @@ kcm_ccache_store_cred_internal(krb5_context context, ret = 0; } - (*c)->next = NULL; - return ret; } -static void -remove_cred(krb5_context context, - struct kcm_creds **c) -{ - struct kcm_creds *cred; - - cred = *c; - - *c = cred->next; - - krb5_free_cred_contents(context, &cred->cred); - free(cred); -} - krb5_error_code kcm_ccache_remove_cred_internal(krb5_context context, kcm_ccache ccache, @@ -561,8 +576,14 @@ kcm_ccache_remove_cred_internal(krb5_context context, for (c = &ccache->creds; *c != NULL; c = &(*c)->next) { if (krb5_compare_creds(context, whichfields, mcreds, &(*c)->cred)) { - remove_cred(context, c); + struct kcm_creds *cred = *c; + + *c = cred->next; + krb5_free_cred_contents(context, &cred->cred); + free(cred); ret = 0; + if (*c == NULL) + break; } } @@ -626,7 +647,7 @@ kcm_ccache_retrieve_cred(krb5_context context, krb5_error_code ret; KCM_ASSERT_VALID(ccache); - + HEIMDAL_MUTEX_lock(&ccache->mutex); ret = kcm_ccache_retrieve_cred_internal(context, ccache, whichfields, mcreds, credp); @@ -634,3 +655,21 @@ kcm_ccache_retrieve_cred(krb5_context context, return ret; } + +char * +kcm_ccache_first_name(kcm_client *client) +{ + kcm_ccache p; + char *name = NULL; + + HEIMDAL_MUTEX_lock(&ccache_mutex); + + for (p = ccache_head; p != NULL; p = p->next) { + if (kcm_is_same_session(client, p->uid, p->session)) + break; + } + if (p) + name = strdup(p->name); + HEIMDAL_MUTEX_unlock(&ccache_mutex); + return name; +} |
