>From 4cc036a492bfb70444497976fa52a29ebf6fb71e Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Wed, 29 May 2013 09:57:38 +0200
Subject: [PATCH 2/3] Every time return directory for krb5 cache collection.

Function krb5_cc_get_full_name is called only as a way to validate that,
we have the right cache. Instead of returned name, location will be returned
from function cc_dir_cache_for_princ.

https://fedorahosted.org/sssd/ticket/1936
---
 src/providers/krb5/krb5_child.c | 65 ++++++++++++++++++++++++++++++++++++++---
 src/providers/krb5/krb5_utils.c |  5 +++-
 2 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index e4dc49327db1fadac52fa77ffad07c8cc2d1bba8..3beaa07ca5425e90d31f0e7720bae71b927915d6 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -949,14 +949,60 @@ done:
 
 }
 
+static char * get_ccache_name_by_principal(TALLOC_CTX *mem_ctx,
+                                           krb5_context ctx,
+                                           krb5_principal principal,
+                                           const char *ccname)
+{
+    krb5_error_code kerr;
+    krb5_ccache tmp_cc = NULL;
+    char *tmp_ccname = NULL;
+    char *ret_ccname = NULL;
+
+    kerr = krb5_cc_set_default_name(ctx, ccname);
+    if (kerr != 0) {
+        KRB5_CHILD_DEBUG(SSSDBG_MINOR_FAILURE, kerr);
+        return NULL;
+    }
+
+    kerr = krb5_cc_cache_match(ctx, principal, &tmp_cc);
+    if (kerr != 0) {
+        KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
+        return NULL;
+    }
+
+    kerr = krb5_cc_get_full_name(ctx, tmp_cc, &tmp_ccname);
+    if (kerr !=0) {
+        KRB5_CHILD_DEBUG(SSSDBG_MINOR_FAILURE, kerr);
+        goto done;
+    }
+
+    ret_ccname = talloc_strdup(mem_ctx, tmp_ccname);
+    if (ret_ccname == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed (ENOMEM).\n"));
+    }
+
+done:
+    if (tmp_cc != NULL) {
+        kerr = krb5_cc_close(ctx, tmp_cc);
+        if (kerr != 0) {
+            KRB5_CHILD_DEBUG(SSSDBG_MINOR_FAILURE, kerr);
+        }
+    }
+    krb5_free_string(ctx, tmp_ccname);
+
+    return ret_ccname;
+}
+
 static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
                                         char *password)
 {
-    krb5_error_code kerr = 0;
     int ret;
     const char *realm_name;
     int realm_length;
-
+    krb5_error_code kerr;
+    char *cc_name;
+    krb5_principal principal;
 
     kerr = sss_krb5_get_init_creds_opt_set_expire_callback(kr->ctx, kr->options,
                                                   sss_krb5_expire_callback_func,
@@ -1000,10 +1046,21 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
         }
     }
 
+    principal = kr->creds ? kr->creds->client : kr->princ;
+
+    /* If kr->ccname is cache collection (DIR:/...), we want to work
+     * directly with file ccache (DIR::/...), but cache collection
+     * should be returned back to back end.
+     */
+    cc_name = get_ccache_name_by_principal(kr->pd, kr->ctx, principal,
+                                           kr->ccname);
+    if (cc_name == NULL) {
+        cc_name = kr->ccname;
+    }
+
     /* Use the updated principal in the creds in case canonicalized */
     kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
-                         kr->creds ? kr->creds->client : kr->princ,
-                         kr->ccname, kr->creds);
+                         principal, cc_name, kr->creds);
     if (kerr != 0) {
         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
         goto done;
diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
index d85ca20d193abc96826f581622341610250d2ec6..7d0ad1ec974c42e443fb41b2c30a67693426e4c1 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1163,6 +1163,9 @@ cc_dir_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
         return NULL;
     }
 
+    /* This function is called only as a way to validate that,
+     * we have the right cache
+     */
     krberr = krb5_cc_get_full_name(context, ccache, &name);
     if (ccache) krb5_cc_close(context, ccache);
     krb5_free_context(context);
@@ -1172,7 +1175,7 @@ cc_dir_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
         return NULL;
     }
 
-    return talloc_strdup(mem_ctx, name);
+    return talloc_strdup(mem_ctx, location);
 }
 
 errno_t
-- 
1.9.3

