Added Frank's CCache API implementation and made it default on the Mac
authorMiro Jurisic <meeroh@mit.edu>
Thu, 20 Aug 1998 22:31:26 +0000 (22:31 +0000)
committerMiro Jurisic <meeroh@mit.edu>
Thu, 20 Aug 1998 22:31:26 +0000 (22:31 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10857 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/ccache/ChangeLog
src/lib/krb5/ccache/Makefile.in
src/lib/krb5/ccache/ccapi/Makefile.in [new file with mode: 0644]
src/lib/krb5/ccache/ccapi/stdcc.c [new file with mode: 0644]
src/lib/krb5/ccache/ccapi/stdcc.h [new file with mode: 0644]
src/lib/krb5/ccache/ccapi/stdcc_util.c [new file with mode: 0644]
src/lib/krb5/ccache/ccapi/stdcc_util.h [new file with mode: 0644]
src/lib/krb5/ccache/ccdefops.c

index 5c0ad1a6a9fd3fa1eee868d05ce846c8547c0b00..a0a23d2a5384292ac2c6a64f3579c9f356442198 100644 (file)
@@ -1,3 +1,7 @@
+Fri Aug 20 18:30:00 1998  Miro Jurisic  <meeroh@mit.edu>
+       * Added Frank's CCache API cache implementation and made
+               it default on the Mac
+
 1998-05-27  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * Makefile.in: Add ccache/memory as a directory to be recursively
index 48bfd9dd7d9b79afc9b08efbdaec71f85954d553..c32eeb40e819e6b5e54b4368caf10c63e4e52a26 100644 (file)
@@ -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 (file)
index 0000000..e47ded4
--- /dev/null
@@ -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 (file)
index 0000000..646fd06
--- /dev/null
@@ -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 (file)
index 0000000..4786cb9
--- /dev/null
@@ -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 (file)
index 0000000..ef4becf
--- /dev/null
@@ -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 <stdlib.h>
+#include <string.h>
+#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 (file)
index 0000000..f743d8e
--- /dev/null
@@ -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
+
index df7497f80020dae3b2f0f2b67c77c154b777b85a..180ce0e644410d1c3926ff5381be8b7d3a6146d1 100644 (file)
 
 #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 <sys/types.h> 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