Cleaned up CCAPI v3 code to remove memory leaks. Fixed crashes in
authorAlexandra Ellwood <lxs@mit.edu>
Tue, 11 Jul 2006 17:28:07 +0000 (17:28 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Tue, 11 Jul 2006 17:28:07 +0000 (17:28 +0000)
cc_ccache <-> krb5_ccache translation code.  Still testing edge cases but
the code seems to work now with the KfM CCAPI implementation.

ticket: 3936
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18327 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/ccache/ccapi/stdcc.c
src/lib/krb5/ccache/ccapi/stdcc.h
src/lib/krb5/ccache/ccapi/stdcc_util.c
src/lib/krb5/ccache/ccapi/stdcc_util.h

index 4414abfbc3c91b2e0f03a344f9a1f6feb485bfdf..277b29cdc2f7d6abaae5de779deee36aa8db85c3 100644 (file)
@@ -111,7 +111,7 @@ krb5_cc_ops krb5_cc_stdcc_ops = {
  * changes made.  We register a unique message type with which
  * we'll communicate to all other processes. 
  */
-void cache_changed()
+static void cache_changed()
 {
        static unsigned int message = 0;
        
@@ -122,7 +122,7 @@ void cache_changed()
 }
 #else /* _WIN32 */
 
-void cache_changed()
+static void cache_changed()
 {
        return;
 }
@@ -189,65 +189,48 @@ static const struct err_xlate err_xlate_table[] =
 
 static krb5_error_code cc_err_xlate(int err)
 {
-       const struct err_xlate *p;
-
+    const struct err_xlate *p;
+    
 #ifdef USE_CCAPI_V3
-       if (err == ccNoError)
-               return 0;
+    if (err == ccNoError)
+        return 0;
 #else
-        if (err == CC_NOERROR)
-               return 0;
+    if (err == CC_NOERROR)
+        return 0;
 #endif
-
-       for (p = err_xlate_table; p->cc_err; p++) {
-               if (err == p->cc_err)
-                       return p->krb5_err;
-       }
-       return KRB5_FCC_INTERNAL; /* XXX we need a miscellaneous return */
+    
+    for (p = err_xlate_table; p->cc_err; p++) {
+        if (err == p->cc_err)
+            return p->krb5_err;
+    }
+    return KRB5_FCC_INTERNAL; /* XXX we need a miscellaneous return */
 }
 
 
 #ifdef USE_CCAPI_V3
-static krb5_error_code stdccv3_setup(krb5_context context,
-                                    stdccCacheDataPtr ccapi_data)
+static krb5_error_code stdccv3_setup (krb5_context context,
+                                      stdccCacheDataPtr ccapi_data)
 {
-       cc_int32        err;
-
-       /* make sure the API has been intialized */
-       if (gCntrlBlock == NULL) {
-               err = cc_initialize(&gCntrlBlock, ccapi_version_max, NULL, NULL);
-               if (err != ccNoError)
-                       return cc_err_xlate(err);
-       }
-
-       /*
-        * No ccapi_data structure, so we don't need to make sure the
-        * ccache exists.
-        */
-       if (!ccapi_data)
-               return 0;
-
-       /*
-        * The ccache already exists
-        */
-       if (ccapi_data->NamedCache)
-               return 0;
-
-       err = cc_context_open_ccache(gCntrlBlock, ccapi_data->cache_name,
-                     &ccapi_data->NamedCache);
-       if (err == ccNoError)
-               return 0;
-
-       ccapi_data->NamedCache = NULL;
-       return cc_err_xlate(err);
+    krb5_error_code err = 0;
+    
+    if (!err && !gCntrlBlock) {
+        err = cc_initialize (&gCntrlBlock, ccapi_version_max, NULL, NULL);
+    }
+    
+    if (!err && ccapi_data && !ccapi_data->NamedCache) {
+        /* ccache has not been opened yet.  open it. */  
+        err = cc_context_open_ccache (gCntrlBlock, ccapi_data->cache_name,
+                                      &ccapi_data->NamedCache);
+    }
+    
+    return cc_err_xlate(err);
 }
 
 /* krb5_stdcc_shutdown is exported; use the old name */
 void krb5_stdcc_shutdown()
 {
-       if (gCntrlBlock)
-               cc_context_release(gCntrlBlock);
-       gCntrlBlock = NULL;
+    if (gCntrlBlock) { cc_context_release(gCntrlBlock); }
+    gCntrlBlock = NULL;
 }
 
 /*
@@ -256,58 +239,68 @@ void krb5_stdcc_shutdown()
  * create a new cache with a unique name, corresponds to creating a
  * named cache initialize the API here if we have to.
  */
-krb5_error_code KRB5_CALLCONV  krb5_stdccv3_generate_new 
-       (krb5_context context, krb5_ccache *id ) 
+krb5_error_code KRB5_CALLCONV  
+krb5_stdccv3_generate_new (krb5_context context, krb5_ccache *id ) 
 {
-       krb5_ccache             newCache = NULL;
-       krb5_error_code         retval;
-       stdccCacheDataPtr       ccapi_data = NULL;
-       char                    *name = NULL;
-       cc_time                 time;
-       int                     err;
-
-       if ((retval = stdccv3_setup(context, NULL)))
-               return retval;
-       
-       retval = KRB5_CC_NOMEM;
-       if (!(newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache))))
-               goto errout;
-       if (!(ccapi_data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData))))
-               goto errout;
-       if (!(name = malloc(256)))
-               goto errout;
-       
-       /* create a unique name */
-       if (retval = cc_context_get_change_time(gCntrlBlock, &time))
-               goto errout;
-       sprintf(name, "gen_new_cache%d", time);
-       
-       /* create the new cache */
-       err = cc_context_create_ccache(gCntrlBlock, name, cc_credentials_v5, 0L,
-                       &ccapi_data->NamedCache);
-       if (err != ccNoError) {
-               retval = cc_err_xlate(err);
-               goto errout;
-       }
-
-       /* setup some fields */
-       newCache->ops = &krb5_cc_stdcc_ops;
-       newCache->data = ccapi_data;
-       ccapi_data->cache_name = name;
-       
-       /* return a pointer to the new cache */
-       *id = newCache;
-               
-       return 0;
-
-errout:
-       if (newCache)
-               free(newCache);
-       if (ccapi_data)
-               free(ccapi_data);
-       if (name)
-               free(name);
-       return retval;
+    krb5_error_code err = 0;
+    krb5_ccache newCache = NULL;
+    stdccCacheDataPtr ccapi_data = NULL;
+    cc_ccache_t ccache = NULL;
+    cc_string_t ccstring = NULL;
+    char *name = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup(context, NULL);
+    }
+    
+    if (!err) {
+        newCache = (krb5_ccache) malloc (sizeof (*newCache));
+        if (!newCache) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data));
+        if (!ccapi_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = cc_context_create_new_ccache(gCntrlBlock, cc_credentials_v5, 0L,
+                                           &ccapi_data->NamedCache);
+    }
+    
+    if (!err) {
+        err = cc_ccache_get_name (ccapi_data->NamedCache, &ccstring);
+    }
+    
+    if (!err) {
+        name = (char *) malloc (sizeof (*name) * (strlen (ccstring->data) + 1));
+        if (!name) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        strcpy (name, ccstring->data);
+        ccapi_data->cache_name = name;
+        name = NULL; /* take ownership */
+        
+        ccapi_data->NamedCache = ccache;
+        ccache = NULL; /* take ownership */
+        
+        newCache->ops = &krb5_cc_stdcc_ops;
+        newCache->data = ccapi_data;
+        ccapi_data = NULL; /* take ownership */
+        
+        /* return a pointer to the new cache */
+        *id = newCache;
+        newCache = NULL;
+    }
+    
+    if (ccstring)   { cc_string_release (ccstring); }
+    if (name)       { free (name); }
+    if (ccache)     { cc_ccache_release (ccache); }
+    if (ccapi_data) { free (ccapi_data); }
+    if (newCache)   { free (newCache); }
+    
+    return cc_err_xlate (err);
 }
   
 /*
@@ -315,54 +308,58 @@ errout:
  *
  * create a new cache with the name stored in residual
  */
