From: Alexandra Ellwood Date: Tue, 11 Jul 2006 17:28:07 +0000 (+0000) Subject: Cleaned up CCAPI v3 code to remove memory leaks. Fixed crashes in X-Git-Tag: krb5-1.6-alpha1~213 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=9e384c1778633ae06a2aa7886e5625750eb9290c;p=krb5.git Cleaned up CCAPI v3 code to remove memory leaks. Fixed crashes in 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 --- diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c index 4414abfbc..277b29cdc 100644 --- a/src/lib/krb5/ccache/ccapi/stdcc.c +++ b/src/lib/krb5/ccache/ccapi/stdcc.c @@ -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 */ diff --git a/src/lib/krb5/ccache/ccapi/stdcc.h b/src/lib/krb5/ccache/ccapi/stdcc.h index c0ce13b42..03948d1a8 100644 --- a/src/lib/krb5/ccache/ccapi/stdcc.h +++ b/src/lib/krb5/ccache/ccapi/stdcc.h @@ -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 diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c index 1969b6e71..2e6538cca 100644 --- a/src/lib/krb5/ccache/ccapi/stdcc_util.c +++ b/src/lib/krb5/ccache/ccapi/stdcc_util.c @@ -23,9 +23,52 @@ /* 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); diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.h b/src/lib/krb5/ccache/ccapi/stdcc_util.h index 7476313df..257eb8dcc 100644 --- a/src/lib/krb5/ccache/ccapi/stdcc_util.h +++ b/src/lib/krb5/ccache/ccapi/stdcc_util.h @@ -21,14 +21,15 @@ /* 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);