pull up r18923 from trunk
authorTom Yu <tlyu@mit.edu>
Wed, 6 Dec 2006 22:57:06 +0000 (22:57 +0000)
committerTom Yu <tlyu@mit.edu>
Wed, 6 Dec 2006 22:57:06 +0000 (22:57 +0000)
 r18923@cathode-dark-space:  lxs | 2006-12-05 18:21:56 -0500
 ticket: new
 owner: tlyu
 target_version: 1.6
 subject: krb5_cc_remove should work for the CCAPI
 tags: pullup

 Implemented a working krb5_cc_remove for the CCAPI cache type.  Added a
 private support function krb5_creds_compare() which checks if two krb5_creds
 are identical.  This function should be needed by implementations of
 krb5_cc_remove for other ccache types.

ticket: 5003
version_fixed: 1.6

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@18928 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int.h
src/lib/krb5/ccache/cc_retr.c
src/lib/krb5/ccache/ccapi/stdcc.c
src/lib/krb5/ccache/ccapi/stdcc.h
src/lib/krb5/ccache/ccapi/stdcc_util.c
src/lib/krb5/ccache/ccapi/stdcc_util.h

index 1935daeeb8e0c06144fa55d58d21e22797366d59..3f93efd8ab0f1dbcd64d750f77cf85dcaa26b320 100644 (file)
@@ -1734,6 +1734,11 @@ krb5_error_code KRB5_CALLCONV krb5_cc_retrieve_cred_default
        (krb5_context, krb5_ccache, krb5_flags,
                        krb5_creds *, krb5_creds *);
 
+krb5_boolean 
+krb5_creds_compare (krb5_context in_context,
+                    krb5_creds *in_creds,
+                    krb5_creds *in_compare_creds);
+
 void krb5int_set_prompt_types
        (krb5_context, krb5_prompt_type *);
 
index cadd3e5fe805a1fac6a161c78e3d285d37f19e2b..43c9da7d01237f04147c38b9ab91c087b16e6318 100644 (file)
@@ -287,3 +287,102 @@ krb5_cc_retrieve_cred_default (krb5_context context, krb5_ccache id, krb5_flags
                                          0, 0);
     }
 }
