pull up r19898 from trunk
authorTom Yu <tlyu@mit.edu>
Wed, 5 Sep 2007 21:32:16 +0000 (21:32 +0000)
committerTom Yu <tlyu@mit.edu>
Wed, 5 Sep 2007 21:32:16 +0000 (21:32 +0000)
 r19898@cathode-dark-space:  tlyu | 2007-08-29 18:59:52 -0400
 ticket: 5697
 tags: pullup

 Make ccache handle referrals better by storing both server principal
 names if they differ between the creds structure and the encoded
 ticket and by looking up the server principal using the client's realm
 if not found and server's realm was initially the referral (empty)
 realm.

ticket: 5697

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

src/lib/krb5/ccache/ccfns.c

index 5e80059aedf05eb43be7b8893f4e2db18cb55b51..f44c0fe6c5c1ee1265a3407dfb103fb74cd0229b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lib/krb5/ccache/ccfns.c
  *
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -65,7 +65,28 @@ krb5_error_code KRB5_CALLCONV
 krb5_cc_store_cred (krb5_context context, krb5_ccache cache,
                    krb5_creds *creds)
 {
-    return cache->ops->store(context, cache, creds);
+    krb5_error_code ret;
+    krb5_ticket *tkt;
+    krb5_principal s1, s2;
+
+    ret = cache->ops->store(context, cache, creds);
+    if (ret) return ret;
+
+    /*
+     * If creds->server and the server in the decoded ticket differ,
+     * store both principals.
+     */
+    s1 = creds->server;
+    ret = decode_krb5_ticket(&creds->ticket, &tkt);
+    if (ret) return ret;
+    s2 = tkt->server;
+    if (!krb5_principal_compare(context, s1, s2)) {
+       creds->server = s2;
+       ret = cache->ops->store(context, cache, creds);
+       creds->server = s1;
+    }
+    krb5_free_ticket(context, tkt);
+    return ret;
 }
 
 krb5_error_code KRB5_CALLCONV
@@ -73,7 +94,23 @@ krb5_cc_retrieve_cred (krb5_context context, krb5_ccache cache,
                       krb5_flags flags, krb5_creds *mcreds,
                       krb5_creds *creds)
 {
-    return cache->ops->retrieve(context, cache, flags, mcreds, creds);
+    krb5_error_code ret;
+    krb5_data tmprealm;
+
+    ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+    if (ret != KRB5_CC_NOTFOUND)
+       return ret;
+    if (!krb5_is_referral_realm(&mcreds->server->realm))
+       return ret;
+
+    /*
+     * Retry using client's realm if service has referral realm.
+     */
+    tmprealm = mcreds->server->realm;
+    mcreds->server->realm = mcreds->client->realm;
+    ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+    mcreds->server->realm = tmprealm;
+    return ret;
 }
 
 krb5_error_code KRB5_CALLCONV