diff options
author | dfr <dfr@FreeBSD.org> | 2008-05-07 13:39:42 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-05-07 13:39:42 +0000 |
commit | 51b6601db456e699ea5d4843cbc7239ee92d9c13 (patch) | |
tree | 4dbb862199a916e3ffe75f1cb08703ec0e662ffc /crypto/heimdal/lib/krb5/keytab_memory.c | |
parent | 2565fa13487d5bfc858144e431e3dfd7ffa5200e (diff) | |
download | FreeBSD-src-51b6601db456e699ea5d4843cbc7239ee92d9c13.zip FreeBSD-src-51b6601db456e699ea5d4843cbc7239ee92d9c13.tar.gz |
Vendor import of Heimdal 1.1
Diffstat (limited to 'crypto/heimdal/lib/krb5/keytab_memory.c')
-rw-r--r-- | crypto/heimdal/lib/krb5/keytab_memory.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/crypto/heimdal/lib/krb5/keytab_memory.c b/crypto/heimdal/lib/krb5/keytab_memory.c index cde8943..0ad8720 100644 --- a/crypto/heimdal/lib/krb5/keytab_memory.c +++ b/crypto/heimdal/lib/krb5/keytab_memory.c @@ -33,26 +33,64 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_memory.c,v 1.5 2001/05/14 06:14:49 assar Exp $"); +RCSID("$Id: keytab_memory.c 16352 2005-12-05 18:39:46Z lha $"); /* memory operations -------------------------------------------- */ struct mkt_data { krb5_keytab_entry *entries; int num_entries; + char *name; + int refcount; + struct mkt_data *next; }; +/* this mutex protects mkt_head, ->refcount, and ->next + * content is not protected (name is static and need no protection) + */ +static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct mkt_data *mkt_head; + + static krb5_error_code mkt_resolve(krb5_context context, const char *name, krb5_keytab id) { struct mkt_data *d; - d = malloc(sizeof(*d)); + + HEIMDAL_MUTEX_lock(&mkt_mutex); + + for (d = mkt_head; d != NULL; d = d->next) + if (strcmp(d->name, name) == 0) + break; + if (d) { + if (d->refcount < 1) + krb5_abortx(context, "Double close on memory keytab, " + "refcount < 1 %d", d->refcount); + d->refcount++; + id->data = d; + HEIMDAL_MUTEX_unlock(&mkt_mutex); + return 0; + } + + d = calloc(1, sizeof(*d)); if(d == NULL) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->name = strdup(name); + if (d->name == NULL) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + free(d); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } d->entries = NULL; d->num_entries = 0; + d->refcount = 1; + d->next = mkt_head; + mkt_head = d; + HEIMDAL_MUTEX_unlock(&mkt_mutex); id->data = d; return 0; } @@ -60,8 +98,27 @@ mkt_resolve(krb5_context context, const char *name, krb5_keytab id) static krb5_error_code mkt_close(krb5_context context, krb5_keytab id) { - struct mkt_data *d = id->data; + struct mkt_data *d = id->data, **dp; int i; + + HEIMDAL_MUTEX_lock(&mkt_mutex); + if (d->refcount < 1) + krb5_abortx(context, + "krb5 internal error, memory keytab refcount < 1 on close"); + + if (--d->refcount > 0) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + return 0; + } + for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) { + if (*dp == d) { + *dp = d->next; + break; + } + } + HEIMDAL_MUTEX_unlock(&mkt_mutex); + + free(d->name); for(i = 0; i < d->num_entries; i++) krb5_kt_free_entry(context, &d->entries[i]); free(d->entries); @@ -75,7 +132,8 @@ mkt_get_name(krb5_context context, char *name, size_t namesize) { - strlcpy(name, "", namesize); + struct mkt_data *d = id->data; + strlcpy(name, d->name, namesize); return 0; } @@ -133,7 +191,13 @@ mkt_remove_entry(krb5_context context, { struct mkt_data *d = id->data; krb5_keytab_entry *e, *end; + int found = 0; + if (d->num_entries == 0) { + krb5_clear_error_string(context); + return KRB5_KT_NOTFOUND; + } + /* do this backwards to minimize copying */ for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) { if(krb5_kt_compare(context, e, entry->principal, @@ -143,10 +207,15 @@ mkt_remove_entry(krb5_context context, memset(end - 1, 0, sizeof(*end)); d->num_entries--; end--; + found = 1; } } + if (!found) { + krb5_clear_error_string (context); + return KRB5_KT_NOTFOUND; + } e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); - if(e != NULL) + if(e != NULL || d->num_entries == 0) d->entries = e; return 0; } |