Fixed the krb5_cc_gen_new memory ccache implementation and updated
authorAlexandra Ellwood <lxs@mit.edu>
Wed, 10 May 2006 21:48:53 +0000 (21:48 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Wed, 10 May 2006 21:48:53 +0000 (21:48 +0000)
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
src/lib/krb5/ccache/cc_memory.c
src/lib/krb5/krb/vfy_increds.c

index 657176b86a0a19d5f0e0d92f01b97396f1d8eeb5..b6c50f9f53a4f1599fcc611057d2b1487dc09267 100644 (file)
@@ -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 */
index 1417aabb7818db8524ee467715f1f3b112913f52..fd42710328df99cba02492d0fced945e783ead73 100644 (file)
@@ -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
index 62b535da90602b2283586d83e4892095616fca66..10a68f20ded91caab204e0dbfe3d1308e4777cb5 100644 (file)
@@ -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)