--- /dev/null
+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
--- /dev/null
+/**********************************************************
+ *
+ * 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) {
+ err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL);
+ if (err != CC_NOERROR) return err;
+ }
+
+ //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;
+
+ //make sure the API has been intialized
+ if (gCntrlBlock == NULL) {
+ err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL);
+ if (err != CC_NOERROR) return err;
+ }
+
+ 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];
+ char *cName = nil;
+ ccache_p *testNC = NULL;
+ ccache_it *it;
+ char *p = NULL, *targetName = NULL;
+
+ //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
+ err = krb5_unparse_name(context, princ, &cName);
+ if (err)
+ return(err);
+
+ //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 - let's not; sgm 10/7/98
+ //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);
+ }
+
+ free(cName);
+
+ 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 = NULL;
+ 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 = NULL;
+ cc_creds *c = NULL;
+
+ 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 = NULL;
+ krb5_creds *fetchcreds;
+
+ fetchcreds = (krb5_creds *)malloc(sizeof(krb5_creds));
+ if (fetchcreds == NULL) return KRB5_CC_NOMEM;
+
+ //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 = NULL;
+ 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 = NULL;
+
+ //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 = NULL;
+ 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
--- /dev/null
+//#include "k5-int.h"
+#include "krb5.h"
+
+#if defined(macintosh)
+#include "CCache.h"
+#endif
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include "cacheapi.h"
+#endif
+
+#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));
--- /dev/null
+// stdcc_util.c
+// utility functions used in implementing the ccache api for krb5
+// not publicly exported
+// Frank Dabek, July 1998
+
+#include <stdlib.h>
+#include <string.h>
+#include "stdcc_util.h"
+#include "krb5.h"
+#include "kv5m_err.h"
+
+#define fieldSize 255
+
+/* on the Mac, we need the calls which allocate memory for the Credentials Cache to use
+ Ptr's in the system help, so that they stay global and so that bad things don't happen
+ when we call DisposePtr() on them. However, on other systems, malloc is probably the
+ right thing to use.
+ So for any place where we allocate memory for the Credentials Cache, use sys_alloc() and
+ define it accordingly.
+*/
+
+#if defined(macintosh)
+#define sys_alloc(size) NewSafePtrSys(size)
+#else
+#define sys_alloc(size) malloc(size)
+#endif
+
+#if defined(macintosh)
+//stolen from CCacheUtils.c
+// -- NewSafePtrSys -----------------
+// - analagous to NewSafePtr but memory is allocated in the system heap
+Ptr NewSafePtrSys(long size) {
+
+ Ptr retPtr;
+
+ retPtr = NewPtrSys(size);
+
+ if (retPtr != NULL)
+ HoldMemory(retPtr, size);
+
+ return retPtr;
+}
+#endif
+
+// 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 **)sys_alloc((numRecords+1)*sizeof(char *));
+ //reset base
+ kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata;
+
+
+ //copy records
+ while (*kbase != NULL) {
+ *cbase = (cc_data *)sys_alloc(sizeof(krb5_address));
+ kAdr = *kbase;
+ ccAdr = *cbase;
+ ccAdr->type = kAdr->addrtype;
+ ccAdr->length = kAdr->length;
+ ccAdr->data = (unsigned char *)sys_alloc(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;
+ #ifdef macintosh
+ char *tempname = NULL;
+ #endif
+
+ if (cu == NULL) return;
+
+ //allocate the cred_union
+ *cu = (cred_union *)sys_alloc(sizeof(cred_union));
+ if ((*cu) == NULL) return;
+ (*cu)->cred_type = CC_CRED_V5;
+
+ //allocate creds structure (and install)
+ c = (cc_creds *)sys_alloc(sizeof(cc_creds));
+ if (c == NULL) return;
+ (*cu)->cred.pV5Cred = c;
+
+ //convert krb5 principals to flat principals
+ #ifdef macintosh
+ //and make sure the memory for c->client and c->server is on the system heap with NewPtr
+ //for the Mac (krb5_unparse_name puts it in appl heap with malloc)
+ err = krb5_unparse_name(context, creds->client, &tempname);
+ c->client = sys_alloc(strlen(tempname));
+ if (c->client != NULL)
+ strcpy(c->client,tempname);
+ free(tempname);
+ tempname = NULL;
+
+ err = krb5_unparse_name(context, creds->server, &tempname);
+ c->server = sys_alloc(strlen(tempname));
+ if (c->server != NULL)
+ strcpy(c->server,tempname);
+ free(tempname);
+ #else
+ err = krb5_unparse_name(context, creds->client, &(c->client));
+ err = krb5_unparse_name(context, creds->server, &(c->server));
+ #endif
+ if (err) return;
+
+ //copy more fields
+ c->keyblock.type = creds->keyblock.enctype;
+ c->keyblock.length = creds->keyblock.length;
+
+ if (creds->keyblock.contents != NULL) {
+ c->keyblock.data = (unsigned char *)sys_alloc(creds->keyblock.length);
+ memcpy(c->keyblock.data, creds->keyblock.contents, creds->keyblock.length);
+ } else {
+ c->keyblock.data = NULL;
+ }
+
+ 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;
+ if (creds->ticket.data != NULL) {
+ c->ticket.data = (unsigned char *)sys_alloc(creds->ticket.length);
+ memcpy(c->ticket.data, creds->ticket.data, creds->ticket.length);
+ } else {
+ c->ticket.data = NULL;
+ }
+
+ c->second_ticket.length = creds->second_ticket.length;
+ if (creds->second_ticket.data != NULL) {
+ c->second_ticket.data = (unsigned char *)sys_alloc(creds->second_ticket.length);
+ memcpy(c->second_ticket.data, creds->second_ticket.data, creds->second_ticket.length);
+ } else {
+ c->second_ticket.data = NULL;
+ }
+
+ 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;
+}
--- /dev/null
+//stdcc_util.h
+//
+// Frank Dabek, July 1998
+
+#if defined(macintosh)
+#include "CCache.h"
+#endif
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include "cacheapi.h"
+#endif
+
+#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
+