From 256446ab7fad68b15773d5fe8cc88b9abe3c461a Mon Sep 17 00:00:00 2001 From: Alexandra Ellwood Date: Wed, 10 May 2006 21:48:53 +0000 Subject: Fixed the krb5_cc_gen_new memory ccache implementation and updated krb5_verify_init_creds() and rd_and_store_for_creds() to use the API properly (possible now that it's been fixed). ticket: 3746 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17997 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/gssapi/krb5/accept_sec_context.c | 16 +++++--- src/lib/krb5/ccache/cc_memory.c | 65 ++++++++++++++++++++++++++++++-- src/lib/krb5/krb/vfy_increds.c | 14 +++++-- 3 files changed, 83 insertions(+), 12 deletions(-) diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c index 657176b..b6c50f9 100644 --- a/src/lib/gssapi/krb5/accept_sec_context.c +++ b/src/lib/gssapi/krb5/accept_sec_context.c @@ -93,6 +93,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred) { krb5_creds ** creds = NULL; krb5_error_code retval; + krb5_ccache template_ccache = NULL; krb5_ccache ccache = NULL; krb5_gss_cred_id_t cred = NULL; krb5_auth_context new_auth_ctx = NULL; @@ -136,9 +137,10 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred) /* Lots of kludging going on here... Some day the ccache interface will be rewritten though */ - if ((retval = krb5_cc_resolve(context, "MEMORY:GSSAPI", &ccache))) - goto cleanup; + if ((retval = krb5_cc_resolve(context, "MEMORY:GSSAPI", &template_ccache))) + goto cleanup; + ccache = template_ccache; /* krb5_cc_gen_new will replace so make a copy */ if ((retval = krb5_cc_gen_new(context, &ccache))) goto cleanup; @@ -182,8 +184,9 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred) cred->prerfc_mech = 1; /* this cred will work with all three mechs */ cred->rfc_mech = 1; cred->keytab = NULL; /* no keytab associated with this... */ - cred->ccache = ccache; /* but there is a credential cache */ cred->tgt_expire = creds[0]->times.endtime; /* store the end time */ + cred->ccache = ccache; /* the ccache containing the credential */ + ccache = NULL; /* cred takes ownership so don't destroy */ } /* If there were errors, there might have been a memory leak @@ -195,8 +198,11 @@ cleanup: if (creds) krb5_free_tgt_creds(context, creds); - if (!cred && ccache) - (void)krb5_cc_close(context, ccache); + if (template_ccache) + (void)krb5_cc_close(context, template_ccache); + + if (ccache) + (void)krb5_cc_destroy(context, ccache); if (out_cred) *out_cred = cred; /* return credential */ diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c index 1417aab..fd42710 100644 --- a/src/lib/krb5/ccache/cc_memory.c +++ b/src/lib/krb5/ccache/cc_memory.c @@ -440,6 +440,8 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr) return 0; } +static krb5_error_code random_string (krb5_context, char *, krb5_int32); + /* * Effects: * Creates a new file cred cache whose name is guaranteed to be @@ -454,13 +456,15 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr) * krb5_ccache. id is undefined. * system errors (from open) */ + 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 */ + char uniquename[8]; krb5_error_code err; krb5_mcc_data *d; + krb5_mcc_list_node *ptr; /* Allocate memory */ lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); @@ -469,25 +473,78 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id) lid->ops = &krb5_mcc_ops; - (void) strcpy(scratch, "XXXXXX"); - mktemp(scratch); + random_string (context, uniquename, sizeof (uniquename)); err = k5_mutex_lock(&krb5int_mcc_mutex); if (err) { free(lid); return err; } - err = new_mcc_data(scratch, &d); + + /* Check for uniqueness with mutex locked to avoid race conditions */ + while (1) { + for (ptr = mcc_head; ptr; ptr=ptr->next) { + if (!strcmp(ptr->cache->name, uniquename)) { + /* name already exists. Pick a new one and start over. */ + random_string (context, uniquename, sizeof (uniquename)); + ptr = mcc_head; + continue; + } + } + break; /* got a unique name. Stop. */ + } + + err = new_mcc_data(uniquename, &d); + k5_mutex_unlock(&krb5int_mcc_mutex); if (err) { krb5_xfree(lid); return err; } lid->data = d; + *id = lid; krb5_change_cache (); return KRB5_OK; } +/* Utility routine: Creates a random memory ccache name. + * This algorithm was selected because it creates readable + * random ccache names in a fixed size buffer. */ + +static krb5_error_code +random_string (krb5_context context, char *string, krb5_int32 length) +{ + static const unsigned char charlist[] = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + krb5_error_code err = 0; + u_int8_t *bytes = NULL; + size_t bytecount = length - 1; + + if (!err) { + bytes = malloc (bytecount); + if (bytes == NULL) { err = ENOMEM; } + } + + if (!err) { + krb5_data data; + data.length = bytecount; + data.data = (char *) bytes; + err = krb5_c_random_make_octets (context, &data); + } + + if (!err) { + krb5_int32 i; + for (i = 0; i < bytecount; i++) { + string [i] = charlist[bytes[i] % (sizeof (charlist) - 1)]; + } + string[length - 1] = '\0'; + } + + if (bytes != NULL) { free (bytes); } + + return err; +} + /* * Requires: * id is a file credential cache diff --git a/src/lib/krb5/krb/vfy_increds.c b/src/lib/krb5/krb/vfy_increds.c index 62b535d..10a68f2 100644 --- a/src/lib/krb5/krb/vfy_increds.c +++ b/src/lib/krb5/krb/vfy_increds.c @@ -60,6 +60,7 @@ krb5_verify_init_creds(krb5_context context, krb5_error_code ret; krb5_principal server; krb5_keytab keytab; + krb5_ccache template_ccache; krb5_ccache ccache; krb5_keytab_entry kte; krb5_creds in_creds, *out_creds; @@ -70,6 +71,7 @@ krb5_verify_init_creds(krb5_context context, server = NULL; keytab = NULL; + template_ccache = NULL; ccache = NULL; out_creds = NULL; authcon = NULL; @@ -137,10 +139,14 @@ krb5_verify_init_creds(krb5_context context, internals with a coherent idea of "in" and "out". */ /* insert the initial cred into the ccache */ - - if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req", &ccache))) + + if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req", &template_ccache))) goto cleanup; - + ccache = template_ccache; /* krb5_cc_gen_new will replace so make a copy */ + + if ((ret = krb5_cc_gen_new(context, &ccache))) + goto cleanup; + if ((ret = krb5_cc_initialize(context, ccache, creds->client))) goto cleanup; @@ -209,6 +215,8 @@ cleanup: krb5_free_principal(context, server); if (!keytab_arg && keytab) krb5_kt_close(context, keytab); + if (template_ccache) + krb5_cc_close(context, template_ccache); if (ccache) krb5_cc_destroy(context, ccache); if (out_creds) -- cgit v1.1