From: Miro Jurisic Date: Thu, 20 Aug 1998 22:31:26 +0000 (+0000) Subject: Added Frank's CCache API implementation and made it default on the Mac X-Git-Tag: krb5-1.1-beta1~570 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=9173dd9e7cf722787f8ca6c98e7c319d33a5dbd6;p=krb5.git Added Frank's CCache API implementation and made it default on the Mac git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10857 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog index 5c0ad1a6a..a0a23d2a5 100644 --- a/src/lib/krb5/ccache/ChangeLog +++ b/src/lib/krb5/ccache/ChangeLog @@ -1,3 +1,7 @@ +Fri Aug 20 18:30:00 1998 Miro Jurisic + * Added Frank's CCache API cache implementation and made + it default on the Mac + 1998-05-27 Theodore Ts'o * Makefile.in: Add ccache/memory as a directory to be recursively diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in index 48bfd9dd7..c32eeb40e 100644 --- a/src/lib/krb5/ccache/Makefile.in +++ b/src/lib/krb5/ccache/Makefile.in @@ -9,7 +9,7 @@ CFLAGS = $(CCOPTS) $(DEFS) -I$(srcdir)$(S)file -I$(srcdir)$(S)stdio ##DOS##OBJFILE=..\$(PREFIXDIR).lst ##WIN16##LIBNAME=..\krb5.lib -MAC_SUBDIRS = file stdio memory +MAC_SUBDIRS = file stdio memory ccapi STLIBOBJS= \ ccbase.o \ diff --git a/src/lib/krb5/ccache/ccapi/Makefile.in b/src/lib/krb5/ccache/ccapi/Makefile.in new file mode 100644 index 000000000..e47ded443 --- /dev/null +++ b/src/lib/krb5/ccache/ccapi/Makefile.in @@ -0,0 +1,21 @@ +thisconfigdir=./../.. +BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)$(S)$(U) +CFLAGS = $(CCOPTS) $(DEFS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = ccache\file +##DOS##OBJFILE = file.lst +##WIN16##LIBNAME=..\..\krb5.lib + +STLIBOBJS = \ + stdcc.o \ + stdcc_util.o + +OBJS = stdcc.${OBJEXT} stdcc_util.${OBJEXT} + +SRCS = $(srcdir)/stdcc.c $(srcdir)/stdcc_util.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix:: all-libobjs +clean-unix:: clean-libobjs diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c new file mode 100644 index 000000000..646fd06c4 --- /dev/null +++ b/src/lib/krb5/ccache/ccapi/stdcc.c @@ -0,0 +1,379 @@ +/********************************************************** + * + * stdcc.c - additions to the Kerberos 5 library to support the memory credentical cache API + * + * Revision 1.1.1.1 - Frank Dabek July 1998 + * + **********************************************************/ + +#include "stdcc.h" +#include "string.h" + +//declare our global object wanna-be +//must be installed in ccdefops.c +krb5_cc_ops krb5_cc_stdcc_ops = { + 0, + "API", + krb5_stdcc_get_name, + krb5_stdcc_resolve, + krb5_stdcc_generate_new, + krb5_stdcc_initialize, + krb5_stdcc_destroy, + krb5_stdcc_close, + krb5_stdcc_store, + krb5_stdcc_retrieve, + krb5_stdcc_get_principal, + krb5_stdcc_start_seq_get, + krb5_stdcc_next_cred, + krb5_stdcc_end_seq_get, + krb5_stdcc_remove, + krb5_stdcc_set_flags, +}; + +// -- generate_new -------------------------------- +// - create a new cache with a unique name, corresponds to creating a named cache +// - iniitialize the API here if we have to. +krb5_error_code krb5_stdcc_generate_new + (krb5_context context, krb5_ccache *id ) + + { + + krb5_ccache newCache; + char name[kStringLiteralLen]; + cc_time_t time; + int err; + + //make sure the API has been intialized + if (gCntrlBlock == NULL) cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL); + + //allocate the cache structure + newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (newCache == NULL) return KRB5_CC_NOMEM; + + //create a unique name + cc_get_change_time(gCntrlBlock, &time); + sprintf(name, "gen_new_cache%d", time); + + //create the new cache + err = cc_create(gCntrlBlock, name, CC_CRED_V5, + name, 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache) ); + if (err != CC_NOERROR) return err; + + //setup some fields + newCache->ops = &krb5_cc_stdcc_ops; + newCache->data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData)); + + //return a pointer to the new cache + *id = newCache; + + return CC_NOERROR; + } + +// -- resolve ------------------------------ +// +// - create a new cache with the name stored in residual +krb5_error_code krb5_stdcc_resolve + (krb5_context context, krb5_ccache *id , const char *residual ) { + + krb5_ccache newCache; + int err,pos; + char *cName; + + if (gCntrlBlock == NULL) cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL); + + newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (newCache == NULL) return KRB5_CC_NOMEM; + + newCache->ops = &krb5_cc_stdcc_ops; + newCache->data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData)); + if (newCache->data == NULL) return KRB5_CC_NOMEM; + + cName = residual; + //attempt to find a cache by the same name before creating it + err = cc_open(gCntrlBlock, cName, CC_CRED_V5, 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache)); + //we didn't find it.. create it. + if (err) { + err = cc_create(gCntrlBlock, cName, CC_CRED_V5, cName, + 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache) ); + if (err != CC_NOERROR) return err; //still an error, return it + } + + //return new cache structure + *id = newCache; + return CC_NOERROR; + } + + // -- initialize -------------------------------- + //-initialize the cache, check to see if one already exists for this principal + // if not set our principal to this principal. This searching enables ticket sharing + krb5_error_code krb5_stdcc_initialize + (krb5_context context, krb5_ccache id, krb5_principal princ) + + { + + int err,err1, found; + char cName[kStringLiteralLen]; + ccache_p *testNC; + ccache_it *it; + char *p, *targetName; + + //test id for null + if (id == NULL) return KRB5_CC_NOMEM; + + //test for initialized API + if (gCntrlBlock == NULL) + return CC_NO_EXIST; + + //create a principal name for the named cache + sprintf(cName, "%s@%s", krb5_princ_name(context, princ)->data, krb5_princ_realm(context, princ)->data); + + //look for a cache already extant for this principal + it = NULL; + found = err = 0; + while ((err != CC_END) && (!found)) { + err = cc_seq_fetch_NCs(gCntrlBlock, &testNC, &it); + if (err == CC_NOERROR) { + cc_get_principal(gCntrlBlock, testNC, &p); + if (strcmp(p, cName) == 0) { + found = 1; + cc_get_name(gCntrlBlock, testNC, &targetName); + } + cc_free_principal(gCntrlBlock, p); + } + err1 = cc_close(gCntrlBlock, &testNC); + } + + if (!found) + //we didn't find one with the name we were looking for, use the one we had and change the name + cc_set_principal(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), CC_CRED_V5, cName); + else { + //we found a cache for this guy, lets trash ours and use that one + cc_destroy(gCntrlBlock, &(((stdccCacheDataPtr)(id->data))->NamedCache)); + err = cc_open(gCntrlBlock, targetName, CC_CRED_V5, 0L, &(((stdccCacheDataPtr)(id->data))->NamedCache)); + if (err != CC_NOERROR) return err; //error opening + cc_free_name(gCntrlBlock, targetName); + } + + return CC_NOERROR; + + } + + +// -- store ---------------------------------- +// - store some credentials in our cache + krb5_error_code krb5_stdcc_store + (krb5_context context, krb5_ccache id , krb5_creds *creds ) { + + cred_union *cu; + int err; + + + //copy the fields from the almost identical structures + dupK52cc(context, creds, &cu); + + //finally store the credential + //store will copy (that is duplicate) everything + err = cc_store(gCntrlBlock, ((stdccCacheDataPtr)(id->data))->NamedCache, *cu); + if (err != CC_NOERROR) return err; + + //free the cred union + err = cc_free_creds(gCntrlBlock, &cu); + + return err; +} + + +// -- start_seq_get -------------------------- +// - begin an iterator call to get all of the credentials in the cache +krb5_error_code krb5_stdcc_start_seq_get +(krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor ) { + + //all we have to do is initialize the cursor + *cursor = NULL; + return CC_NOERROR; +} + +// -- next cred --------------------------- +// - 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_stdcc_next_cred + (krb5_context context, + krb5_ccache id , + krb5_cc_cursor *cursor , + krb5_creds *creds ) { + + int err; + cred_union *credU; + cc_creds *c; + + err = cc_seq_fetch_creds(gCntrlBlock, ((stdccCacheDataPtr)(id->data))->NamedCache, + &credU, (ccache_it **)cursor); + + if (err != CC_NOERROR) + return err; + + //copy data (with translation) + dupCCtoK5(context, credU->cred.pV5Cred, creds); + + //free our version of the cred + cc_free_creds(gCntrlBlock, &credU); + + return CC_NOERROR; + +} + + +// -- retreive ------------------- +// - try to find a matching credential in the cache +krb5_error_code krb5_stdcc_retrieve + (krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + krb5_creds *mcreds, + krb5_creds *creds ) { + + krb5_cc_cursor curs; + krb5_creds *fetchcreds; + + fetchcreds = (krb5_creds *)malloc(sizeof(krb5_creds)); + + //we're going to use the iterators + krb5_stdcc_start_seq_get(context, id, &curs); + + while (krb5_stdcc_next_cred(context, id, &curs, fetchcreds) == CC_NOERROR) { + //look at each credential for a match + //use this match routine since it takes the whichfields and the API doesn't + if (stdccCredsMatch(context, fetchcreds, mcreds, whichfields)) { + //we found it, copy and exit + *creds = *fetchcreds; + krb5_stdcc_end_seq_get(context, id, &curs); + return CC_NOERROR; + } + //free copy allocated by next_cred + krb5_free_cred_contents(context, fetchcreds); + } + + //no luck, end get and exti + krb5_stdcc_end_seq_get(context, id, &curs); + + return KRB5_CC_NOTFOUND; +} + +// -- end seq ------------------------ +// - just free up the storage assoicated with the cursor (if we could) + krb5_error_code krb5_stdcc_end_seq_get + (krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor ) { + + //the limitation of the Ccache api and the seq calls + //causes trouble. cursor might have already been freed + //and anyways it is in the mac's heap so we need FreePtr + //but all i have is free + // FreePtr(*cursor); + + //LEAK IT! + *cursor = NULL; + } + +// -- close --------------------------- +// - free our pointers to the NC +krb5_error_code +krb5_stdcc_close(context, id, princ) + krb5_context context; + krb5_ccache id; + krb5_principal princ; +{ + + //free it + free((stdccCacheDataPtr)(id->data)); + //null it out + (stdccCacheDataPtr)(id->data) = NULL; + + return CC_NOERROR; +} + +// -- destroy ------------- +// - free our storage and the cache +krb5_error_code +krb5_stdcc_destroy (krb5_context context, krb5_ccache id ) { + + int err; + + //destroy the named cache + err = cc_destroy(gCntrlBlock, &(((stdccCacheDataPtr)(id->data))->NamedCache)); + //free the pointer to the record that held the pointer to the cache + free((stdccCacheDataPtr)(id->data)); + //null it out + (stdccCacheDataPtr)(id->data) = NULL; + + return err; +} + + +// -- getname --------------------------- +// - return the name of the named cache +char * krb5_stdcc_get_name + (krb5_context context, krb5_ccache id ) { + + char *ret; + int err; + + //just a wrapper + err = cc_get_name(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), &ret); + + if (err != CC_NOERROR) + return ret; + else + return NULL; + +} + +// -- get_principal --------------------------- +// - return the principal associated with the named cache +krb5_error_code +krb5_stdcc_get_principal (krb5_context context, krb5_ccache id , krb5_principal *princ ) { + + int err; + char *name; + + //another wrapper + err = cc_get_principal(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), &name); + + if (err != CC_NOERROR) + return err; + + //turn it into a krb principal + err = krb5_parse_name(context, name, princ); + + return err; +} + +// -- set_flags --------------------------- +// - currently a NOP since we don't store any flags in the NC +krb5_error_code krb5_stdcc_set_flags + (krb5_context context, krb5_ccache id , krb5_flags flags ) { + + return CC_NOERROR; +} + +// - remove --------------------------- +// - remove the specified credentials from the NC +krb5_error_code krb5_stdcc_remove + (krb5_context context, krb5_ccache id , krb5_flags flags, krb5_creds *creds ) { + + cred_union *cu; + int err; + + //convert to a cred union + dupK52cc(context, creds, &cu); + + //remove it + err = cc_remove_cred(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), *cu); + if (err != CC_NOERROR) return err; + + //free the temp cred union + err = cc_free_creds(gCntrlBlock, &cu); + if (err != CC_NOERROR) return err; + + return CC_NOERROR; + } + \ No newline at end of file diff --git a/src/lib/krb5/ccache/ccapi/stdcc.h b/src/lib/krb5/ccache/ccapi/stdcc.h new file mode 100644 index 000000000..4786cb9e2 --- /dev/null +++ b/src/lib/krb5/ccache/ccapi/stdcc.h @@ -0,0 +1,66 @@ +//#include "k5-int.h" +#include "krb5.h" +#include "CCache.h" + +#define kStringLiteralLen 255 + +//globals to be exported +extern krb5_cc_ops krb5_cc_stdcc_ops; + +//structure to stash in the cache's data field +//only holds another pointer to the actual cache right now +typedef struct _stdccCacheData { + ccache_p *NamedCache; +} stdccCacheData, *stdccCacheDataPtr; + + +//function protoypes complete with bogus windowsesque macros.. + +KRB5_DLLIMP krb5_error_code krb5_stdcc_close + KRB5_PROTOTYPE((krb5_context, krb5_ccache id )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_destroy + KRB5_PROTOTYPE((krb5_context, krb5_ccache id )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_end_seq_get + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_cc_cursor *cursor )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_generate_new + KRB5_PROTOTYPE((krb5_context, krb5_ccache *id )); + +KRB5_DLLIMP char * krb5_stdcc_get_name + KRB5_PROTOTYPE((krb5_context, krb5_ccache id )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_get_principal + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_principal *princ )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_initialize + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_principal princ )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_next_cred + KRB5_PROTOTYPE((krb5_context, + krb5_ccache id , + krb5_cc_cursor *cursor , + krb5_creds *creds )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_resolve + KRB5_PROTOTYPE((krb5_context, krb5_ccache *id , const char *residual )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_retrieve + KRB5_PROTOTYPE((krb5_context, + krb5_ccache id , + krb5_flags whichfields , + krb5_creds *mcreds , + krb5_creds *creds )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_start_seq_get + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_cc_cursor *cursor )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_store + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_creds *creds )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_set_flags + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_flags flags )); + +KRB5_DLLIMP krb5_error_code krb5_stdcc_remove + KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds)); \ No newline at end of file diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c new file mode 100644 index 000000000..ef4becf84 --- /dev/null +++ b/src/lib/krb5/ccache/ccapi/stdcc_util.c @@ -0,0 +1,302 @@ +// stdcc_util.c +// utility functions used in implementing the ccache api for krb5 +// not publicly exported +// Frank Dabek, July 1998 + +#include +#include +#include "stdcc_util.h" +#include "krb5.h" +#include "kv5m_err.h" + +#define fieldSize 255 + +// CopyCCDataArrayToK5 +// - copy and translate the null terminated arrays of data records +// used in k5 tickets +int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray) { + + cc_data *ccAdr, **cbase; + krb5_address *kAdr, **kbase, **constKBase; + int numRecords = 0; + + + if (whichArray == kAddressArray) { + //check pointer + if (cc->addresses == NULL) { + kc->addresses = NULL; + return 0; } + } else if (whichArray == kAuthDataArray) { + //check pointer + if (cc->authdata == NULL) { + kc->authdata = NULL; + return 0; } + } else return -1; + + + cbase = (whichArray == kAddressArray) ? cc->addresses : cc->authdata; + //calc number of records + while (*cbase++ != NULL) numRecords++; + //allocate new array + constKBase = kbase = (krb5_address **)malloc((numRecords+1)*sizeof(char *)); + //reset base + cbase = (whichArray == kAddressArray) ? cc->addresses : cc->authdata; + + + //copy records + while (*cbase != NULL) { + *kbase = (krb5_address *)malloc(sizeof(krb5_address)); + kAdr = *kbase; + ccAdr = *cbase; + kAdr->magic = (whichArray == kAddressArray) ? KV5M_ADDRESS : KV5M_AUTHDATA; + kAdr->addrtype = ccAdr->type; + kAdr->length = ccAdr->length; + kAdr->contents = (krb5_octet *)malloc(kAdr->length); + memcpy(kAdr->contents, ccAdr->data, kAdr->length); + //next element please + kbase++; cbase++; + } + + //write terminator + *kbase = NULL; + if (whichArray == kAddressArray) kc->addresses = constKBase; + else kc->authdata = (krb5_authdata **)constKBase; + + return 0; +} + +// copyK5DataArrayToCC +// - analagous to above, but in the other direction +int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray) { + + cc_data *ccAdr, **cbase, **constCBase; + krb5_address *kAdr, **kbase; + int numRecords = 0; + + + if (whichArray == kAddressArray) { + //check pointer + if (kc->addresses == NULL) { + cc->addresses = NULL; + return 0; } + } else if (whichArray == kAuthDataArray) { + //check pointer + if (kc->authdata == NULL) { + cc->authdata = NULL; + return 0; } + } else return -1; + + + kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata; + //calc number of records + while (*kbase++ != NULL) numRecords++; + //allocate new array + constCBase = cbase = (cc_data **)malloc((numRecords+1)*sizeof(char *)); + //reset base + kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata; + + + //copy records + while (*kbase != NULL) { + *cbase = (cc_data *)malloc(sizeof(krb5_address)); + kAdr = *kbase; + ccAdr = *cbase; + ccAdr->type = kAdr->addrtype; + ccAdr->length = kAdr->length; + ccAdr->data = (unsigned char *)malloc(ccAdr->length); + memcpy(ccAdr->data, kAdr->contents, kAdr->length); + //next element please + kbase++; cbase++; + } + + //write terminator + *cbase = NULL; + if (whichArray == kAddressArray) cc->addresses = (cc_data **)constCBase; + else cc->authdata = (cc_data **)constCBase; + + return 0; +} + + +// dupcctok5 +// - allocate an empty k5 style ticket and copy info from the cc_creds ticket +void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest) { + + int err; + + //allocate and copy + //copy all of those damn fields back + err = krb5_parse_name(context, src->client, &(dest->client)); + err = krb5_parse_name(context, src->server, &(dest->server)); + if (err) return; //parsename fails w/o krb5.ini for example + + //copy keyblock + dest->keyblock.enctype = src->keyblock.type; + dest->keyblock.length = src->keyblock.length; + dest->keyblock.contents = (krb5_octet *)malloc(dest->keyblock.length); + memcpy(dest->keyblock.contents, src->keyblock.data, dest->keyblock.length); + + //copy times + dest->times.authtime = src->authtime; + dest->times.starttime = src->starttime; + dest->times.endtime = src->endtime; + dest->times.renew_till = src->renew_till; + dest->is_skey = src->is_skey; + dest->ticket_flags = src->ticket_flags; + + //more branching fields + copyCCDataArrayToK5(src, dest, kAddressArray); + dest->ticket.length = src->ticket.length; + dest->ticket.data = (char *)malloc(src->ticket.length); + memcpy(dest->ticket.data, src->ticket.data, src->ticket.length); + dest->second_ticket.length = src->second_ticket.length; + (dest->second_ticket).data = ( char *)malloc(src->second_ticket.length); + memcpy(dest->second_ticket.data, src->second_ticket.data, src->second_ticket.length); + + //zero out magic number + dest->magic = 0; + //later + //copyCCDataArrayToK5(src, dest, kAuthDataArray); + //krb5 docs say that authdata can be nulled out if we + //only want default behavior + dest->authdata = NULL; + + return; +} + +// dupK52CC +// - analagous to above but in the reverse direction +void dupK52cc(krb5_context context, krb5_creds *creds, cred_union **cu) { + + krb5_address **tA; + krb5_authdata **tAd; + cc_creds *c; + int err; + + if (cu == NULL) return; + + //allocate the cred_union + *cu = (cred_union *)malloc(sizeof(cred_union)); + if ((*cu) == NULL) return; + (*cu)->cred_type = CC_CRED_V5; + + //allocate creds structure (and install) + c = (cc_creds *)malloc(sizeof(cc_creds)); + if (c == NULL) return; + (*cu)->cred.pV5Cred = c; + + //convert krb5 principals to flat principals + err = krb5_unparse_name(context, creds->client, &(c->client)); + err = krb5_unparse_name(context, creds->server, &(c->server)); + if (err) return; + + //copy more fields + c->keyblock.type = creds->keyblock.enctype; + c->keyblock.length = creds->keyblock.length; + c->keyblock.data = (unsigned char *)malloc(creds->keyblock.length); + memcpy(c->keyblock.data, creds->keyblock.contents, creds->keyblock.length); + c->authtime = creds->times.authtime; + c->starttime = creds->times.starttime; + c->endtime = creds->times.endtime; + c->renew_till = creds->times.renew_till; + c->is_skey = creds->is_skey; + c->ticket_flags = creds->ticket_flags; + + copyK5DataArrayToCC(creds, c, kAddressArray); + + c->ticket.length = creds->ticket.length; + c->ticket.data = (unsigned char *)malloc(creds->ticket.length); + memcpy(c->ticket.data, creds->ticket.data, creds->ticket.length); + c->second_ticket.length = creds->second_ticket.length; + c->second_ticket.data = (unsigned char *)malloc(creds->second_ticket.length); + memcpy(c->second_ticket.data, creds->second_ticket.data, creds->second_ticket.length); + + c->authdata = NULL; + + return; +} + + +// bitTst +// - utility function for below function +int bitTst(int var, int mask) { + + return var & mask; +} + +// stdccCredsMatch +// - check to see if the creds match based on the whichFields variable +// NOTE: if whichfields is zero we are now comparing 'standard fields.' +// This is the bug that was killing fetch for a week. The behaviour +// is what krb5 expects, however. +int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields) { + + krb5_ticket_times b, m; + krb5_authdata **bp, **mp; + krb5_boolean retval; + krb5_principal_data p1, p2; + + + //always check the standard fields + if ((krb5_principal_compare(context, base->client, match->client) && + krb5_principal_compare(context, base->server, match->server)) == false) + return FALSE; + + if (bitTst(whichfields, KRB5_TC_MATCH_TIMES)) { + //test for matching times + //according to the file cache implementation we do: + if (match->times.renew_till) { + if (match->times.renew_till > base->times.renew_till) + return FALSE; /* this one expires too late */ + } + if (match->times.endtime) { + if (match->times.endtime > base->times.endtime) + return FALSE; /* this one expires too late */ + } + } //continue search + + if (bitTst(whichfields, KRB5_TC_MATCH_IS_SKEY)) + if (base->is_skey != match->is_skey) return false; + + if (bitTst(whichfields, KRB5_TC_MATCH_FLAGS)) + if (base->ticket_flags != match->ticket_flags) return false; + + if (bitTst(whichfields, KRB5_TC_MATCH_TIMES_EXACT)) { + b = base->times; m = match->times; + if ((b.authtime != m.authtime) || + (b.starttime != m.starttime) || + (b.endtime != m.endtime) || + (b.renew_till != m.renew_till)) return false; + } + + if (bitTst(whichfields, KRB5_TC_MATCH_AUTHDATA)) { + bp = base->authdata; + mp = match->authdata; + if ((bp != NULL) && (mp != NULL)) { + while ( (bp) && (*bp != NULL) ){ + if (( (*bp)->ad_type != (*mp)->ad_type) || + ( (*bp)->length != (*mp)->length) || + ( memcmp( (*bp)->contents, (*mp)->contents, (*bp)->length) != 0)) return false; + mp++; bp++; + } + } + } + + if (bitTst(whichfields, KRB5_TC_MATCH_SRV_NAMEONLY)) { + //taken from cc_retrv.c + retval = krb5_principal_compare(context, base->client,match->client); + if (!retval) return false; + + } + + if (bitTst(whichfields, KRB5_TC_MATCH_2ND_TKT)) + if ( (base->second_ticket.length != match->second_ticket.length) || + (memcmp(base->second_ticket.data, match->second_ticket.data, base->second_ticket.length) != 0)) + return false; + + if (bitTst(whichfields, KRB5_TC_MATCH_KTYPE)) + if (base->keyblock.enctype != match->keyblock.enctype) return false; + + //if we fall through to here, they must match + return true; +} diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.h b/src/lib/krb5/ccache/ccapi/stdcc_util.h new file mode 100644 index 000000000..f743d8ea7 --- /dev/null +++ b/src/lib/krb5/ccache/ccapi/stdcc_util.h @@ -0,0 +1,18 @@ +//stdcc_util.h +// +// Frank Dabek, July 1998 + +#include "CCache.h" +#include "krb5.h" + +//protoypes for private functions declared in stdcc_util.c +int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray); +int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray); +void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest); +void dupK52cc(krb5_context context, krb5_creds *creds, cred_union **cu); +int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields); +int bitTst(int var, int mask); +void typeK52cc(krb5_context context, krb5_creds *creds, cc_creds *c, char **client, char **server); +#define kAddressArray 4 +#define kAuthDataArray 5 + diff --git a/src/lib/krb5/ccache/ccdefops.c b/src/lib/krb5/ccache/ccdefops.c index df7497f80..180ce0e64 100644 --- a/src/lib/krb5/ccache/ccdefops.c +++ b/src/lib/krb5/ccache/ccdefops.c @@ -27,6 +27,15 @@ #include "k5-int.h" +#ifdef macintosh + +/* Macs use the shared, memory based credentials cache */ +#include "stdcc.h" /* from ccapi subdir */ + +krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_stdcc_ops; + +#else + #ifdef HAVE_SYS_TYPES_H /* Systems that have probably have Unix-like files (off_t, for example, which is needed by fcc.h). */ @@ -41,3 +50,5 @@ krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_file_ops; krb5_cc_ops *krb5_cc_dfl_ops = &krb5_scc_ops; #endif + +#endif \ No newline at end of file