+
+/* The following function duplicates some of the functionality above and */
+/* should probably be merged with it at some point.  It is used by the   */
+/* CCAPI krb5_cc_remove to figure out if the opaque credentials object   */
+/* returned by the CCAPI is the same creds as the caller passed in.      */
+/* Unlike the code above it requires that all structures be identical.   */
+
+krb5_boolean KRB5_CALLCONV 
+krb5_creds_compare (krb5_context in_context,
+                    krb5_creds *in_creds,
+                    krb5_creds *in_compare_creds)
+{
+    /* Set to 0 when we hit the first mismatch and then fall through */
+    int equal = 1;
+    
+    if (equal) {
+        equal = krb5_principal_compare (in_context, in_creds->client, 
+                                        in_compare_creds->client);
+    }
+    
+    if (equal) {
+        equal = krb5_principal_compare (in_context, in_creds->server, 
+                                        in_compare_creds->server);
+    }
+    
+    if (equal) {
+        equal = (in_creds->keyblock.enctype == in_compare_creds->keyblock.enctype &&
+                 in_creds->keyblock.length  == in_compare_creds->keyblock.length &&
+                 (!in_creds->keyblock.length ||
+                  !memcmp (in_creds->keyblock.contents, in_compare_creds->keyblock.contents,
+                           in_creds->keyblock.length)));
+    }
+    
+    if (equal) {   
+        equal = (in_creds->times.authtime   == in_compare_creds->times.authtime &&
+                 in_creds->times.starttime  == in_compare_creds->times.starttime &&
+                 in_creds->times.endtime    == in_compare_creds->times.endtime &&
+                 in_creds->times.renew_till == in_compare_creds->times.renew_till);
+    }
+    
+    if (equal) {
+        equal = (in_creds->is_skey == in_compare_creds->is_skey);
+    } 
+    
+    if (equal) {
+        equal = (in_creds->ticket_flags == in_compare_creds->ticket_flags);
+    }
+    
+    if (equal) {
+        krb5_address **addresses = in_creds->addresses;
+        krb5_address **compare_addresses = in_compare_creds->addresses;
+        unsigned int i;
+        
+        if (addresses && compare_addresses) {
+            for (i = 0; (equal && addresses[i] && compare_addresses[i]); i++) {
+                equal = krb5_address_compare (in_context, addresses[i],
+                                              compare_addresses[i]);
+            }
+            if (equal) { equal = (!addresses[i] && !compare_addresses[i]); }
+        } else {
+            if (equal) { equal = (!addresses && !compare_addresses); }
+        }
+    }
+    
+    if (equal) {
+        equal = (in_creds->ticket.length  == in_compare_creds->ticket.length &&
+                 (!in_creds->ticket.length ||
+                  !memcmp (in_creds->ticket.data, in_compare_creds->ticket.data,
+                           in_creds->ticket.length)));
+    }
+    
+    if (equal) {
+        equal = (in_creds->second_ticket.length  == in_compare_creds->second_ticket.length &&
+                 (!in_creds->second_ticket.length ||
+                  !memcmp (in_creds->second_ticket.data, in_compare_creds->second_ticket.data,
+                           in_creds->second_ticket.length)));
+    }
+    
+    if (equal) {
+        krb5_authdata **authdata = in_creds->authdata;
+        krb5_authdata **compare_authdata = in_compare_creds->authdata;
+        unsigned int i;
+        
+        if (authdata && compare_authdata) { 
+            for (i = 0; (equal && authdata[i] && compare_authdata[i]); i++) {
+                equal = (authdata[i]->ad_type == compare_authdata[i]->ad_type &&
+                         authdata[i]->length  == compare_authdata[i]->length &&
+                         (!authdata[i]->length || 
+                          !memcmp (authdata[i]->contents, compare_authdata[i]->contents,
+                                   authdata[i]->length)));
+            }
+            if (equal) { equal = (!authdata[i] && !compare_authdata[i]); }
+        } else {
+            if (equal) { equal = (!authdata && !compare_authdata); }
+        }
+    }
+    
+    return equal;
+}
index ce54b2895c36046a72a3c9f371f90748baecca03..edbec11f22d5cf42090f15d56cf6ff0185ca3f20 100644 (file)
@@ -436,7 +436,7 @@ krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds )
 {
     krb5_error_code err = 0;
     stdccCacheDataPtr ccapi_data = id->data;
-    cc_credentials_t credentials = NULL;
+    cc_credentials_union *cred_union = NULL;
     
     if (!err) {
         err = stdccv3_setup (context, ccapi_data);
@@ -444,19 +444,18 @@ krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds )
     
     if (!err) {
         /* copy the fields from the almost identical structures */
-        err = copy_krb5_creds_to_cc_credentials (context, creds, &credentials);
+        err = copy_krb5_creds_to_cc_cred_union (context, creds, &cred_union);
     }
     
     if (!err) {
-        err = cc_ccache_store_credentials (ccapi_data->NamedCache, 
-                                           credentials->data);
+        err = cc_ccache_store_credentials (ccapi_data->NamedCache, cred_union);
     }
     
     if (!err) {
         cache_changed();
     }
     
-    if (credentials) { cc_credentials_release (credentials); }
+    if (cred_union) { cred_union_release (cred_union); }
     
     return cc_err_xlate (err);
 }
@@ -519,7 +518,7 @@ krb5_stdccv3_next_cred (krb5_context context,
         err = cc_credentials_iterator_next (iterator, &credentials);
 
         if (!err && (credentials->data->version == cc_credentials_v5)) {
-            copy_cc_credentials_to_krb5_creds(context, credentials, creds);
+            copy_cc_cred_union_to_krb5_creds(context, credentials->data, creds);
             break;
         }
     }
@@ -742,36 +741,57 @@ krb5_error_code KRB5_CALLCONV
 krb5_stdccv3_remove (krb5_context context, 
                      krb5_ccache id,
                      krb5_flags flags, 
-                     krb5_creds *creds)
+                     krb5_creds *in_creds)
 {
     krb5_error_code err = 0;
     stdccCacheDataPtr ccapi_data = id->data;
-    cc_credentials_t credentials = NULL;
+    cc_credentials_iterator_t iterator = NULL;
+    int found = 0;
     
     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);
+        err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache,
+                                                 &iterator);
     }
