Make ccache handle referrals better by storing both server principal
authorTom Yu <tlyu@mit.edu>
Wed, 29 Aug 2007 22:59:52 +0000 (22:59 +0000)
committerTom Yu <tlyu@mit.edu>
Wed, 29 Aug 2007 22:59:52 +0000 (22:59 +0000)
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
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19898 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