-krb5_error_code KRB5_CALLCONV  krb5_stdccv3_resolve 
-        (krb5_context context, krb5_ccache *id , const char *residual ) 
+krb5_error_code KRB5_CALLCONV  
+krb5_stdccv3_resolve (krb5_context context, krb5_ccache *id , const char *residual ) 
 {
-       krb5_ccache             newCache = NULL;
-       stdccCacheDataPtr       ccapi_data = NULL;
-       int                     err;
-       krb5_error_code         retval;
-       char                    *cName = NULL;
-       
-       if ((retval = stdccv3_setup(context, NULL)))
-               return retval;
-       
-       retval = KRB5_CC_NOMEM;
-       if (!(newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache))))
-               goto errout;
-       
-       if (!(ccapi_data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData))))
-               goto errout;
-
-       if (!(cName = malloc(strlen(residual)+1)))
-               goto errout;
-       
-       newCache->ops = &krb5_cc_stdcc_ops;
-       newCache->data = ccapi_data;
-       ccapi_data->cache_name = cName;
-
-       strcpy(cName, residual);
-       
-       err = cc_context_open_ccache(gCntrlBlock, cName,
-                                    &ccapi_data->NamedCache);
-        if (err != ccNoError) {
-               ccapi_data->NamedCache = NULL;
-               goto errout;
-       }
-
-       /* return new cache structure */
-       *id = newCache;
-       
-       return 0;
-       
-errout:
-       if (newCache)
-               free(newCache);
-       if (ccapi_data)
-               free(ccapi_data);
-       if (cName)
-               free(cName);
-       return retval;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = NULL;
+    krb5_ccache ccache = NULL;
+    char *name = NULL;
+    
+    if (id == NULL) { err = KRB5_CC_NOMEM; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, NULL);
+    }
+    
+    if (!err) {
+        ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data));
+        if (!ccapi_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        ccache = (krb5_ccache ) malloc (sizeof (*ccache));
+        if (!ccache) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        name = malloc (strlen(residual) + 1);
+        if (!name) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = cc_context_open_ccache (gCntrlBlock, residual,
+                                      &ccapi_data->NamedCache);
+    }
+
+    if (!err) {
+       strcpy(name, residual);        
+       ccapi_data->cache_name = name;
+        name = NULL; /* take ownership */
+
+       ccache->ops = &krb5_cc_stdcc_ops;
+       ccache->data = ccapi_data;
+        ccapi_data = NULL; /* take ownership */
+        
+        *id = ccache;
+        ccache = NULL; /* take ownership */
+    }
+    
+    if (ccache)     { free (ccache); }
+    if (ccapi_data) { free (ccapi_data); }
+    if (name)       { free (name); }
+    
+    return cc_err_xlate (err);
 }
   
 /*
@@ -372,43 +369,43 @@ errout:
  * principal if not set our principal to this principal. This
  * searching enables ticket sharing
  */
-krb5_error_code KRB5_CALLCONV  krb5_stdccv3_initialize 
-       (krb5_context context, krb5_ccache id,  krb5_principal princ) 
+krb5_error_code KRB5_CALLCONV  
+krb5_stdccv3_initialize (krb5_context context, 
+                         krb5_ccache id,  
+                         krb5_principal princ) 
 {
-       stdccCacheDataPtr       ccapi_data = NULL;
-       int                     err;
-       char                    *cName = NULL;
-       krb5_error_code         retval;
-       
-       if ((retval = stdccv3_setup(context, NULL)))
-               return retval;
-       
-       /* test id for null */
-       if (id == NULL) return KRB5_CC_NOMEM;
-       
-       if ((retval = krb5_unparse_name(context, princ, &cName)))
-               return retval;
-
-       ccapi_data = id->data;
-
-
-        if (ccapi_data->NamedCache) {
-               err = cc_ccache_release(ccapi_data->NamedCache);
-               ccapi_data->NamedCache = NULL;
-       }
-
-       err = cc_context_create_ccache(gCntrlBlock, ccapi_data->cache_name, 
-                                      cc_credentials_v5, cName,
-                                      &ccapi_data->NamedCache);
-       if (err != ccNoError) {
-               krb5_free_unparsed_name(context, cName);
-               return cc_err_xlate(err);
-       }
-
-       krb5_free_unparsed_name(context, cName);
-       cache_changed();
-       
-       return cc_err_xlate(err);
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    char *name = NULL;
+    
+    if (id == NULL) { err = KRB5_CC_NOMEM; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, NULL);
+    }
+    
+    if (!err) {
+        err = krb5_unparse_name(context, princ, &name);
+    }
+    
+    if (!err && ccapi_data->NamedCache) {
+        err = cc_ccache_release(ccapi_data->NamedCache);
+        ccapi_data->NamedCache = NULL;
+    }
+    
+    if (!err) {
+        err = cc_context_create_ccache (gCntrlBlock, ccapi_data->cache_name, 
+                                        cc_credentials_v5, name,
+                                        &ccapi_data->NamedCache);
+    }
+    
+    if (!err) {
+        cache_changed();
+    }
+    
+    if (name) { krb5_free_unparsed_name(context, name); }
+    
+    return cc_err_xlate(err);
 }
 
 /*
@@ -416,32 +413,34 @@ krb5_error_code KRB5_CALLCONV  krb5_stdccv3_initialize
  *
  * store some credentials in our cache
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_store 
-        (krb5_context context, krb5_ccache id, krb5_creds *creds )
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds )
 {
-       krb5_error_code         retval;
-       stdccCacheDataPtr       ccapi_data = id->data;
-       cc_credentials_t        c = NULL;
-       int err;
-
-       if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-       
-       /* copy the fields from the almost identical structures */
-       dupK5toCC3(context, creds, &c);
-                       
-       /*
-        * finally store the credential
-        * store will copy (that is duplicate) everything
-        */
-       err = cc_ccache_store_credentials(((stdccCacheDataPtr)(id->data))->NamedCache, c->data);
-       if (err != ccNoError)
-               return cc_err_xlate(err);
-             
-       err = cc_credentials_release(c);
-                
-       cache_changed();
-       return err;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_t credentials = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    if (!err) {
+        /* copy the fields from the almost identical structures */
+        err = copy_krb5_creds_to_cc_credentials (context, creds, &credentials);
+    }
+    
+    if (!err) {
+        err = cc_ccache_store_credentials (ccapi_data->NamedCache, 
+                                           credentials->data);
+    }
+    
+    if (!err) {
+        cache_changed();
+    }
+    
+    if (credentials) { cc_credentials_release (credentials); }
+    
+    return cc_err_xlate (err);
 }
 
 /*
@@ -449,23 +448,29 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_store
  *
  * begin an iterator call to get all of the credentials in the cache
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_start_seq_get 
-(krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor )
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_start_seq_get (krb5_context context, 
+                            krb5_ccache id, 
+                            krb5_cc_cursor *cursor )
 {
-       stdccCacheDataPtr               ccapi_data = id->data;
-       krb5_error_code                 retval;
-       int                             err;
-       cc_credentials_iterator_t       iterator;
-
-       if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-
-       err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache,
-                                                &iterator);
-       if (err != ccNoError)
-               return cc_err_xlate(err);
-       *cursor = iterator;
-       return 0;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_iterator_t iterator = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache,
+                                                 &iterator);
+    }
+    
+    if (!err) {
+        *cursor = iterator;
+    }
+    
+    return cc_err_xlate (err);
 }
 
 /*
@@ -474,37 +479,40 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_start_seq_get
  * - get the next credential in the cache as part of an iterator call
  * - this maps to call to cc_seq_fetch_creds
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_next_cred 
-        (krb5_context context, krb5_ccache id,  krb5_cc_cursor *cursor, 
-        krb5_creds *creds)
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_next_cred (krb5_context context, 
+                        krb5_ccache id, 
+                        krb5_cc_cursor *cursor, 
+                        krb5_creds *creds)
 {
-       krb5_error_code                 retval;
-       stdccCacheDataPtr               ccapi_data = id->data;
-       int                             err;
-       cc_credentials_t                cu;
-       cc_credentials_iterator_t       iterator;
-       
-       if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-       
-       iterator = *cursor;
-       if (iterator == 0)
-               return KRB5_CC_END;
-       err = cc_credentials_iterator_next(iterator, &cu);
-
-       if (err == ccIteratorEnd) {
-               cc_credentials_iterator_release(iterator);
-               *cursor = 0;
-       }
-       if (err != ccNoError)
-               return cc_err_xlate(err);
-       
-       /* copy data    (with translation) */
-       dupCC3toK5(context, cu, creds);
-       
-       cc_credentials_release(cu);
-       
-       return 0;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_t credentials = NULL;
+    cc_credentials_iterator_t iterator = *cursor;
+    
+    if (!iterator) { err = KRB5_CC_END; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    /* Note: CCAPI v3 ccaches can contain both v4 and v5 creds */
+    while (!err) {
+        err = cc_credentials_iterator_next (iterator, &credentials);
+
+        if (!err && (credentials->data->version == cc_credentials_v5)) {
+            copy_cc_credentials_to_krb5_creds(context, credentials, creds);
+            break;
+        }
+    }
+    
+    if (credentials) { cc_credentials_release (credentials); }
+    if (err == ccIteratorEnd) {
+        cc_credentials_iterator_release (iterator);
+        *cursor = 0;
+    }    
+    
+    return cc_err_xlate (err);
 }
 
 