-    
+
+    /* Note: CCAPI v3 ccaches can contain both v4 and v5 creds */
+    while (!err && !found) {
+        cc_credentials_t credentials = NULL;
+        
+        err = cc_credentials_iterator_next (iterator, &credentials);
+        
+        if (!err && (credentials->data->version == cc_credentials_v5)) {
+            krb5_creds creds;
+            
+            err = copy_cc_cred_union_to_krb5_creds(context, 
+                                                   credentials->data, &creds);
+
+            if (!err) {
+                found = krb5_creds_compare (context, in_creds, &creds);
+                krb5_free_cred_contents (context, &creds);
+            }
+            
+            if (!err && found) {
+                err = cc_ccache_remove_credentials (ccapi_data->NamedCache, credentials);
+            }
+        }
+        
+        if (credentials) { cc_credentials_release (credentials); }
+    }
+    if (err == ccIteratorEnd) { err = ccErrCredentialsNotFound; }    
+
     if (!err) {
         cache_changed ();
-    } else if (err == KRB5_FCC_NOFILE) {
-        err = 0;
     }
     
-    if (credentials) { cc_credentials_release (credentials); }
-    
     return cc_err_xlate (err);
 }
 
-static krb5_error_code KRB5_CALLCONV
+krb5_error_code KRB5_CALLCONV
 krb5_stdccv3_ptcursor_new(krb5_context context,
                           krb5_cc_ptcursor *cursor)
 {
@@ -809,7 +829,7 @@ krb5_stdccv3_ptcursor_new(krb5_context context,
        return err;
 }
 
-static krb5_error_code KRB5_CALLCONV
+krb5_error_code KRB5_CALLCONV
 krb5_stdccv3_ptcursor_next(
     krb5_context context,
     krb5_cc_ptcursor cursor,
@@ -885,7 +905,7 @@ krb5_stdccv3_ptcursor_next(
        return err;
 }
 
-static krb5_error_code KRB5_CALLCONV
+krb5_error_code KRB5_CALLCONV
 krb5_stdccv3_ptcursor_free(
     krb5_context context,
     krb5_cc_ptcursor *cursor)
index d548c0531b448c0ed13fb379ec3c86f8e49a5325..4fe6027995fddba2b71b449ad4522c5d978dcc67 100644 (file)
@@ -33,8 +33,9 @@ typedef struct _stdccCacheData {
 
 /* function protoypes  */
 
+void krb5_stdcc_shutdown(void);
+
 #ifdef USE_CCAPI_V3
-void krb5_stdccv3_shutdown(void);
 
 krb5_error_code KRB5_CALLCONV krb5_stdccv3_close
         (krb5_context, krb5_ccache id );
@@ -88,18 +89,17 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_flags
 krb5_error_code KRB5_CALLCONV krb5_stdccv3_remove 
         (krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds);
 
-static krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_new
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_new
                (krb5_context context, krb5_cc_ptcursor *cursor);
 
-static krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_next
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_next
                (krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *ccache);
 
-static krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_free
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_free
                (krb5_context context, krb5_cc_ptcursor *cursor);
 
 
 #else
-void krb5_stdcc_shutdown(void);
 
 krb5_error_code KRB5_CALLCONV krb5_stdcc_close
         (krb5_context, krb5_ccache id );
index 2e6538ccaf3438985a6db9eb0e0acfddc3978c97..58e72b33a09620efba2552b22414b168d1233f55 100644 (file)
@@ -20,9 +20,7 @@
 #define fieldSize 255
 
 #ifdef USE_CCAPI_V3
-/* 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)
@@ -38,47 +36,6 @@ free_cc_array (cc_data **io_cc_array)
     }    
 }
 
-static cc_int32 
-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;
-}
-
-static cc_int32 
-krb5int_cc_credentials_compare(cc_credentials_t creds,
-                              cc_credentials_t compare_to,
-                              cc_uint32* equal) {
-    return ccErrNotImplemented;
-}
-
 static krb5_error_code 
 copy_cc_array_to_addresses (krb5_context in_context, 
                             cc_data **in_cc_array, 
@@ -282,12 +239,11 @@ copy_authdata_to_cc_array (krb5_context in_context,
  */
 
 krb5_error_code 
-copy_cc_credentials_to_krb5_creds (krb5_context in_context, 
-                                   cc_credentials_t in_credentials
-                                   krb5_creds *out_creds)
+copy_cc_cred_union_to_krb5_creds (krb5_context in_context, 
+                                  const cc_credentials_union *in_cred_union
+                                  krb5_creds *out_creds)
 {
     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_principal client = NULL;
@@ -298,10 +254,10 @@ copy_cc_credentials_to_krb5_creds (krb5_context in_context,
     krb5_address **addresses = NULL;
     krb5_authdata **authdata = NULL;
     
-    if (cred_union->version != cc_credentials_v5) { 
+    if (in_cred_union->version != cc_credentials_v5) { 
        err = KRB5_CC_NOT_KTYPE;
     } else {
-        cv5 = cred_union->credentials.credentials_v5;
+        cv5 = in_cred_union->credentials.credentials_v5;
     }
     
 #if TARGET_OS_MAC
@@ -409,14 +365,12 @@ copy_cc_credentials_to_krb5_creds (krb5_context in_context,
  * - analagous to above but in the reverse direction
  */
 krb5_error_code
-copy_krb5_creds_to_cc_credentials (krb5_context in_context, 
-                                   krb5_creds *in_creds, 
-                                   cc_credentials_t *out_credentials)
+copy_krb5_creds_to_cc_cred_union (krb5_context in_context, 
+                                  krb5_creds *in_creds, 
+                                  cc_credentials_union **out_cred_union)
 {
     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;
@@ -427,7 +381,7 @@ copy_krb5_creds_to_cc_credentials (krb5_context in_context,
     cc_data **cc_address_array = NULL;
     cc_data **cc_authdata_array = NULL;
     
-    if (out_credentials == NULL) { err = KRB5_CC_NOMEM; }
+    if (out_cred_union == NULL) { err = KRB5_CC_NOMEM; }
     
 #if TARGET_OS_MAC
     if (!err) {
@@ -435,16 +389,6 @@ copy_krb5_creds_to_cc_credentials (krb5_context in_context,
     }
 #endif
     
-    if (!err) {
-        credentials = (cc_credentials_t) malloc (sizeof (*credentials));
-        if (!credentials) { err = KRB5_CC_NOMEM; }
-    }
-    
-    if (!err) {
-        functions = (cc_credentials_f *) malloc (sizeof (*functions));
-        if (!functions) { err = KRB5_CC_NOMEM; }
-    }
-    
     if (!err) {
         cred_union = (cc_credentials_union *) malloc (sizeof (*cred_union));
         if (!cred_union) { err = KRB5_CC_NOMEM; }
@@ -534,19 +478,8 @@ copy_krb5_creds_to_cc_credentials (krb5_context in_context,
         cred_union->credentials.credentials_v5 = cv5;
         cv5 = NULL;
         
-        credentials->data = cred_union;
+        *out_cred_union = 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); }
@@ -558,11 +491,41 @@ copy_krb5_creds_to_cc_credentials (krb5_context in_context,
     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;
 }
+
+krb5_error_code 
+cred_union_release (cc_credentials_union *in_cred_union) 
+{
+    if (in_cred_union) {
+        if (in_cred_union->version == cc_credentials_v5 &&
+            in_cred_union->credentials.credentials_v5) {
+            cc_credentials_v5_t *cv5 = in_cred_union->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 (in_cred_union->version == cc_credentials_v4 &&
+                   in_cred_union->credentials.credentials_v4) {
+            free (in_cred_union->credentials.credentials_v4);
+        }
+        free ((cc_credentials_union *) in_cred_union);
+    }
+    
+    return 0;
+}
+
 #else /* !USE_CCAPI_V3 */
 /*
  * CopyCCDataArrayToK5
index 257eb8dcc580c2b95b267aafdddf8ab6338a88de..c3a5e39cc9da3d98ad9d30cbacabb17c96e54908 100644 (file)
 /* protoypes for private functions declared in stdcc_util.c */
 #ifdef USE_CCAPI_V3
 krb5_error_code 
-copy_cc_credentials_to_krb5_creds (krb5_context in_context, 
-                                   cc_credentials_t in_credentials
-                                   krb5_creds *out_creds);
+copy_cc_cred_union_to_krb5_creds (krb5_context in_context, 
+                                  const cc_credentials_union *in_cred_union
+                                  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);
+copy_krb5_creds_to_cc_cred_union (krb5_context in_context, 
+                                  krb5_creds *in_creds, 
+                                  cc_credentials_union **out_cred_union);
 
+krb5_error_code 
+cred_union_release (cc_credentials_union *in_cred_union);
 #else
 int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray);
 int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray);