From 4d46db6bf4525c5bf4265df5e4485abc79f99040 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Mon, 28 Jun 2004 18:58:53 +0000 Subject: [PATCH] * cc_memory.c: Include k5-thread.h. (krb5int_mcc_mutex): New lock. (krb5_mcc_store): Rewrite. (NEED_WINDOWS): Don't define. (krb5_mcc_*): All functions now static. * cc-int.h (krb5int_mcc_mutex): Declare. * ccbase.c (krb5int_cc_initialize): Initialize it. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16524 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/ccache/ChangeLog | 10 + src/lib/krb5/ccache/cc-int.h | 2 + src/lib/krb5/ccache/cc_memory.c | 383 ++++++++++++++++++-------------- src/lib/krb5/ccache/ccbase.c | 9 +- 4 files changed, 231 insertions(+), 173 deletions(-) diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog index d2d0a4920..9377ba66a 100644 --- a/src/lib/krb5/ccache/ChangeLog +++ b/src/lib/krb5/ccache/ChangeLog @@ -1,3 +1,13 @@ +2004-06-28 Ken Raeburn + + * cc_memory.c: Include k5-thread.h. + (krb5int_mcc_mutex): New lock. + (krb5_mcc_store): Rewrite. + (NEED_WINDOWS): Don't define. + (krb5_mcc_*): All functions now static. + * cc-int.h (krb5int_mcc_mutex): Declare. + * ccbase.c (krb5int_cc_initialize): Initialize it. + 2004-06-24 Ken Raeburn * cc_file.c (krb5_fcc_read_data): Combine stdio and posix versions diff --git a/src/lib/krb5/ccache/cc-int.h b/src/lib/krb5/ccache/cc-int.h index d890cf6ba..03342747d 100644 --- a/src/lib/krb5/ccache/cc-int.h +++ b/src/lib/krb5/ccache/cc-int.h @@ -42,4 +42,6 @@ krb5int_cc_initialize(void); void krb5int_cc_finalize(void); +extern k5_mutex_t krb5int_mcc_mutex; + #endif /* __KRB5_CCACHE_H__ */ diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c index c3aeb1e8b..31a586eaa 100644 --- a/src/lib/krb5/ccache/cc_memory.c +++ b/src/lib/krb5/ccache/cc_memory.c @@ -1,7 +1,7 @@ /* * lib/krb5/ccache/cc_memory.c * - * Copyright 1990,1991,2000 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2000,2004 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -26,78 +26,79 @@ * * implementation of memory-based credentials cache */ -/* - * mcc_store.c had: - * Copyright 1995 Locus Computing Corporation - * - */ #include "k5-int.h" #include -krb5_error_code KRB5_CALLCONV krb5_mcc_close +static krb5_error_code KRB5_CALLCONV krb5_mcc_close (krb5_context, krb5_ccache id ); -krb5_error_code KRB5_CALLCONV krb5_mcc_destroy +static krb5_error_code KRB5_CALLCONV krb5_mcc_destroy (krb5_context, krb5_ccache id ); -krb5_error_code KRB5_CALLCONV krb5_mcc_end_seq_get +static krb5_error_code KRB5_CALLCONV krb5_mcc_end_seq_get (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); -krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new +static krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new (krb5_context, krb5_ccache *id ); -const char * KRB5_CALLCONV krb5_mcc_get_name +static const char * KRB5_CALLCONV krb5_mcc_get_name (krb5_context, krb5_ccache id ); -krb5_error_code KRB5_CALLCONV krb5_mcc_get_principal +static krb5_error_code KRB5_CALLCONV krb5_mcc_get_principal (krb5_context, krb5_ccache id , krb5_principal *princ ); -krb5_error_code KRB5_CALLCONV krb5_mcc_initialize +static krb5_error_code KRB5_CALLCONV krb5_mcc_initialize (krb5_context, krb5_ccache id , krb5_principal princ ); -krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred +static krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor , krb5_creds *creds ); -krb5_error_code KRB5_CALLCONV krb5_mcc_resolve +static krb5_error_code KRB5_CALLCONV krb5_mcc_resolve (krb5_context, krb5_ccache *id , const char *residual ); -krb5_error_code KRB5_CALLCONV krb5_mcc_retrieve +static krb5_error_code KRB5_CALLCONV krb5_mcc_retrieve (krb5_context, krb5_ccache id , krb5_flags whichfields , krb5_creds *mcreds , krb5_creds *creds ); -krb5_error_code KRB5_CALLCONV krb5_mcc_start_seq_get +static krb5_error_code KRB5_CALLCONV krb5_mcc_start_seq_get (krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); -krb5_error_code KRB5_CALLCONV krb5_mcc_store +static krb5_error_code KRB5_CALLCONV krb5_mcc_store (krb5_context, krb5_ccache id , krb5_creds *creds ); -krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags +static krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags (krb5_context, krb5_ccache id , krb5_flags flags ); extern const krb5_cc_ops krb5_mcc_ops; -krb5_error_code krb5_change_cache (void); +extern krb5_error_code krb5_change_cache (void); #define KRB5_OK 0 typedef struct _krb5_mcc_link { - struct _krb5_mcc_link *next; - krb5_creds *creds; + struct _krb5_mcc_link *next; + krb5_creds *creds; } krb5_mcc_link, *krb5_mcc_cursor; typedef struct _krb5_mcc_data { - struct _krb5_mcc_data *next; - char *name; - krb5_principal prin; - krb5_mcc_cursor link; + char *name; + k5_mutex_t lock; + krb5_principal prin; + krb5_mcc_cursor link; } krb5_mcc_data; -static krb5_mcc_data *mcc_head = 0; +typedef struct krb5_mcc_list_node { + struct krb5_mcc_list_node *next; + krb5_mcc_data *cache; +} krb5_mcc_list_node; + +k5_mutex_t krb5int_mcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static krb5_mcc_list_node *mcc_head = 0; /* * Modifies: @@ -111,7 +112,7 @@ static krb5_mcc_data *mcc_head = 0; * system errors * permission errors */ -void krb5_mcc_free (krb5_context context, krb5_ccache id); +static void krb5_mcc_free (krb5_context context, krb5_ccache id); krb5_error_code KRB5_CALLCONV krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) @@ -120,7 +121,7 @@ krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) krb5_mcc_free(context, id); ret = krb5_copy_principal(context, princ, - &((krb5_mcc_data *)id->data)->prin); + &((krb5_mcc_data *)id->data)->prin); if (ret == KRB5_OK) krb5_change_cache(); return ret; @@ -145,17 +146,19 @@ krb5_mcc_close(krb5_context context, krb5_ccache id) void krb5_mcc_free(krb5_context context, krb5_ccache id) { - krb5_mcc_cursor curr,next; - - for (curr = ((krb5_mcc_data *)id->data)->link; curr;) - { + krb5_mcc_cursor curr,next; + krb5_mcc_data *d; + + d = (krb5_mcc_data *) id->data; + for (curr = d->link; curr;) { krb5_free_creds(context, curr->creds); next = curr->next; krb5_xfree(curr); curr = next; - } - ((krb5_mcc_data *)id->data)->link = NULL; - krb5_free_principal(context, ((krb5_mcc_data *)id->data)->prin); + } + d->link = NULL; + krb5_free_principal(context, d->prin); + k5_mutex_destroy(&d->lock); } /* @@ -168,29 +171,33 @@ krb5_mcc_free(krb5_context context, krb5_ccache id) krb5_error_code KRB5_CALLCONV krb5_mcc_destroy(krb5_context context, krb5_ccache id) { - krb5_mcc_data *curr; - - if (mcc_head && ((krb5_mcc_data *)id->data) == mcc_head) - mcc_head = mcc_head->next; - else { - for (curr=mcc_head; curr; curr=curr->next) - if (curr->next == ((krb5_mcc_data *)id->data)) { - curr->next = curr->next->next; - break; - } - } - - krb5_mcc_free(context, id); + krb5_mcc_list_node **curr, *node; + krb5_mcc_data *d; + krb5_error_code err; + + err = k5_mutex_lock(&krb5int_mcc_mutex); + if (err) + return err; + + d = (krb5_mcc_data *)id->data; + for (curr = &mcc_head; *curr; curr = &(*curr)->next) { + if ((*curr)->cache == d) { + node = *curr; + *curr = node->next; + free(node); + break; + } + } + k5_mutex_unlock(&krb5int_mcc_mutex); - krb5_xfree(((krb5_mcc_data *)id->data)->name); - krb5_xfree(id->data); - krb5_xfree(id); -#if 0 - --krb5_cache_sessions; -#endif + krb5_mcc_free(context, id); + krb5_xfree(d->name); + k5_mutex_destroy(&d->lock); + krb5_xfree(d); + krb5_xfree(id); - krb5_change_cache (); - return KRB5_OK; + krb5_change_cache (); + return KRB5_OK; } /* @@ -212,51 +219,42 @@ krb5_mcc_destroy(krb5_context context, krb5_ccache id) * krb5_ccache. id is undefined. * permission errors */ +static krb5_error_code new_mcc_data (const char *, krb5_mcc_data **); + krb5_error_code KRB5_CALLCONV krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) { - krb5_ccache lid; - krb5_mcc_data *ptr; - - - lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); - if (lid == NULL) - return KRB5_CC_NOMEM; - - lid->ops = &krb5_mcc_ops; - - for (ptr = mcc_head; ptr; ptr=ptr->next) - if (!strcmp(ptr->name, residual)) - break; - if (ptr) { - lid->data = ptr; - } else { - lid->data = (krb5_pointer) malloc(sizeof(krb5_mcc_data)); - if (lid->data == NULL) { - krb5_xfree(lid); - return KRB5_CC_NOMEM; - } + krb5_ccache lid; + krb5_mcc_list_node *ptr; + krb5_error_code err; + krb5_mcc_data *d; - ((krb5_mcc_data *) lid->data)->name = (char *) - malloc(strlen(residual) + 1); - if (((krb5_mcc_data *)lid->data)->name == NULL) { - krb5_xfree(((krb5_mcc_data *)lid->data)); - krb5_xfree(lid); + lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) return KRB5_CC_NOMEM; - } - strcpy(((krb5_mcc_data *)lid->data)->name, residual); - ((krb5_mcc_data *)lid->data)->link = 0L; - ((krb5_mcc_data *)lid->data)->prin = 0L; + lid->ops = &krb5_mcc_ops; - ((krb5_mcc_data *)lid->data)->next = mcc_head; - mcc_head = (krb5_mcc_data *)lid->data; -#if 0 - ++krb5_cache_sessions; -#endif - } - *id = lid; - return KRB5_OK; + err = k5_mutex_lock(&krb5int_mcc_mutex); + if (err) + return err; + for (ptr = mcc_head; ptr; ptr=ptr->next) + if (!strcmp(ptr->cache->name, residual)) + break; + if (ptr) + d = ptr->cache; + else { + err = new_mcc_data(residual, &d); + if (err) { + k5_mutex_unlock(&krb5int_mcc_mutex); + krb5_xfree(lid); + return err; + } + } + k5_mutex_unlock(&krb5int_mcc_mutex); + lid->data = d; + *id = lid; + return KRB5_OK; } /* @@ -273,11 +271,19 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) * system errors */ krb5_error_code KRB5_CALLCONV -krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id, + krb5_cc_cursor *cursor) { krb5_mcc_cursor mcursor; - - mcursor = ((krb5_mcc_data *)id->data)->link; + krb5_error_code err; + krb5_mcc_data *d; + + d = id->data; + err = k5_mutex_lock(&d->lock); + if (err) + return err; + mcursor = d->link; + k5_mutex_unlock(&d->lock); *cursor = (krb5_cc_cursor) mcursor; return KRB5_OK; } @@ -303,12 +309,16 @@ krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cur * system errors */ krb5_error_code KRB5_CALLCONV -krb5_mcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, krb5_creds *creds) +krb5_mcc_next_cred(krb5_context context, krb5_ccache id, + krb5_cc_cursor *cursor, krb5_creds *creds) { krb5_mcc_cursor mcursor; krb5_error_code retval; krb5_data *scratch; + /* Once the node in the linked list is created, it's never + modified, so we don't need to worry about locking here. (Note + that we don't support _remove_cred.) */ mcursor = (krb5_mcc_cursor) *cursor; if (mcursor == NULL) return KRB5_CC_END; @@ -383,6 +393,55 @@ krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *curso return KRB5_OK; } +/* Utility routine: Creates the back-end data for a memory cache, and + threads it into the global linked list. + + Call with the global list lock held. */ +static krb5_error_code +new_mcc_data (const char *name, krb5_mcc_data **dataptr) +{ + krb5_error_code err; + krb5_mcc_data *d; + krb5_mcc_list_node *n; + + d = malloc(sizeof(krb5_mcc_data)); + if (d == NULL) + return KRB5_CC_NOMEM; + + err = k5_mutex_init(&d->lock); + if (err) { + krb5_xfree(d); + return err; + } + + d->name = malloc(strlen(name) + 1); + if (d->name == NULL) { + k5_mutex_destroy(&d->lock); + krb5_xfree(d); + return KRB5_CC_NOMEM; + } + d->link = NULL; + d->prin = NULL; + + /* Set up the filename */ + strcpy(d->name, name); + + n = malloc(sizeof(krb5_mcc_list_node)); + if (n == NULL) { + free(d->name); + k5_mutex_destroy(&d->lock); + free(d); + return KRB5_CC_NOMEM; + } + + n->cache = d; + n->next = mcc_head; + mcc_head = n; + + *dataptr = d; + return 0; +} + /* * Effects: * Creates a new file cred cache whose name is guaranteed to be @@ -400,47 +459,35 @@ krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *curso krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new (krb5_context context, krb5_ccache *id) { - krb5_ccache lid; - char scratch[6+1]; /* 6 for the scratch part, +1 for NUL */ - - /* Allocate memory */ - lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); - if (lid == NULL) - return KRB5_CC_NOMEM; - - lid->ops = &krb5_mcc_ops; - - (void) strcpy(scratch, "XXXXXX"); - mktemp(scratch); - - lid->data = (krb5_pointer) malloc(sizeof(krb5_mcc_data)); - if (lid->data == NULL) { - krb5_xfree(lid); - return KRB5_CC_NOMEM; - } - - ((krb5_mcc_data *) lid->data)->name = (char *) - malloc(strlen(scratch) + 1); - if (((krb5_mcc_data *) lid->data)->name == NULL) { - krb5_xfree(((krb5_mcc_data *) lid->data)); - krb5_xfree(lid); - return KRB5_CC_NOMEM; - } - ((krb5_mcc_data *) lid->data)->link = NULL; - ((krb5_mcc_data *) lid->data)->prin = NULL; + krb5_ccache lid; + char scratch[6+1]; /* 6 for the scratch part, +1 for NUL */ + krb5_error_code err; + krb5_mcc_data *d; + + /* Allocate memory */ + lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) + return KRB5_CC_NOMEM; - /* Set up the filename */ - strcpy(((krb5_mcc_data *) lid->data)->name, scratch); + lid->ops = &krb5_mcc_ops; - *id = lid; -#if 0 - ++krb5_cache_sessions; -#endif - ((krb5_mcc_data *)lid->data)->next = mcc_head; - mcc_head = (krb5_mcc_data *)lid->data; + (void) strcpy(scratch, "XXXXXX"); + mktemp(scratch); - krb5_change_cache (); - return KRB5_OK; + err = k5_mutex_lock(&krb5int_mcc_mutex); + if (err) { + free(lid); + return err; + } + err = new_mcc_data(scratch, &d); + k5_mutex_unlock(&krb5int_mcc_mutex); + if (err) { + krb5_xfree(lid); + return err; + } + lid->data = d; + krb5_change_cache (); + return KRB5_OK; } /* @@ -473,8 +520,7 @@ krb5_error_code KRB5_CALLCONV krb5_mcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) { krb5_mcc_data *ptr = (krb5_mcc_data *)id->data; - if (!ptr->prin) - { + if (!ptr->prin) { *princ = 0L; return KRB5_FCC_NOFILE; } @@ -482,43 +528,13 @@ krb5_mcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *pri } krb5_error_code KRB5_CALLCONV -krb5_mcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds) +krb5_mcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, + krb5_creds *mcreds, krb5_creds *creds) { return krb5_cc_retrieve_cred_default (context, id, whichfields, mcreds, creds); } -#define CHECK(ret) if (ret != KRB5_OK) return ret; - -/* - * Modifies: - * the memory cache - * - * Effects: - * stores creds in the memory cred cache - * - * Errors: - * system errors - * storage failure errors - */ -krb5_error_code KRB5_CALLCONV -krb5_mcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds) -{ - krb5_error_code ret; - krb5_mcc_cursor mcursor; - - mcursor = (krb5_mcc_cursor)malloc(sizeof(krb5_mcc_link)); - if (mcursor == NULL) - return KRB5_CC_NOMEM; - ret = krb5_copy_creds(context, creds, &mcursor->creds); - if (ret == KRB5_OK) { - mcursor->next = ((krb5_mcc_data *)id->data)->link; - ((krb5_mcc_data *)id->data)->link = mcursor; - krb5_change_cache(); - } - return ret; -} - /* * Non-functional stub implementation for krb5_mcc_remove * @@ -550,7 +566,30 @@ krb5_mcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) return KRB5_OK; } -#define NEED_WINDOWS +/* store: Save away creds in the ccache. */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds) +{ + krb5_error_code err; + krb5_mcc_link *new_node; + krb5_mcc_data *mptr = (krb5_mcc_data *)id->data; + + new_node = malloc(sizeof(sizeof(krb5_mcc_link))); + if (new_node == NULL) + return errno; + err = krb5_copy_creds(ctx, creds, &new_node->creds); + if (err) { + free(new_node); + return err; + } + err = k5_mutex_lock(&mptr->lock); + if (err) + return err; + new_node->next = mptr->link; + mptr->link = new_node; + k5_mutex_unlock(&mptr->lock); + return 0; +} const krb5_cc_ops krb5_mcc_ops = { 0, diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c index d685ae14f..3d353209a 100644 --- a/src/lib/krb5/ccache/ccbase.c +++ b/src/lib/krb5/ccache/ccbase.c @@ -56,7 +56,14 @@ static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; int krb5int_cc_initialize(void) { - return k5_mutex_finish_init(&cc_typelist_lock); + int err; + err = k5_mutex_finish_init(&krb5int_mcc_mutex); + if (err) + return err; + err = k5_mutex_finish_init(&cc_typelist_lock); + if (err) + return err; + return 0; } void -- 2.26.2