@@ -514,12 +522,11 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_next_cred
  * - try to find a matching credential in the cache
  */
 krb5_error_code KRB5_CALLCONV
-krb5_stdccv3_retrieve(context, id, whichfields, mcreds, creds)
-   krb5_context context;
-   krb5_ccache id;
-   krb5_flags whichfields;
-   krb5_creds *mcreds;
-   krb5_creds *creds;
+krb5_stdccv3_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);
@@ -530,28 +537,26 @@ krb5_stdccv3_retrieve(context, id, whichfields, mcreds, creds)
  *
  * just free up the storage assoicated with the cursor (if we can)
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_end_seq_get 
-        (krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_end_seq_get (krb5_context context, 
+                          krb5_ccache id, 
+                          krb5_cc_cursor *cursor)
 {
-       krb5_error_code                 retval;
-       stdccCacheDataPtr               ccapi_data = NULL;
-       int                             err;
-        cc_credentials_iterator_t      iterator;
-
-       ccapi_data = id->data;
-       
-        if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-
-       if (*cursor == NULL)
-               return 0;
-
-        iterator = *cursor;
-
-       err = cc_credentials_iterator_release(iterator);
-       if (err != ccNoError)
-               return cc_err_xlate(err);
-       return(0);
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_iterator_t iterator = *cursor;
+    
+    if (!iterator) { return 0; }
+    
+    if (!err) {
+        err = stdccv3_setup (context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = cc_credentials_iterator_release(iterator);
+    }
+    
+    return cc_err_xlate(err);
 }
      
 /*
@@ -560,26 +565,31 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_end_seq_get
  * - free our pointers to the NC
  */
 krb5_error_code KRB5_CALLCONV 
-krb5_stdccv3_close(krb5_context context, krb5_ccache id)
+krb5_stdccv3_close(krb5_context context, 
+                   krb5_ccache id)
 {
-       krb5_error_code retval;
-       stdccCacheDataPtr       ccapi_data = id->data;
-
-       if ((retval = stdccv3_setup(context, NULL)))
-               return retval;
-       
-       /* free it */
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    if (!err) {
+        err = stdccv3_setup (context, NULL);
+    }
+    
+    if (!err) {
        if (ccapi_data) {
-               if (ccapi_data->cache_name)
-                       free(ccapi_data->cache_name);
-               if (ccapi_data->NamedCache)
-                       cc_ccache_release(ccapi_data->NamedCache);
-               free(ccapi_data);
-               id->data = NULL;
+            if (ccapi_data->cache_name) { 
+                free (ccapi_data->cache_name); 
+            }
+            if (ccapi_data->NamedCache) { 
+                err = cc_ccache_release (ccapi_data->NamedCache); 
+            }
+            free (ccapi_data);
+            id->data = NULL;
        }
-       free(id);
-       
-       return 0;
+       free (id);        
+    }
+    
+    return cc_err_xlate(err);
 }
 
 /*
@@ -588,37 +598,36 @@ krb5_stdccv3_close(krb5_context context, krb5_ccache id)
  * - free our storage and the cache
  */
 krb5_error_code KRB5_CALLCONV
-krb5_stdccv3_destroy (krb5_context context, krb5_ccache id)
+krb5_stdccv3_destroy (krb5_context context, 
+                      krb5_ccache id)
 {
-       int err;
-       krb5_error_code retval;
-       stdccCacheDataPtr       ccapi_data = id->data;
-
-       if ((retval = stdccv3_setup(context, ccapi_data))) {
-               return retval;
-       }
-
-       /* free memory associated with the krb5_ccache */
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+   
+    if (!err) {
+        err = stdccv3_setup(context, ccapi_data);
+    }
+    
+    if (!err) {
        if (ccapi_data) {
-               if (ccapi_data->cache_name)
-                       free(ccapi_data->cache_name);
-               if (ccapi_data->NamedCache) {
-                       /* destroy the named cache */
-                       err = cc_ccache_destroy(ccapi_data->NamedCache);
-                       retval = cc_err_xlate(err);
-                       cache_changed();
-               }
-               free(ccapi_data);
-               id->data = NULL;
+            if (ccapi_data->cache_name) { 
+                free(ccapi_data->cache_name); 
+            }
+            if (ccapi_data->NamedCache) {
+                /* destroy the named cache */
+                err = cc_ccache_destroy(ccapi_data->NamedCache);
+                if (err == ccErrCCacheNotFound) { 
+                    err = 0; /* ccache maybe already destroyed */
+                }
+                cache_changed();
+            }
+            free(ccapi_data);
+            id->data = NULL;
        }
-       free(id);
-
-       /* If the cache does not exist when we tried to destroy it,
-          that's fine.  That means someone else destroyed it since
-          we resolved it. */
-       if (retval == ccErrCCacheNotFound)
-               return 0;
-       return retval;
+       free(id);        
+    }
+    
+    return cc_err_xlate(err);
 }
 
 /*
@@ -626,15 +635,17 @@ krb5_stdccv3_destroy (krb5_context context, krb5_ccache id)
  *
  * - return the name of the named cache
  */
-const char * KRB5_CALLCONV krb5_stdccv3_get_name 
-        (krb5_context context, krb5_ccache id )
+const char * KRB5_CALLCONV 
+krb5_stdccv3_get_name (krb5_context context, 
+                       krb5_ccache id )
 {
-       stdccCacheDataPtr       ccapi_data = id->data;
-
-       if (!ccapi_data)
-               return 0;
-
-       return (ccapi_data->cache_name);
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    if (!ccapi_data) {
+        return NULL;
+    } else {
+        return (ccapi_data->cache_name);
+    }
 }
 
 
@@ -642,29 +653,30 @@ const char * KRB5_CALLCONV krb5_stdccv3_get_name
  *
  * - return the principal associated with the named cache
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_principal
-       (krb5_context context, krb5_ccache id , krb5_principal *princ) 
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_get_principal (krb5_context context, 
+                            krb5_ccache id , 
+                            krb5_principal *princ) 
 {
-       int                     err;
-       cc_string_t             name = NULL;
-       stdccCacheDataPtr       ccapi_data = id->data;
-       krb5_error_code         retval;
-       
-       if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-
-       /* another wrapper */
-       err = cc_ccache_get_principal(ccapi_data->NamedCache, cc_credentials_v5, &name);
-
-       if (err != ccNoError) 
-               return cc_err_xlate(err);
-               
-       /* turn it into a krb principal */
-       err = krb5_parse_name(context, name->data, princ);
-
-       cc_string_release(name);
-       
-       return err;     
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_string_t name = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup(context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = cc_ccache_get_principal (ccapi_data->NamedCache, cc_credentials_v5, &name);
+    }
+    
+    if (!err) {
+        err = krb5_parse_name (context, name->data, princ);
+    }
+    
+    if (name) { cc_string_release (name); }
+    
+    return cc_err_xlate (err);
 }
 
 /*
@@ -672,16 +684,17 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_principal
  *
  * - currently a NOP since we don't store any flags in the NC
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_set_flags 
-        (krb5_context context, krb5_ccache id , krb5_flags flags)
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_set_flags (krb5_context context, 
+                        krb5_ccache id, 
+                        krb5_flags flags)
 {
-       stdccCacheDataPtr       ccapi_data = id->data;
-       krb5_error_code         retval;
-       
-       if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-
-       return 0;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    err = stdccv3_setup (context, ccapi_data);
+    
+    return cc_err_xlate (err);
 }
 
 /*
@@ -689,16 +702,17 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_set_flags
  *
  * - currently a NOP since we don't store any flags in the NC
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_flags 
-        (krb5_context context, krb5_ccache id , krb5_flags *flags)
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_get_flags (krb5_context context, 
+                        krb5_ccache id, 
+                        krb5_flags *flags)
 {
-       stdccCacheDataPtr       ccapi_data = id->data;
-       krb5_error_code         retval;
-       
-       if ((retval = stdccv3_setup(context, ccapi_data)))
-               return retval;
-
-       return 0;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    
+    err = stdccv3_setup (context, ccapi_data);
+    
+    return cc_err_xlate (err);
 }
 
 /*
@@ -706,37 +720,41 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_flags
  *
  * - remove the specified credentials from the NC
  */
-krb5_error_code KRB5_CALLCONV krb5_stdccv3_remove 
-        (krb5_context context, krb5_ccache id,
-        krb5_flags flags, krb5_creds *creds)
+krb5_error_code KRB5_CALLCONV 
+krb5_stdccv3_remove (krb5_context context, 
+                     krb5_ccache id,
+                     krb5_flags flags, 
+                     krb5_creds *creds)
 {
-       cc_credentials_t        c = NULL;
-       int                     err;
-       stdccCacheDataPtr       ccapi_data = id->data;
-       krb5_error_code         retval;
-       
-       if ((retval = stdccv3_setup(context, ccapi_data))) {
-               if (retval == KRB5_FCC_NOFILE)
-                       return 0;
-               return retval;
-       }
-       
-       /* convert to a cred union */
-       dupK5toCC3(context, creds, &c);
-       
-       /* remove it */
-       err = cc_ccache_remove_credentials(ccapi_data->NamedCache, c);
-       if (err != ccNoError)
-               return cc_err_xlate(err);
-       
-       err = cc_credentials_release(c);
-       cache_changed();
-       if (err != ccNoError)
-               return cc_err_xlate(err);
-
-        return 0;
+    krb5_error_code err = 0;
+    stdccCacheDataPtr ccapi_data = id->data;
+    cc_credentials_t credentials = NULL;
+    
+    if (!err) {
+        err = stdccv3_setup(context, ccapi_data);
+    }
+    
+    if (!err) {
+        err = copy_krb5_creds_to_cc_credentials (context, creds, &credentials);
+    }
+    
+    if (!err) {
+        err = cc_ccache_remove_credentials (ccapi_data->NamedCache, credentials);
+    }
+    
+    if (!err) {
+        cache_changed ();
+    } else if (err == KRB5_FCC_NOFILE) {
+        err = 0;
+    }
+    
+    if (credentials) { cc_credentials_release (credentials); }
+    
+    return cc_err_xlate (err);
 }
+
 #else /* !USE_CCAPI_V3 */
+
 static krb5_error_code stdcc_setup(krb5_context context,
                                   stdccCacheDataPtr ccapi_data)
 {
@@ -797,7 +815,7 @@ krb5_error_code KRB5_CALLCONV  krb5_stdcc_generate_new
        krb5_error_code         retval;
        stdccCacheDataPtr       ccapi_data = NULL;
        char                    *name = NULL;
-       cc_time_t               time;
+       cc_time_t               change_time;
        int                     err;
 
        if ((retval = stdcc_setup(context, NULL)))
@@ -812,8 +830,8 @@ krb5_error_code KRB5_CALLCONV  krb5_stdcc_generate_new
                goto errout;
        
        /* create a unique name */
-       cc_get_change_time(gCntrlBlock, &time);
-       sprintf(name, "gen_new_cache%d", time);
+       cc_get_change_time(gCntrlBlock, &change_time);
+       sprintf(name, "gen_new_cache%d", change_time);
        
        /* create the new cache */
        err = cc_create(gCntrlBlock, name, name, CC_CRED_V5, 0L,
@@ -878,9 +896,11 @@ krb5_error_code KRB5_CALLCONV  krb5_stdcc_resolve
        
        err = cc_open(gCntrlBlock, cName, CC_CRED_V5, 0L,
                      &ccapi_data->NamedCache);
-        if (err != CC_NOERROR)
+        if (err != CC_NOERROR) {
                ccapi_data->NamedCache = NULL;
-
+               goto errout;
+        }
+        
        /* return new cache structure */
        *id = newCache;
        
@@ -1358,4 +1378,4 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_remove
 
         return 0;
 }
-#endif /* !USE_CCAPI_V3 */
\ No newline at end of file
+#endif /* !USE_CCAPI_V3 */
index c0ce13b420494017b98d9cf61efc37a6a22c6c31..03948d1a848fe23a9ac3156c6a5f2a585ce5587e 100644 (file)
@@ -141,4 +141,4 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_get_flags
 
 krb5_error_code KRB5_CALLCONV krb5_stdcc_remove 
         (krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds);
-#endif
\ No newline at end of file
+#endif
index 1969b6e718af29341818d82741be5cb263d99b5c..2e6538ccaf3438985a6db9eb0e0acfddc3978c97 100644 (file)
 /* krb5int_cc_credentials_release(cc_credentials_t creds)
  * - function used to release internally generated cc_credentials_t objects
  */
+
+static void 
+free_cc_array (cc_data **io_cc_array)
+{
+    if (io_cc_array) {
+        unsigned int i;
+        
+        for (i = 0; io_cc_array[i]; i++) {
+            if (io_cc_array[i]->data) { free (io_cc_array[i]->data); }
+            free (io_cc_array[i]);
+        }
+        free (io_cc_array);
+    }    
+}
+
 static cc_int32 
-krb5int_cc_credentials_release(cc_credentials_t creds) {
-    free(creds);
+krb5int_cc_credentials_release(cc_credentials_t creds) 
+{
+    if (creds) {
+        if (creds->data) {
+            if (creds->data->version == cc_credentials_v5 &&
+                creds->data->credentials.credentials_v5) {
+                cc_credentials_v5_t *cv5 = creds->data->credentials.credentials_v5;
+                
+                /* should use krb5_free_unparsed_name but we have no context */
+                if (cv5->client) { free (cv5->client); }
+                if (cv5->server) { free (cv5->server); }
+                
+                if (cv5->keyblock.data)      { free (cv5->keyblock.data); }
+                if (cv5->ticket.data)        { free (cv5->ticket.data); }
+                if (cv5->second_ticket.data) { free (cv5->second_ticket.data); }
+                
+                free_cc_array (cv5->addresses);
+                free_cc_array (cv5->authdata);
+                
+                free (cv5);
+                
+            } else if (creds->data->version == cc_credentials_v4 &&
+                       creds->data->credentials.credentials_v4) {
+                free (creds->data->credentials.credentials_v4);
+            }
+            free ((cc_credentials_union *) creds->data);
+        }
+        free(creds);
+    }
+    
     return ccNoError;
 }
 
@@ -36,381 +79,488 @@ krb5int_cc_credentials_compare(cc_credentials_t creds,
     return ccErrNotImplemented;
 }
 
-/*
- * CopyCC3DataArrayToK5
- * - copy and translate the null terminated arrays of data records
- *      used in k5 tickets
- */
-int 
-copyCC3DataArrayToK5(cc_credentials_v5_t *ccCreds, krb5_creds *v5Creds, char whichArray) {
-
-    switch (whichArray) {
-    case kAddressArray: 
-       if (ccCreds->addresses == NULL) {
-           v5Creds->addresses = NULL;
-       } else {
-
-           krb5_address        **addrPtr, *addr;
-           cc_data             **dataPtr, *data;
-           unsigned int        numRecords = 0;
-
-           /* Allocate the array of pointers: */
-           for (dataPtr = ccCreds->addresses; *dataPtr != NULL; numRecords++, dataPtr++) {}
-
-           v5Creds->addresses = (krb5_address **) malloc (sizeof(krb5_address *) * (numRecords + 1));
-           if (v5Creds->addresses == NULL)
-               return ENOMEM;
-
-           /* Fill in the array, allocating the address structures: */
-           for (dataPtr = ccCreds->addresses, addrPtr = v5Creds->addresses; *dataPtr != NULL; addrPtr++, dataPtr++) {
-
-               *addrPtr = (krb5_address *) malloc (sizeof(krb5_address));
-               if (*addrPtr == NULL)
-                   return ENOMEM;
-               data = *dataPtr;
-               addr = *addrPtr;
-
-               addr->addrtype = data->type;
-               addr->magic    = KV5M_ADDRESS;
-               addr->length   = data->length;
-               addr->contents = (krb5_octet *) malloc (sizeof(krb5_octet) * addr->length);
-               if (addr->contents == NULL)
-                   return ENOMEM;
-               memmove(addr->contents, data->data, addr->length); /* copy contents */
-           }
-
-           /* Write terminator: */
-           *addrPtr = NULL;
-       }
-       break;
-    case kAuthDataArray:
-       if (ccCreds->authdata == NULL) {
-           v5Creds->authdata = NULL;
-       } else {
-           krb5_authdata       **authPtr, *auth;
-           cc_data             **dataPtr, *data;
-           unsigned int        numRecords = 0;
-
-           /* Allocate the array of pointers: */
-           for (dataPtr = ccCreds->authdata; *dataPtr != NULL; numRecords++, dataPtr++) {}
-
-           v5Creds->authdata = (krb5_authdata **) malloc (sizeof(krb5_authdata *) * (numRecords + 1));
-           if (v5Creds->authdata == NULL)
-               return ENOMEM;
-
-           /* Fill in the array, allocating the address structures: */
-           for (dataPtr = ccCreds->authdata, authPtr = v5Creds->authdata; *dataPtr != NULL; authPtr++, dataPtr++) {
-
-               *authPtr = (krb5_authdata *) malloc (sizeof(krb5_authdata));
-               if (*authPtr == NULL)
-                   return ENOMEM;
-               data = *dataPtr;
-               auth = *authPtr;
-
-               auth->ad_type  = data->type;
-               auth->magic    = KV5M_AUTHDATA;
-               auth->length   = data->length;
-               auth->contents = (krb5_octet *) malloc (sizeof(krb5_octet) * auth->length);
-               if (auth->contents == NULL)
-                   return ENOMEM;
-               memmove(auth->contents, data->data, auth->length); /* copy contents */
-           }
-
-           /* Write terminator: */
-           *authPtr = NULL;
-       }
-       break;
+static krb5_error_code 
+copy_cc_array_to_addresses (krb5_context in_context, 
+                            cc_data **in_cc_array, 
+                            krb5_address ***out_addresses)
+{
+    krb5_error_code err = 0;
+    
+    if (in_cc_array == NULL) {
+        *out_addresses = NULL;
+        
+    } else {
+        unsigned int count, i;
+        krb5_address **addresses = NULL;
+
+        /* get length of array */
+        for (count = 0; in_cc_array[count]; count++);
+        addresses = (krb5_address **) malloc (sizeof (*addresses) * (count + 1));
+        if (!addresses) { err = KRB5_CC_NOMEM; }
+        
+        for (i = 0; !err && i < count; i++) { 
+            addresses[i] = (krb5_address *) malloc (sizeof (krb5_address));
+            if (!addresses[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                addresses[i]->contents = (krb5_octet *) malloc (sizeof (krb5_octet) * 
+                                                            in_cc_array[i]->length);
+                if (!addresses[i]->contents) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                addresses[i]->magic = KV5M_ADDRESS;
+                addresses[i]->addrtype = in_cc_array[i]->type;
+                addresses[i]->length = in_cc_array[i]->length;
+                memcpy (addresses[i]->contents, 
+                        in_cc_array[i]->data, in_cc_array[i]->length);
+            }
+        }
+        
+        if (!err) {
+            addresses[i] = NULL; /* terminator */
+            *out_addresses = addresses;
+            addresses = NULL;
+        }
+
+        if (addresses) { krb5_free_addresses (in_context, addresses); }
     }
-
-    return 0;
+    
+    return err;
 }
 
-/*
- * copyK5DataArrayToCC
- * - analagous to above, but in the other direction
- */
-int 
-copyK5DataArrayToCC3(krb5_creds *v5Creds, cc_credentials_v5_t * ccCreds, char whichArray)
+static krb5_error_code 
+copy_cc_array_to_authdata (krb5_context in_context, 
+                           cc_data **in_cc_array, 
+                           krb5_authdata ***out_authdata)
 {
-    switch (whichArray) {
-    case kAddressArray:
-       if (v5Creds->addresses == NULL) {
-           ccCreds->addresses = NULL;
-       } else {
-
-           krb5_address        **addrPtr, *addr;
-           cc_data             **dataPtr, *data;
-           unsigned int        numRecords = 0;
-
-           /* Allocate the array of pointers: */
-           for (addrPtr = v5Creds->addresses; *addrPtr != NULL; numRecords++, addrPtr++) {}
-
-           ccCreds->addresses = (cc_data **) malloc (sizeof(cc_data *) * (numRecords + 1));
-           if (ccCreds->addresses == NULL)
-               return ENOMEM;
-
-           /* Fill in the array, allocating the address structures: */
-           for (dataPtr = ccCreds->addresses, addrPtr = v5Creds->addresses; *addrPtr != NULL; addrPtr++, dataPtr++) {
-
-               *dataPtr = (cc_data *) malloc (sizeof(cc_data));
-               if (*dataPtr == NULL)
-                   return ENOMEM;
-               data = *dataPtr;
-               addr = *addrPtr;
-
-               data->type   = addr->addrtype;
-               data->length = addr->length;
-               data->data   = malloc (sizeof(char) * data->length);
-               if (data->data == NULL)
-                   return ENOMEM;
-               memmove(data->data, addr->contents, data->length); /* copy contents */
-           }
-
-           /* Write terminator: */
-           *dataPtr = NULL;
-       }
-       break;
-    case kAuthDataArray:
-       if (v5Creds->authdata == NULL) {
-           ccCreds->authdata = NULL;
-       } else {
-           krb5_authdata       **authPtr, *auth;
-           cc_data                     **dataPtr, *data;
-           unsigned int                        numRecords = 0;
-
-           /* Allocate the array of pointers: */
-           for (authPtr = v5Creds->authdata; *authPtr != NULL; numRecords++, authPtr++) {}
-
-           ccCreds->authdata = (cc_data **) malloc (sizeof(cc_data *) * (numRecords + 1));
-           if (ccCreds->authdata == NULL)
-               return ENOMEM;
-
-           /* Fill in the array, allocating the address structures: */
-           for (dataPtr = ccCreds->authdata, authPtr = v5Creds->authdata; *authPtr != NULL; authPtr++, dataPtr++) {
-
-               *dataPtr = (cc_data *) malloc (sizeof(cc_data));
-               if (*dataPtr == NULL)
-                   return ENOMEM;
-               data = *dataPtr;
-               auth = *authPtr;
-
-               data->type   = auth->ad_type;
-               data->length = auth->length;
-               data->data   = malloc (sizeof(char) * data->length);
-               if (data->data == NULL)
-                   return ENOMEM;
-               memmove(data->data, auth->contents, data->length); /* copy contents */
-           }
+    krb5_error_code err = 0;
+    
+    if (in_cc_array == NULL) {
+        *out_authdata = NULL;
+        
+    } else {
+        unsigned int count, i;
+        krb5_authdata **authdata = NULL;
+        
+        /* get length of array */
+        for (count = 0; in_cc_array[count]; count++);
+        authdata = (krb5_authdata **) malloc (sizeof (*authdata) * (count + 1));
+        if (!authdata) { err = KRB5_CC_NOMEM; }
+        
+        for (i = 0; !err && i < count; i++) { 
+            authdata[i] = (krb5_authdata *) malloc (sizeof (krb5_authdata));
+            if (!authdata[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                authdata[i]->contents = (krb5_octet *) malloc (sizeof (krb5_octet) * 
+                                                           in_cc_array[i]->length);
+                if (!authdata[i]->contents) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                authdata[i]->magic = KV5M_AUTHDATA;
+                authdata[i]->ad_type = in_cc_array[i]->type;
+                authdata[i]->length = in_cc_array[i]->length;
+                memcpy (authdata[i]->contents, 
+                        in_cc_array[i]->data, in_cc_array[i]->length);
+            }
+        }
+        
+        if (!err) {
+            authdata[i] = NULL; /* terminator */
+            *out_authdata = authdata;
+            authdata = NULL;
+        }
+        
+        if (authdata) { krb5_free_authdata (in_context, authdata); }
+    }
+    
+    return err;
+}
 
-           /* Write terminator: */
-           *dataPtr = NULL;
-       }
-       break;
+static krb5_error_code 
+copy_addresses_to_cc_array (krb5_context in_context, 
+                            krb5_address **in_addresses, 
+                            cc_data ***out_cc_array)
+{
+    krb5_error_code err = 0;
+    
+    if (in_addresses == NULL) {
+        *out_cc_array = NULL;
+        
+    } else {
+        unsigned int count, i;
+        cc_data **cc_array = NULL;
+
+        /* get length of array */
+        for (count = 0; in_addresses[count]; count++);
+        cc_array = (cc_data **) malloc (sizeof (*cc_array) * (count + 1));
+        if (!cc_array) { err = KRB5_CC_NOMEM; }
+    
+        for (i = 0; !err && i < count; i++) { 
+            cc_array[i] = (cc_data *) malloc (sizeof (cc_data));
+            if (!cc_array[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                cc_array[i]->data = malloc (in_addresses[i]->length);
+                if (!cc_array[i]->data) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                cc_array[i]->type = in_addresses[i]->addrtype;
+                cc_array[i]->length = in_addresses[i]->length;
+                memcpy (cc_array[i]->data, in_addresses[i]->contents, in_addresses[i]->length);
+            }
+        }
+        
+        if (!err) {
+            cc_array[i] = NULL; /* terminator */
+            *out_cc_array = cc_array;
+            cc_array = NULL;
+        }
+
+        if (cc_array) { free_cc_array (cc_array); }
     }
+    
+    
+    return err;
+}
 
-    return 0;
+static krb5_error_code 
+copy_authdata_to_cc_array (krb5_context in_context, 
+                           krb5_authdata **in_authdata, 
+                           cc_data ***out_cc_array)
+{
+    krb5_error_code err = 0;
+    
+    if (in_authdata == NULL) {
+        *out_cc_array = NULL;
 
+    } else {
+        unsigned int count, i;
+        cc_data **cc_array = NULL;
+
+        /* get length of array */
+        for (count = 0; in_authdata[count]; count++);
+        cc_array = (cc_data **) malloc (sizeof (*cc_array) * (count + 1));
+        if (!cc_array) { err = KRB5_CC_NOMEM; }
+    
+        for (i = 0; !err && i < count; i++) { 
+            cc_array[i] = (cc_data *) malloc (sizeof (cc_data));
+            if (!cc_array[i]) { err = KRB5_CC_NOMEM; }
+            
+            if (!err) {
+                cc_array[i]->data = malloc (in_authdata[i]->length);
+                if (!cc_array[i]->data) { err = KRB5_CC_NOMEM; }
+            }
+            
+            if (!err) {
+                cc_array[i]->type = in_authdata[i]->ad_type;
+                cc_array[i]->length = in_authdata[i]->length;
+                memcpy (cc_array[i]->data, in_authdata[i]->contents, in_authdata[i]->length);
+            }
+        }
+        
+        if (!err) {
+            cc_array[i] = NULL; /* terminator */
+            *out_cc_array = cc_array;
+            cc_array = NULL;
+        }
+
+        if (cc_array) { free_cc_array (cc_array); }
+    }
+    
+    
+    return err;
 }
 
+
 /*
- * dupCC3toK5
+ * copy_cc_credentials_to_krb5_creds
  * - allocate an empty k5 style ticket and copy info from the cc_creds ticket
  */
 
-krb5_error_code
-dupCC3toK5(krb5_context context, cc_credentials_t src, krb5_creds *dest)
+krb5_error_code 
+copy_cc_credentials_to_krb5_creds (krb5_context in_context, 
+                                   cc_credentials_t in_credentials, 
+                                   krb5_creds *out_creds)
 {
-    const cc_credentials_union         *cu = src->data;
-    cc_credentials_v5_t                *cv5;
+    krb5_error_code err = 0;
+    const cc_credentials_union *cred_union = in_credentials->data;
+    cc_credentials_v5_t *cv5 = NULL;
     krb5_int32 offset_seconds = 0, offset_microseconds = 0;
-    krb5_error_code err;
-
-    if (cu->version != cc_credentials_v5) 
-       return KRB5_CC_NOT_KTYPE;
-
-    cv5 = cu->credentials.credentials_v5;
-
-    /*
-     * allocate and copy
-     * copy all of those damn fields back
-     */
-    err = krb5_parse_name(context, cv5->client, &(dest->client));
-    err = krb5_parse_name(context, cv5->server, &(dest->server));
-    if (err) 
-       return err; /* parsename fails w/o krb5.ini for example */
-
-    /* copy keyblock */
-    dest->keyblock.enctype = cv5->keyblock.type;
-    dest->keyblock.length = cv5->keyblock.length;
-    dest->keyblock.contents = (krb5_octet *)malloc(dest->keyblock.length);
-    memcpy(dest->keyblock.contents, cv5->keyblock.data, dest->keyblock.length);
-
-    /* copy times */
+    krb5_principal client = NULL;
+    krb5_principal server = NULL;
+    char *ticket_data = NULL;
+    char *second_ticket_data = NULL;
+    unsigned char *keyblock_contents = NULL;
+    krb5_address **addresses = NULL;
+    krb5_authdata **authdata = NULL;
+    
+    if (cred_union->version != cc_credentials_v5) { 
+       err = KRB5_CC_NOT_KTYPE;
+    } else {
+        cv5 = cred_union->credentials.credentials_v5;
+    }
+    
 #if TARGET_OS_MAC
-    err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
-    if (err) 
-       return err;
+    if (!err) {
+        err = krb5_get_time_offsets (in_context, &offset_seconds, &offset_microseconds);
+    }
 #endif
-    dest->times.authtime   = cv5->authtime     + offset_seconds;
-    dest->times.starttime  = cv5->starttime    + offset_seconds;
-    dest->times.endtime    = cv5->endtime      + offset_seconds;
-    dest->times.renew_till = cv5->renew_till   + offset_seconds;
-    dest->is_skey          = cv5->is_skey;
-    dest->ticket_flags     = cv5->ticket_flags;
-
-    /* more branching fields */
-    err = copyCC3DataArrayToK5(cv5, dest, kAddressArray);
-    if (err) 
-       return err;
-
-    /* first ticket */
-    dest->ticket.length = cv5->ticket.length;
-    dest->ticket.data = (char *)malloc(cv5->ticket.length);
-    memcpy(dest->ticket.data, cv5->ticket.data, cv5->ticket.length);
-
-    /* second ticket */
-    dest->second_ticket.length = cv5->second_ticket.length;
-    (dest->second_ticket).data = ( char *)malloc(cv5->second_ticket.length);
-    memcpy(dest->second_ticket.data, cv5->second_ticket.data, cv5->second_ticket.length);
-
-    /* zero out magic number */
-    dest->magic = 0;
-
-    /* authdata */
-    err = copyCC3DataArrayToK5(cv5, dest, kAuthDataArray);
-    if (err) 
-       return err;
-
-    return 0;
+    
+    if (!err) {
+        err = krb5_parse_name (in_context, cv5->client, &client);
+    }
+    
+    if (!err) {
+        err = krb5_parse_name (in_context, cv5->server, &server);
+    }
+    
+    if (!err && cv5->keyblock.data) {
+        keyblock_contents = (unsigned char *) malloc (cv5->keyblock.length);
+        if (!keyblock_contents) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && cv5->ticket.data) {
+        ticket_data = (char *) malloc (cv5->ticket.length);
+        if (!ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && cv5->second_ticket.data) {
+        second_ticket_data = (char *) malloc (cv5->second_ticket.length);
+        if (!second_ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        /* addresses */
+        err = copy_cc_array_to_addresses (in_context, cv5->addresses, &addresses);
+    }
+    if (!err) {
+        /* authdata */
+        err = copy_cc_array_to_authdata (in_context, cv5->authdata, &authdata);
+    }
+    
+    if (!err) {
+        /* principals */
+        out_creds->client = client;
+        client = NULL;
+        out_creds->server = server;
+        server = NULL;
+        
+        /* copy keyblock */
+        if (cv5->keyblock.data) {
+            memcpy (keyblock_contents, cv5->keyblock.data, cv5->keyblock.length);
+        }
+        out_creds->keyblock.enctype = cv5->keyblock.type;
+        out_creds->keyblock.length = cv5->keyblock.length;
+        out_creds->keyblock.contents = keyblock_contents;
+        keyblock_contents = NULL;
+
+        /* copy times */
+        out_creds->times.authtime   = cv5->authtime     + offset_seconds;
+        out_creds->times.starttime  = cv5->starttime    + offset_seconds;
+        out_creds->times.endtime    = cv5->endtime      + offset_seconds;
+        out_creds->times.renew_till = cv5->renew_till   + offset_seconds;
+        out_creds->is_skey          = cv5->is_skey;
+        out_creds->ticket_flags     = cv5->ticket_flags;
+
+        /* first ticket */
+        if (cv5->ticket.data) {
+            memcpy(ticket_data, cv5->ticket.data, cv5->ticket.length);
+        }
+        out_creds->ticket.length = cv5->ticket.length;
+        out_creds->ticket.data = ticket_data;
+        ticket_data = NULL;
+        
+        /* second ticket */
+        if (cv5->second_ticket.data) {
+            memcpy(second_ticket_data, cv5->second_ticket.data, cv5->second_ticket.length);
+        }
+        out_creds->second_ticket.length = cv5->second_ticket.length;
+        out_creds->second_ticket.data = second_ticket_data;
+        second_ticket_data = NULL;
+        
+        out_creds->addresses = addresses;
+        addresses = NULL;
+
+        out_creds->authdata = authdata;
+        authdata = NULL;
+        
+        /* zero out magic number */
+        out_creds->magic = 0;
+    }
+    
+    if (addresses)          { krb5_free_addresses (in_context, addresses); }
+    if (authdata)           { krb5_free_authdata (in_context, authdata); }
+    if (keyblock_contents)  { free (keyblock_contents); }
+    if (ticket_data)        { free (ticket_data); }
+    if (second_ticket_data) { free (second_ticket_data); }
+    if (client)             { krb5_free_principal (in_context, client); }
+    if (server)             { krb5_free_principal (in_context, server); }
+    
+    return err;
 }
 
 /*
- * dupK5toCC3
+ * copy_krb5_creds_to_cc_credentials
  * - analagous to above but in the reverse direction
  */
 krb5_error_code
-dupK5toCC3(krb5_context context, krb5_creds *src, cc_credentials_t *dest)
+copy_krb5_creds_to_cc_credentials (krb5_context in_context, 
+                                   krb5_creds *in_creds, 
+                                   cc_credentials_t *out_credentials)
 {
-    cc_credentials_v5_t *c;
-    cc_credentials_union *cu;
-    cc_credentials_f    *f;
-    int err;
+    krb5_error_code err = 0;
+    cc_credentials_t credentials = NULL;
+    cc_credentials_union *cred_union = NULL;
+    cc_credentials_f    *functions = NULL;
+    cc_credentials_v5_t *cv5 = NULL;
+    char *client = NULL;
+    char *server = NULL;
+    unsigned char *ticket_data = NULL;
+    unsigned char *second_ticket_data = NULL;
+    unsigned char *keyblock_data = NULL;
     krb5_int32 offset_seconds = 0, offset_microseconds = 0;
-    cc_credentials_t           creds = NULL;
-
-    if (dest == NULL) 
-       return KRB5_CC_NOMEM;
-
-    /* allocate the cc_credentials_t */
-    creds = (cc_credentials_t)malloc(sizeof(cc_credentials_d));
-    if (!creds) {
-       err = KRB5_CC_NOMEM;
-       goto cleanup;
+    cc_data **cc_address_array = NULL;
+    cc_data **cc_authdata_array = NULL;
+    
+    if (out_credentials == NULL) { err = KRB5_CC_NOMEM; }
+    
+#if TARGET_OS_MAC
+    if (!err) {
+        err = krb5_get_time_offsets (in_context, &offset_seconds, &offset_microseconds);
     }
-
-    /* allocate the cred_union */
-    creds->data = NULL;
-    creds->functions = NULL;
-#ifdef TARGET_OS_MAC
-    creds->otherFunctions = NULL;
 #endif
-    f = (cc_credentials_f *)malloc(sizeof(cc_credentials_f));
-    if (!f) {
-       err = KRB5_CC_NOMEM;
-       goto cleanup;
+    
+    if (!err) {
+        credentials = (cc_credentials_t) malloc (sizeof (*credentials));
+        if (!credentials) { err = KRB5_CC_NOMEM; }
     }
-    creds->functions = f;
-
-    cu = (cc_credentials_union *)malloc(sizeof(cc_credentials_union));
-    if (!creds->data) {
-       err = KRB5_CC_NOMEM;
-       goto cleanup;
+    
+    if (!err) {
+        functions = (cc_credentials_f *) malloc (sizeof (*functions));
+        if (!functions) { err = KRB5_CC_NOMEM; }
     }
-    creds->data = cu; 
-
-    f->release = krb5int_cc_credentials_release;
-    f->compare = krb5int_cc_credentials_compare;
-
-    cu->version = cc_credentials_v5;
-
-    c = (cc_credentials_v5_t*)malloc(sizeof(cc_credentials_v5_t));
-    if (!c) {
-       err = KRB5_CC_NOMEM;
-       goto cleanup;
+    
+    if (!err) {
+        cred_union = (cc_credentials_union *) malloc (sizeof (*cred_union));
+        if (!cred_union) { err = KRB5_CC_NOMEM; }
     }
-    cu->credentials.credentials_v5 = c;
-
-    /* convert krb5 principals to flat principals */
-    err = krb5_unparse_name(context, src->client, &(c->client));
-    if (err) 
-       goto cleanup;
-
-    err = krb5_unparse_name(context, src->server, &(c->server));
-    if (err) 
-       goto cleanup;
-
-    /* copy more fields */
-    c->keyblock.type = src->keyblock.enctype;
-    c->keyblock.length = src->keyblock.length;
-
-    if (src->keyblock.contents != NULL) {
-       c->keyblock.data = (unsigned char *)malloc(src->keyblock.length);
-       memcpy(c->keyblock.data, src->keyblock.contents, src->keyblock.length);
-    } else {
-       c->keyblock.data = NULL;
+    
+    if (!err) {
+        cv5 = (cc_credentials_v5_t *) malloc (sizeof (*cv5));
+        if (!cv5) { err = KRB5_CC_NOMEM; }
     }
-
-#if TARGET_OS_MAC
-    err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
-    if (err) 
-       goto cleanup;
-#endif
-    c->authtime     = src->times.authtime   - offset_seconds;
-    c->starttime    = src->times.starttime  - offset_seconds;
-    c->endtime      = src->times.endtime    - offset_seconds;
-    c->renew_till   = src->times.renew_till - offset_seconds;
-    c->is_skey      = src->is_skey;
-    c->ticket_flags = src->ticket_flags;
-
-    err = copyK5DataArrayToCC3(src, c, kAddressArray);
-    if (err) 
-       goto cleanup;
-
-    c->ticket.length = src->ticket.length;
-    if (src->ticket.data != NULL) {
-       c->ticket.data = (unsigned char *)malloc(src->ticket.length);
-       memcpy(c->ticket.data, src->ticket.data, src->ticket.length);
-    } else {
-       c->ticket.data = NULL;
+    
+    if (!err) {
+        err = krb5_unparse_name (in_context, in_creds->client, &client);
     }
-
-    c->second_ticket.length = src->second_ticket.length;
-    if (src->second_ticket.data != NULL) {
-       c->second_ticket.data = (unsigned char *)malloc(src->second_ticket.length);
-       memcpy(c->second_ticket.data, src->second_ticket.data, src->second_ticket.length);
-    } else {
-       c->second_ticket.data = NULL;
+    
+    if (!err) {
+        err = krb5_unparse_name (in_context, in_creds->server, &server);
     }
-
-    err = copyK5DataArrayToCC3(src, c, kAuthDataArray);
-    if (err) 
-       goto cleanup;
-
-    *dest = creds;
-    return 0;
-
-  cleanup:
-    if (creds) {
-       if (creds->functions)
-           free((void *)creds->functions);
-       if (creds->data) {
-           if (creds->data->credentials.credentials_v5)
-               free(creds->data->credentials.credentials_v5);
-           free((void *)creds->data);
-       }
-       free(creds);
+    
+    if (!err && in_creds->keyblock.contents) {
+        keyblock_data = (unsigned char *) malloc (in_creds->keyblock.length);
+        if (!keyblock_data) { err = KRB5_CC_NOMEM; }
     }
-
+    
+    if (!err && in_creds->ticket.data) {
+        ticket_data = (unsigned char *) malloc (in_creds->ticket.length);
+        if (!ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err && in_creds->second_ticket.data) {
+        second_ticket_data = (unsigned char *) malloc (in_creds->second_ticket.length);
+        if (!second_ticket_data) { err = KRB5_CC_NOMEM; }
+    }
+    
+    if (!err) {
+        err = copy_addresses_to_cc_array (in_context, in_creds->addresses, &cc_address_array);
+    }
+    
+    if (!err) {
+        err = copy_authdata_to_cc_array (in_context, in_creds->authdata, &cc_authdata_array);
+    }
+        
+    if (!err) {
+        /* principals */
+        cv5->client = client;
+        client = NULL;
+        cv5->server = server;
+        server = NULL;
+
+        /* copy more fields */
+        if (in_creds->keyblock.contents) {
+            memcpy(keyblock_data, in_creds->keyblock.contents, in_creds->keyblock.length);
+        }
+        cv5->keyblock.type = in_creds->keyblock.enctype;
+        cv5->keyblock.length = in_creds->keyblock.length;
+        cv5->keyblock.data = keyblock_data;
+        keyblock_data = NULL;
+        
+        cv5->authtime     = in_creds->times.authtime   - offset_seconds;
+        cv5->starttime    = in_creds->times.starttime  - offset_seconds;
+        cv5->endtime      = in_creds->times.endtime    - offset_seconds;
+        cv5->renew_till   = in_creds->times.renew_till - offset_seconds;
+        cv5->is_skey      = in_creds->is_skey;
+        cv5->ticket_flags = in_creds->ticket_flags;
+
+        if (in_creds->ticket.data) {
+            memcpy (ticket_data, in_creds->ticket.data, in_creds->ticket.length);
+        }
+        cv5->ticket.length = in_creds->ticket.length;
+        cv5->ticket.data = ticket_data;
+        ticket_data = NULL;
+        
+        if (in_creds->second_ticket.data) {
+            memcpy (second_ticket_data, in_creds->second_ticket.data, in_creds->second_ticket.length);
+        }
+        cv5->second_ticket.length = in_creds->second_ticket.length;
+        cv5->second_ticket.data = second_ticket_data;
+        second_ticket_data = NULL;
+        
+        cv5->addresses = cc_address_array;
+        cc_address_array = NULL;
+        
+        cv5->authdata = cc_authdata_array;
+        cc_authdata_array = NULL;       
+        
+        /* Set up the structures to return to the caller */
+        cred_union->version = cc_credentials_v5;
+        cred_union->credentials.credentials_v5 = cv5;
+        cv5 = NULL;
+        
+        credentials->data = cred_union;
+        cred_union = NULL;
+        
+        functions->release = krb5int_cc_credentials_release;
+        functions->compare = krb5int_cc_credentials_compare;
+        credentials->functions = functions;
+        functions = NULL;
+#ifdef TARGET_OS_MAC
+        credentials->otherFunctions = NULL;
+#endif
+        
+        *out_credentials = credentials;
+        credentials = NULL;
+    }
+    
+    if (cc_address_array)   { free_cc_array (cc_address_array); }
+    if (cc_authdata_array)  { free_cc_array (cc_authdata_array); }
+    if (keyblock_data)      { free (keyblock_data); }
+    if (ticket_data)        { free (ticket_data); }
+    if (second_ticket_data) { free (second_ticket_data); }
+    if (client)             { krb5_free_unparsed_name (in_context, client); }
+    if (server)             { krb5_free_unparsed_name (in_context, server); }
+    if (cv5)                { free (cv5); }
+    if (cred_union)         { free (cred_union); }
+    if (functions)          { free (functions); } 
+    if (credentials)        { free (credentials); }
+    
     return err;
 }
 #else /* !USE_CCAPI_V3 */
@@ -739,14 +889,14 @@ static void deep_free_cc_data (cc_data data)
 
 static void deep_free_cc_data_array (cc_data** data) {
 
-    unsigned int       index;
+    unsigned int i;
 
     if (data == NULL)
        return;
 
-    for (index = 0; data [index] != NULL; index++) {
-       deep_free_cc_data (*(data [index]));
-       free (data [index]);
+    for (i = 0; data [i] != NULL; i++) {
+       deep_free_cc_data (*(data [i]));
+       free (data [i]);
     }
 
     free (data);
index 7476313dfa5c953ea38a7cb3d70dd0c365381c55..257eb8dcc580c2b95b267aafdddf8ab6338a88de 100644 (file)
 
 /* protoypes for private functions declared in stdcc_util.c */
 #ifdef USE_CCAPI_V3
-krb5_error_code dupCC3toK5(krb5_context context, cc_credentials_t src, krb5_creds *dest);
-krb5_error_code dupK5toCC3(krb5_context context, krb5_creds *src, cc_credentials_t *dest);
-cc_int32 krb5int_cc_credentials_release(cc_credentials_t creds);
-cc_int32 krb5int_cc_credentials_compare(cc_credentials_t creds,
-                                       cc_credentials_t compare_to,
-                                       cc_uint32* equal);
-int copyCC3DataArrayToK5(cc_credentials_v5_t *ccCreds, krb5_creds *v5Creds, char whichArray);
-int copyK5DataArrayToCC3(krb5_creds *v5Creds, cc_credentials_v5_t * ccCreds, char whichArray);
+krb5_error_code 
+copy_cc_credentials_to_krb5_creds (krb5_context in_context, 
+                                   cc_credentials_t in_credentials, 
+                                   krb5_creds *out_creds);
+krb5_error_code
+copy_krb5_creds_to_cc_credentials (krb5_context in_context, 
+                                   krb5_creds *in_creds, 
+                                   cc_credentials_t *out_credentials);
+
 #else
 int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray);
 int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray);