[sssd/f20] Backport simplification of ccache management from 1.11.1

Jakub Hrozek jhrozek at fedoraproject.org
Mon Sep 23 12:46:55 UTC 2013


commit 41b3a01afa70c32787258641bc916bd9a58f91e0
Author: Jakub Hrozek <jhrozek at redhat.com>
Date:   Mon Sep 23 12:23:42 2013 +0200

    Backport simplification of ccache management from 1.11.1
    
    - Resolves: rhbz#1010553 - sssd setting KRB5CCNAME=(null) on login

 ...d-calls-to-change-and-restore-credentials.patch |  168 ++++++
 ...krb5-Add-helper-to-destroy-ccache-as-user.patch |  154 ++++++
 ...Use-krb5_cc_destroy-to-remove-old-ccaches.patch |  279 ++++++++++
 ...lace-type-specific-ccache-principal-check.patch |  357 ++++++++++++
 ...5-Move-determination-of-user-being-active.patch |  220 ++++++++
 ...b5-move-template-check-to-initializzation.patch |  160 ++++++
 0007-krb5-Make-check_for_valid_tgt-static.patch    |  201 +++++++
 ...krb5-Use-new-function-to-validate-ccaches.patch |  568 +++++++++++++++++++
 ...rb5-Unify-function-to-create-ccache-files.patch |  348 ++++++++++++
 ...move-unused-ccache-backend-infrastructure.patch |  337 +++++++++++
 0011-krb5-Remove-unused-function.patch             |   69 +++
 0012-krb5-Add-file-dir-path-precheck.patch         |   97 ++++
 0013-krb5_child-Simplify-ccache-creation.patch     |  582 ++++++++++++++++++++
 0014-krb5-Remove-unused-helper-functions.patch     |  127 +++++
 sssd.spec                                          |   20 +-
 15 files changed, 3686 insertions(+), 1 deletions(-)
---
diff --git a/0001-krb5-Add-calls-to-change-and-restore-credentials.patch b/0001-krb5-Add-calls-to-change-and-restore-credentials.patch
new file mode 100644
index 0000000..e377e55
--- /dev/null
+++ b/0001-krb5-Add-calls-to-change-and-restore-credentials.patch
@@ -0,0 +1,168 @@
+From 0371fbcf60d4dd8e25b9bb0a83029c812b66f3d6 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Wed, 28 Aug 2013 21:19:32 -0400
+Subject: [PATCH 01/14] krb5: Add calls to change and restore credentials
+
+In some cases we want to temporarily assume user credentials but allow the
+process to regain back the original credentials (normally regaining uid 0).
+
+Related:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_become_user.c | 125 ++++++++++++++++++++++++++++++++++
+ src/providers/krb5/krb5_utils.h       |   6 ++
+ 2 files changed, 131 insertions(+)
+
+diff --git a/src/providers/krb5/krb5_become_user.c b/src/providers/krb5/krb5_become_user.c
+index 70bc5630ece21505b58bd1a8795d7ab4b7864460..567cf237569f70a6b0fd500327438f2dbb08d24d 100644
+--- a/src/providers/krb5/krb5_become_user.c
++++ b/src/providers/krb5/krb5_become_user.c
+@@ -70,3 +70,128 @@ errno_t become_user(uid_t uid, gid_t gid)
+     return EOK;
+ }
+ 
++struct sss_creds {
++    uid_t uid;
++    gid_t gid;
++    int num_gids;
++    gid_t gids[];
++};
++
++errno_t restore_creds(struct sss_creds *saved_creds);
++
++/* This is a reversible version of become_user, and returns the saved
++ * credentials so that creds can be switched back calling restore_creds */
++errno_t switch_creds(TALLOC_CTX *mem_ctx,
++                     uid_t uid, gid_t gid,
++                     int num_gids, gid_t *gids,
++                     struct sss_creds **saved_creds)
++{
++    struct sss_creds *ssc = NULL;
++    int size;
++    int ret;
++
++    DEBUG(SSSDBG_FUNC_DATA, ("Switch user to [%d][%d].\n", uid, gid));
++
++    if (saved_creds) {
++        /* save current user credentials */
++        size = getgroups(0, NULL);
++        if (size == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE, ("Getgroups failed! (%d, %s)\n",
++                                        ret, strerror(ret)));
++            goto done;
++        }
++
++        ssc = talloc_size(mem_ctx,
++                          (sizeof(struct sss_creds) + size * sizeof(gid_t)));
++        if (!ssc) {
++            DEBUG(SSSDBG_CRIT_FAILURE, ("Allocation failed!\n"));
++            ret = ENOMEM;
++            goto done;
++        }
++        ssc->num_gids = size;
++
++        size = getgroups(ssc->num_gids, ssc->gids);
++        if (size == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE, ("Getgroups failed! (%d, %s)\n",
++                                        ret, strerror(ret)));
++            /* free ssc immediately otherwise the code will try to restore
++             * wrong creds */
++            talloc_zfree(ssc);
++            goto done;
++        }
++
++        /* we care only about effective ids */
++        ssc->uid = geteuid();
++        ssc->gid = getegid();
++    }
++
++    /* if we are regaining root set euid first so that we have CAP_SETUID back,
++     * ane the other calls work too, otherwise call it last so that we can
++     * change groups before we loose CAP_SETUID */
++    if (uid == 0) {
++        ret = setresuid(0, 0, 0);
++        if (ret == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  ("setresuid failed [%d][%s].\n", ret, strerror(ret)));
++            goto done;
++        }
++    }
++
++    /* TODO: use prctl to get/set capabilities too ? */
++
++    /* try to setgroups first should always work if CAP_SETUID is set,
++     * otherwise it will always fail, failure is not critical though as
++     * generally we only really care about uid and at mot primary gid */
++    ret = setgroups(num_gids, gids);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_TRACE_FUNC,
++              ("setgroups failed [%d][%s].\n", ret, strerror(ret)));
++    }
++
++    /* change gid now, (leaves saved gid to current, so we can restore) */
++    ret = setresgid(-1, gid, -1);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              ("setresgid failed [%d][%s].\n", ret, strerror(ret)));
++        goto done;
++    }
++
++    if (uid != 0) {
++        /* change uid, (leaves saved uid to current, so we can restore) */
++        ret = setresuid(-1, uid, -1);
++        if (ret == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  ("setresuid failed [%d][%s].\n", ret, strerror(ret)));
++            goto done;
++        }
++    }
++
++    ret = 0;
++
++done:
++    if (ret) {
++        if (ssc) {
++            /* attempt to restore creds first */
++            restore_creds(ssc);
++            talloc_free(ssc);
++        }
++    } else if (saved_creds) {
++        *saved_creds = ssc;
++    }
++    return ret;
++}
++
++errno_t restore_creds(struct sss_creds *saved_creds)
++{
++    return switch_creds(saved_creds,
++                        saved_creds->uid,
++                        saved_creds->gid,
++                        saved_creds->num_gids,
++                        saved_creds->gids, NULL);
++}
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index cdc9f23641905cff300077f708087e98ba683e0d..aac3ec72ec7e1664ae96cc4e53d368e22448f5f1 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -80,6 +80,12 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
+                              bool case_sensitive, bool *private_path);
+ 
+ errno_t become_user(uid_t uid, gid_t gid);
++struct sss_creds;
++errno_t switch_creds(TALLOC_CTX *mem_ctx,
++                     uid_t uid, gid_t gid,
++                     int num_gids, gid_t *gids,
++                     struct sss_creds **saved_creds);
++errno_t restore_creds(struct sss_creds *saved_creds);
+ 
+ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                              struct tgt_times *tgtt);
+-- 
+1.8.3.1
+
diff --git a/0002-krb5-Add-helper-to-destroy-ccache-as-user.patch b/0002-krb5-Add-helper-to-destroy-ccache-as-user.patch
new file mode 100644
index 0000000..6c4c8b5
--- /dev/null
+++ b/0002-krb5-Add-helper-to-destroy-ccache-as-user.patch
@@ -0,0 +1,154 @@
+From 04c49a183f49c28f9ef900bdbc4eb30f23278e17 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Wed, 28 Aug 2013 22:12:07 -0400
+Subject: [PATCH 02/14] krb5: Add helper to destroy ccache as user
+
+This function safely destroy a ccache given a cache name and user crdentials.
+It becomes the user so no possible races can compromise the system, then
+uses libkrb5 functions to properly destroy a ccache, independently of the
+cache type.
+Finally restores the original credentials after closing the ccache handlers.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_utils.c | 109 ++++++++++++++++++++++++++++++++++++++++
+ src/providers/krb5/krb5_utils.h |   2 +
+ 2 files changed, 111 insertions(+)
+
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index 6bf1cf610dd20afc7a600e9505c4bae2ff675fcc..1141f3fc839a78927dab5f50267c52d5b44b46ba 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -818,6 +818,115 @@ done:
+ }
+ 
+ 
++struct sss_krb5_ccache {
++    struct sss_creds *creds;
++    krb5_context context;
++    krb5_ccache ccache;
++};
++
++static int sss_free_krb5_ccache(void *mem)
++{
++    struct sss_krb5_ccache *cc = talloc_get_type(mem, struct sss_krb5_ccache);
++
++    if (cc->ccache) {
++        krb5_cc_close(cc->context, cc->ccache);
++    }
++    krb5_free_context(cc->context);
++    restore_creds(cc->creds);
++    return 0;
++}
++
++static errno_t sss_open_ccache_as_user(TALLOC_CTX *mem_ctx,
++                                       const char *ccname,
++                                       uid_t uid, gid_t gid,
++                                       struct sss_krb5_ccache **ccache)
++{
++    struct sss_krb5_ccache *cc;
++    krb5_error_code kerr;
++    errno_t ret;
++
++    cc = talloc_zero(mem_ctx, struct sss_krb5_ccache);
++    if (!cc) {
++        return ENOMEM;
++    }
++    talloc_set_destructor((TALLOC_CTX *)cc, sss_free_krb5_ccache);
++
++    ret = switch_creds(cc, uid, gid, 0, NULL, &cc->creds);
++    if (ret) {
++        goto done;
++    }
++
++    kerr = krb5_init_context(&cc->context);
++    if (kerr) {
++        ret = EIO;
++        goto done;
++    }
++
++    kerr = krb5_cc_resolve(cc->context, ccname, &cc->ccache);
++    if (kerr == KRB5_FCC_NOFILE || cc->ccache == NULL) {
++        DEBUG(SSSDBG_TRACE_FUNC, ("ccache %s is missing or empty\n", ccname));
++        ret = ERR_NOT_FOUND;
++        goto done;
++    } else if (kerr != 0) {
++        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
++        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
++        ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (ret) {
++        talloc_free(cc);
++    } else {
++        *ccache = cc;
++    }
++    return ret;
++}
++
++static errno_t sss_destroy_ccache(struct sss_krb5_ccache *cc)
++{
++    krb5_error_code kerr;
++    errno_t ret;
++
++    kerr = krb5_cc_destroy(cc->context, cc->ccache);
++    if (kerr) {
++        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
++        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_destroy failed.\n"));
++        ret = EIO;
++    }
++
++    /* krb5_cc_destroy frees cc->ccache in all events */
++    cc->ccache = NULL;
++
++    return ret;
++}
++
++errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid)
++{
++    struct sss_krb5_ccache *cc = NULL;
++    TALLOC_CTX *tmp_ctx;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
++        return ENOMEM;
++    }
++
++    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
++    if (ret) {
++        goto done;
++    }
++
++    ret = sss_destroy_ccache(cc);
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
+ 
+ /*======== ccache back end utilities ========*/
+ struct sss_krb5_cc_be *
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index aac3ec72ec7e1664ae96cc4e53d368e22448f5f1..ebcfe938af913f107b8816c3209b690ac90e797e 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -87,6 +87,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
+                      struct sss_creds **saved_creds);
+ errno_t restore_creds(struct sss_creds *saved_creds);
+ 
++errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
++
+ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                              struct tgt_times *tgtt);
+ 
+-- 
+1.8.3.1
+
diff --git a/0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch b/0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch
new file mode 100644
index 0000000..d18f7c2
--- /dev/null
+++ b/0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch
@@ -0,0 +1,279 @@
+From a70e88f62e8ba48c5042b881f20ed6586cb135a8 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Wed, 28 Aug 2013 23:18:37 -0400
+Subject: [PATCH 03/14] krb5: Use krb5_cc_destroy to remove old ccaches
+
+This completely replaces the per-ccache-type custom code to remove old cacches
+and instead uses libkrb5 base doperations (krb5_cc_destroy) and operating as
+the user owner.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ Makefile.am                     |  2 ++
+ src/providers/krb5/krb5_auth.c  | 63 +++++++++++-------------------------
+ src/providers/krb5/krb5_utils.c | 71 -----------------------------------------
+ src/providers/krb5/krb5_utils.h |  2 --
+ src/tests/krb5_child-test.c     |  2 +-
+ 5 files changed, 21 insertions(+), 119 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 150f53e72cfa68dc5d32aa90ad475a72000ba3fb..25a4cbf83c790b85fab9ccccd611f59704a5b301 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -962,6 +962,7 @@ strtonum_tests_LDADD = \
+ krb5_utils_tests_SOURCES = \
+     src/tests/krb5_utils-tests.c \
+     src/providers/krb5/krb5_utils.c \
++    src/providers/krb5/krb5_become_user.c \
+     src/providers/krb5/krb5_common.c \
+     src/util/sss_krb5.c \
+     src/util/find_uid.c \
+@@ -1532,6 +1533,7 @@ libsss_ldap_la_SOURCES = \
+     src/providers/ldap/ldap_access.c \
+     src/providers/krb5/krb5_common.c \
+     src/providers/krb5/krb5_utils.c \
++    src/providers/krb5/krb5_become_user.c \
+     src/util/user_info_msg.c \
+     src/util/sss_ldap.c \
+     src/util/sss_krb5.c
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index db0aa936ff5577afedf72cb43f1c71485e16505c..5d33dddb6d3bf28c7021580a3859a257b1507210 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -40,48 +40,19 @@
+ #include "providers/krb5/krb5_auth.h"
+ #include "providers/krb5/krb5_utils.h"
+ 
+-static errno_t safe_remove_old_ccache_file(struct sss_krb5_cc_be *cc_be,
+-                                           const char *princ,
+-                                           const char *old_ccache,
+-                                           const char *new_ccache)
++static errno_t safe_remove_old_ccache_file(const char *old_ccache,
++                                           const char *new_ccache,
++                                           uid_t uid, gid_t gid)
+ {
+-    int ret;
+-    enum sss_krb5_cc_type old_type;
+-    struct sss_krb5_cc_be *old_cc_ops;
+-
+-    if (old_ccache == NULL) {
+-        DEBUG(SSSDBG_FUNC_DATA, ("No old ccache, nothing to do\n"));
+-        return EOK;
+-    }
+-
+-    if (new_ccache == NULL) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              ("Missing new ccache file, old ccache file is not deleted.\n"));
+-        return EINVAL;
+-    }
+-
+-    old_type = sss_krb5_get_type(old_ccache);
+-    old_cc_ops = get_cc_be_ops(old_type);
+-    if (!old_cc_ops) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get ccache operations\n"));
+-        return EINVAL;
+-    }
+-
+-    if (cc_be->type == old_type &&
+-        strcmp(old_ccache, new_ccache) == 0) {
++    if ((old_ccache == new_ccache)
++        || (old_ccache && new_ccache
++            && (strcmp(old_ccache, new_ccache) == 0))) {
+         DEBUG(SSSDBG_TRACE_FUNC, ("New and old ccache file are the same, "
+-                                  "no one will be deleted.\n"));
++                                  "none will be deleted.\n"));
+         return EOK;
+     }
+ 
+-    ret = old_cc_ops->remove(old_ccache);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-                ("Cannot remove ccache [%s]\n", old_ccache));
+-        return EIO;
+-    }
+-
+-    return EOK;
++    return sss_krb5_cc_destroy(old_ccache, uid, gid);
+ }
+ 
+ static errno_t
+@@ -1037,8 +1008,8 @@ static void krb5_auth_done(struct tevent_req *subreq)
+          * used. */
+         if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache) {
+             if (kr->old_ccname != NULL) {
+-                ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
+-                                                  kr->old_ccname, "dummy");
++                ret = safe_remove_old_ccache_file(kr->old_ccname, NULL,
++                                                  kr->uid, kr->gid);
+                 if (ret != EOK) {
+                     DEBUG(1, ("Failed to remove old ccache file [%s], "
+                               "please remove it manually.\n", kr->old_ccname));
+@@ -1114,12 +1085,14 @@ static void krb5_auth_done(struct tevent_req *subreq)
+         goto done;
+     }
+ 
+-    ret = safe_remove_old_ccache_file(kr->cc_be, kr->upn,
+-                                      kr->old_ccname, store_ccname);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_MINOR_FAILURE,
+-              ("Failed to remove old ccache file [%s], "
+-               "please remove it manually.\n", kr->old_ccname));
++    if (kr->old_ccname) {
++        ret = safe_remove_old_ccache_file(kr->old_ccname, store_ccname,
++                                          kr->uid, kr->gid);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_MINOR_FAILURE,
++                  ("Failed to remove old ccache file [%s], "
++                   "please remove it manually.\n", kr->old_ccname));
++        }
+     }
+ 
+     ret = krb5_save_ccname(state, state->sysdb, state->domain,
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index 1141f3fc839a78927dab5f50267c52d5b44b46ba..0245cc9d008f64e00717dc3e878357ddf2fae9fa 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -1120,42 +1120,11 @@ cc_file_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
+     return talloc_strdup(mem_ctx, location);
+ }
+ 
+-errno_t
+-cc_file_remove(const char *location)
+-{
+-    errno_t ret;
+-    const char *filename;
+-
+-    filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
+-    if (!filename) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type FILE:\n", location));
+-        return EINVAL;
+-    }
+-
+-    if (filename[0] != '/') {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("Ccache file name [%s] is not an absolute path.\n", filename));
+-        return EINVAL;
+-    }
+-
+-    errno = 0;
+-    ret = unlink(filename);
+-    if (ret == -1 && errno != ENOENT) {
+-        ret = errno;
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("unlink [%s] failed [%d][%s].\n", filename, ret,
+-                                                 strerror(ret)));
+-        return ret;
+-    }
+-    return EOK;
+-}
+-
+ struct sss_krb5_cc_be file_cc = {
+     .type               = SSS_KRB5_TYPE_FILE,
+     .create             = cc_file_create,
+     .check_existing     = cc_file_check_existing,
+     .ccache_for_princ   = cc_file_cache_for_princ,
+-    .remove             = cc_file_remove,
+ };
+ 
+ #ifdef HAVE_KRB5_CC_COLLECTION
+@@ -1333,32 +1302,11 @@ done:
+     return name;
+ }
+ 
+-errno_t
+-cc_dir_remove(const char *location)
+-{
+-    const char *subsidiary;
+-
+-    if (sss_krb5_get_type(location) != SSS_KRB5_TYPE_DIR) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type DIR\n", location));
+-        return EINVAL;
+-    }
+-
+-    subsidiary = sss_krb5_cc_file_path(location);
+-    if (!subsidiary) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get subsidiary cache from %s\n",
+-              location));
+-        return EINVAL;
+-    }
+-
+-    return cc_file_remove(subsidiary);
+-}
+-
+ struct sss_krb5_cc_be dir_cc = {
+     .type               = SSS_KRB5_TYPE_DIR,
+     .create             = cc_dir_create,
+     .check_existing     = cc_dir_check_existing,
+     .ccache_for_princ   = cc_dir_cache_for_princ,
+-    .remove             = cc_dir_remove
+ };
+ 
+ 
+@@ -1485,30 +1433,11 @@ done:
+     return name;
+ }
+ 
+-errno_t
+-cc_keyring_remove(const char *location)
+-{
+-    const char *residual;
+-
+-    residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
+-    if (!residual) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("%s is not of type KEYRING:\n", location));
+-        return EINVAL;
+-    }
+-
+-    /* No special steps are needed to create a kernel keyring.
+-     * Everything is handled in libkrb5.
+-     */
+-    return EOK;
+-}
+-
+ struct sss_krb5_cc_be keyring_cc = {
+     .type               = SSS_KRB5_TYPE_KEYRING,
+     .create             = cc_keyring_create,
+     .check_existing     = cc_keyring_check_existing,
+     .ccache_for_princ   = cc_keyring_cache_for_princ,
+-    .remove             = cc_keyring_remove
+ };
+ 
+ #endif /* HAVE_KRB5_CC_COLLECTION */
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index ebcfe938af913f107b8816c3209b690ac90e797e..ac29d61e9e4efe963c835e8646ce540e09dc8dd7 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -52,7 +52,6 @@ typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
+ typedef const char * (*cc_be_ccache_for_princ)(TALLOC_CTX *mem_ctx,
+                                                const char *location,
+                                                const char *princ);
+-typedef errno_t (*cc_be_remove)(const char *location);
+ 
+ /* A ccache back end */
+ struct sss_krb5_cc_be {
+@@ -61,7 +60,6 @@ struct sss_krb5_cc_be {
+     cc_be_create_fn create;
+     cc_be_check_existing check_existing;
+     cc_be_ccache_for_princ ccache_for_princ;
+-    cc_be_remove remove;
+ };
+ 
+ extern struct sss_krb5_cc_be file_cc;
+diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
+index 24d077289d64d52488a3419ffc4494f59d6bc5df..dff62ab64dd1948d20da6b640a0570ee8ea6b11d 100644
+--- a/src/tests/krb5_child-test.c
++++ b/src/tests/krb5_child-test.c
+@@ -561,7 +561,7 @@ done:
+     if (rm_ccache && ctx->res
+             && ctx->res->ccname
+             && ctx->kr) {
+-        ctx->kr->krb5_ctx->cc_be->remove(ctx->res->ccname);
++        sss_krb5_cc_destroy(ctx->res->ccname, ctx->kr->uid, ctx->kr->gid);
+     }
+     free(password);
+     talloc_free(ctx);
+-- 
+1.8.3.1
+
diff --git a/0004-krb5-Replace-type-specific-ccache-principal-check.patch b/0004-krb5-Replace-type-specific-ccache-principal-check.patch
new file mode 100644
index 0000000..c47eebd
--- /dev/null
+++ b/0004-krb5-Replace-type-specific-ccache-principal-check.patch
@@ -0,0 +1,357 @@
+From 1536e39c191a013bc50bb6fd4b8eaef11cf0d436 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 00:58:24 -0400
+Subject: [PATCH 04/14] krb5: Replace type-specific ccache/principal check
+
+Instead of having duplicate functions that are type custom use a signle common
+function that also performs access to the cache as the user owner, implicitly
+validating correctness of ownership.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c  |  11 +-
+ src/providers/krb5/krb5_utils.c | 220 +++++++++++++++-------------------------
+ src/providers/krb5/krb5_utils.h |   6 +-
+ 3 files changed, 89 insertions(+), 148 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index 5d33dddb6d3bf28c7021580a3859a257b1507210..976fdec097a06ae5b211a5a93dcb13b9548031ef 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -837,7 +837,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
+     uint8_t *buf = NULL;
+     ssize_t len = -1;
+     struct krb5_child_response *res;
+-    const char *store_ccname;
+     struct fo_server *search_srv;
+     krb5_deltat renew_interval_delta;
+     char *renew_interval_str;
+@@ -1076,17 +1075,15 @@ static void krb5_auth_done(struct tevent_req *subreq)
+         goto done;
+     }
+ 
+-    store_ccname = kr->cc_be->ccache_for_princ(kr, kr->ccname,
+-                                               kr->upn);
+-    if (store_ccname == NULL) {
++    ret = sss_krb5_check_ccache_princ(kr->uid, kr->gid, kr->ccname, kr->upn);
++    if (ret) {
+         DEBUG(SSSDBG_CRIT_FAILURE,
+                 ("No ccache for %s in %s?\n", kr->upn, kr->ccname));
+-        ret = EIO;
+         goto done;
+     }
+ 
+     if (kr->old_ccname) {
+-        ret = safe_remove_old_ccache_file(kr->old_ccname, store_ccname,
++        ret = safe_remove_old_ccache_file(kr->old_ccname, kr->ccname,
+                                           kr->uid, kr->gid);
+         if (ret != EOK) {
+             DEBUG(SSSDBG_MINOR_FAILURE,
+@@ -1096,7 +1093,7 @@ static void krb5_auth_done(struct tevent_req *subreq)
+     }
+ 
+     ret = krb5_save_ccname(state, state->sysdb, state->domain,
+-                           pd->user, store_ccname);
++                           pd->user, kr->ccname);
+     if (ret) {
+         DEBUG(1, ("krb5_save_ccname failed.\n"));
+         goto done;
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index 0245cc9d008f64e00717dc3e878357ddf2fae9fa..ce3cab60d71a8b3329eeedbd82bec6ecb750948c 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -928,6 +928,89 @@ done:
+ }
+ 
+ 
++/* This function is called only as a way to validate that we have the
++ * right cache */
++errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
++                                    const char *ccname, const char *principal)
++{
++    struct sss_krb5_ccache *cc = NULL;
++    krb5_principal ccprinc = NULL;
++    krb5_principal kprinc = NULL;
++    krb5_error_code kerr;
++    const char *cc_type;
++    TALLOC_CTX *tmp_ctx;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
++        return ENOMEM;
++    }
++
++    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
++    if (ret) {
++        goto done;
++    }
++
++    cc_type = krb5_cc_get_type(cc->context, cc->ccache);
++
++    DEBUG(SSSDBG_TRACE_INTERNAL,
++          ("Searching for [%s] in cache of type [%s]\n", principal, cc_type));
++
++    kerr = krb5_parse_name(cc->context, principal, &kprinc);
++    if (kerr != 0) {
++        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
++        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
++        ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    kerr = krb5_cc_get_principal(cc->context, cc->ccache, &ccprinc);
++    if (kerr != 0) {
++        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
++        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_get_principal failed.\n"));
++    }
++
++    if (ccprinc) {
++        if (krb5_principal_compare(cc->context, kprinc, ccprinc) == TRUE) {
++            /* found in the primary ccache */
++            ret = EOK;
++            goto done;
++        }
++    }
++
++#ifdef HAVE_KRB5_CC_COLLECTION
++
++    if (krb5_cc_support_switch(cc->context, cc_type)) {
++
++        krb5_cc_close(cc->context, cc->ccache);
++        cc->ccache = NULL;
++
++        kerr = krb5_cc_set_default_name(cc->context, ccname);
++        if (kerr != 0) {
++            KRB5_DEBUG(SSSDBG_MINOR_FAILURE, cc->context, kerr);
++            /* try to continue despite failure */
++        }
++
++        kerr = krb5_cc_cache_match(cc->context, kprinc, &cc->ccache);
++        if (kerr == 0) {
++            ret = EOK;
++            goto done;
++        }
++        KRB5_DEBUG(SSSDBG_TRACE_INTERNAL, cc->context, kerr);
++    }
++
++#endif /* HAVE_KRB5_CC_COLLECTION */
++
++    ret = ERR_NOT_FOUND;
++
++done:
++    krb5_free_principal(cc->context, ccprinc);
++    krb5_free_principal(cc->context, kprinc);
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
+ /*======== ccache back end utilities ========*/
+ struct sss_krb5_cc_be *
+ get_cc_be_ops(enum sss_krb5_cc_type type)
+@@ -1113,18 +1196,10 @@ cc_file_check_existing(const char *location, uid_t uid,
+     return EOK;
+ }
+ 
+-const char *
+-cc_file_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
+-                        const char *princ)
+-{
+-    return talloc_strdup(mem_ctx, location);
+-}
+-
+ struct sss_krb5_cc_be file_cc = {
+     .type               = SSS_KRB5_TYPE_FILE,
+     .create             = cc_file_create,
+     .check_existing     = cc_file_check_existing,
+-    .ccache_for_princ   = cc_file_cache_for_princ,
+ };
+ 
+ #ifdef HAVE_KRB5_CC_COLLECTION
+@@ -1246,67 +1321,10 @@ done:
+     return ret;
+ }
+ 
+-const char *
+-cc_dir_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
+-                       const char *princ)
+-{
+-    krb5_context context = NULL;
+-    krb5_error_code krberr;
+-    char *name = NULL;
+-    const char *ccname;
+-    krb5_principal client_principal = NULL;
+-
+-    ccname = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR);
+-    if (!ccname) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get ccname file from %s\n",
+-              location));
+-        return NULL;
+-    }
+-
+-    /* ccname already points to a subsidiary cache */
+-    if (ccname[0] == ':' && ccname[1] && ccname[1] == '/') {
+-        return talloc_strdup(mem_ctx, location);
+-    }
+-
+-    krberr = krb5_init_context(&context);
+-    if (krberr) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("Failed to init kerberos context\n"));
+-        return NULL;
+-    }
+-
+-    krberr = krb5_parse_name(context, princ, &client_principal);
+-    if (krberr != 0) {
+-        KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
+-        goto done;
+-    }
+-
+-    /* This function is called only as a way to validate that,
+-     * we have the right cache
+-     */
+-    name = sss_get_ccache_name_for_principal(mem_ctx, context,
+-                                             client_principal, location);
+-    if (name == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get full name of ccache\n"));
+-        goto done;
+-    }
+-
+-    talloc_zfree(name);
+-    /* everytime return location for dir_cache */
+-    name = talloc_strdup(mem_ctx, location);
+-
+-done:
+-    krb5_free_principal(context, client_principal);
+-    krb5_free_context(context);
+-
+-    return name;
+-}
+-
+ struct sss_krb5_cc_be dir_cc = {
+     .type               = SSS_KRB5_TYPE_DIR,
+     .create             = cc_dir_create,
+     .check_existing     = cc_dir_check_existing,
+-    .ccache_for_princ   = cc_dir_cache_for_princ,
+ };
+ 
+ 
+@@ -1362,82 +1380,10 @@ cc_keyring_check_existing(const char *location, uid_t uid,
+     return EOK;
+ }
+ 
+-const char *
+-cc_keyring_cache_for_princ(TALLOC_CTX *mem_ctx, const char *location,
+-                           const char *princ)
+-{
+-    krb5_context context = NULL;
+-    krb5_error_code krberr;
+-    char *name = NULL;
+-    const char *residual;
+-    size_t i;
+-    size_t count;
+-    krb5_principal client_principal = NULL;
+-
+-    residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
+-    if (!residual) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot get residual from %s\n",
+-              location));
+-        return NULL;
+-    }
+-
+-    /* residual already points to a subsidiary cache if it of the
+-     * form "KEYRING:<type>:<UID>:krb5_cc_XXXXXXX"
+-     * For simplicity, we'll count the colons, up to three.
+-     */
+-    i = count = 0;
+-    while (residual[i] && count < 3) {
+-        if (residual[i] == ':') {
+-            count ++;
+-        }
+-        i++;
+-    }
+-
+-    if (count >= 3) {
+-        return talloc_strdup(mem_ctx, location);
+-    }
+-
+-    krberr = krb5_init_context(&context);
+-    if (krberr) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("Failed to init kerberos context\n"));
+-        return NULL;
+-    }
+-
+-    krberr = krb5_parse_name(context, princ, &client_principal);
+-    if (krberr != 0) {
+-        KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_parse_name failed.\n"));
+-        goto done;
+-    }
+-
+-    name = sss_get_ccache_name_for_principal(mem_ctx, context,
+-                                             client_principal, location);
+-    if (name == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get full name of ccache\n"));
+-        goto done;
+-    }
+-
+-    talloc_zfree(name);
+-
+-    /* Always return the master name here.
+-     * We do the above only to ensure that the
+-     * principal-specific name exists and can
+-     * be found.
+-     */
+-    name = talloc_strdup(mem_ctx, location);
+-
+-done:
+-    krb5_free_principal(context, client_principal);
+-    krb5_free_context(context);
+-
+-    return name;
+-}
+-
+ struct sss_krb5_cc_be keyring_cc = {
+     .type               = SSS_KRB5_TYPE_KEYRING,
+     .create             = cc_keyring_create,
+     .check_existing     = cc_keyring_check_existing,
+-    .ccache_for_princ   = cc_keyring_cache_for_princ,
+ };
+ 
+ #endif /* HAVE_KRB5_CC_COLLECTION */
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index ac29d61e9e4efe963c835e8646ce540e09dc8dd7..a73098d4090199c5a49bdf0adf5115e9120eeb5b 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -49,9 +49,6 @@ typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
+                                         const char *realm, const char *princ,
+                                         const char *cc_template, bool *active,
+                                         bool *valid);
+-typedef const char * (*cc_be_ccache_for_princ)(TALLOC_CTX *mem_ctx,
+-                                               const char *location,
+-                                               const char *princ);
+ 
+ /* A ccache back end */
+ struct sss_krb5_cc_be {
+@@ -59,7 +56,6 @@ struct sss_krb5_cc_be {
+ 
+     cc_be_create_fn create;
+     cc_be_check_existing check_existing;
+-    cc_be_ccache_for_princ ccache_for_princ;
+ };
+ 
+ extern struct sss_krb5_cc_be file_cc;
+@@ -86,6 +82,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
+ errno_t restore_creds(struct sss_creds *saved_creds);
+ 
+ errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
++errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
++                                    const char *ccname, const char *principal);
+ 
+ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                              struct tgt_times *tgtt);
+-- 
+1.8.3.1
+
diff --git a/0005-krb5-Move-determination-of-user-being-active.patch b/0005-krb5-Move-determination-of-user-being-active.patch
new file mode 100644
index 0000000..8172582
--- /dev/null
+++ b/0005-krb5-Move-determination-of-user-being-active.patch
@@ -0,0 +1,220 @@
+From bfd32c9e8f302d7722838a68572c6801f5640657 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 11:31:23 -0400
+Subject: [PATCH 05/14] krb5: Move determination of user being active
+
+The way a user is checked for being active does not depend on the ccache
+type so move that check out of the ccache specific functions.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c  | 10 +++++++--
+ src/providers/krb5/krb5_utils.c | 47 +++++++----------------------------------
+ src/providers/krb5/krb5_utils.h |  3 +--
+ 3 files changed, 17 insertions(+), 43 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index 976fdec097a06ae5b211a5a93dcb13b9548031ef..178f18a3c5dec4772a59c6d6cfbcdc419c20d48c 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -76,7 +76,7 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+     cc_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL);
+ 
+     ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm, kr->upn,
+-                                     cc_template, active, valid);
++                                     cc_template, valid);
+     if (ret == ENOENT) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               ("Saved ccache %s doesn't exist.\n", old_ccache));
+@@ -84,11 +84,17 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+     }
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE,
+-              ("Cannot check if saved ccache %s is active and valid\n",
++              ("Cannot check if saved ccache %s is valid\n",
+                old_ccache));
+         return ret;
+     }
+ 
++    ret = check_if_uid_is_active(kr->uid, active);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, ("check_if_uid_is_active failed.\n"));
++        return ret;
++    }
++
+     return EOK;
+ }
+ 
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index ce3cab60d71a8b3329eeedbd82bec6ecb750948c..7f2ca2d5ba570e3467ec7dc4060f58f38b1f3428 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -1066,14 +1066,11 @@ cc_file_create(const char *location, pcre *illegal_re,
+ }
+ 
+ static errno_t
+-cc_residual_is_used(uid_t uid, const char *ccname,
+-                    enum sss_krb5_cc_type type, bool *result)
++cc_residual_exists(uid_t uid, const char *ccname,
++                   enum sss_krb5_cc_type type)
+ {
+     int ret;
+     struct stat stat_buf;
+-    bool active;
+-
+-    *result = false;
+ 
+     if (ccname == NULL || *ccname == '\0') {
+         return EINVAL;
+@@ -1086,7 +1083,6 @@ cc_residual_is_used(uid_t uid, const char *ccname,
+         if (ret == ENOENT) {
+             DEBUG(SSSDBG_FUNC_DATA, ("Cache file [%s] does not exist, "
+                                      "it will be recreated\n", ccname));
+-            *result = false;
+             return ENOENT;
+         }
+ 
+@@ -1123,20 +1119,6 @@ cc_residual_is_used(uid_t uid, const char *ccname,
+         return EINVAL;
+     }
+ 
+-    ret = check_if_uid_is_active(uid, &active);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("check_if_uid_is_active failed.\n"));
+-        return ret;
+-    }
+-
+-    if (!active) {
+-        DEBUG(SSSDBG_TRACE_FUNC, ("User [%d] is not active\n", uid));
+-    } else {
+-        DEBUG(SSSDBG_TRACE_LIBS,
+-              ("User [%d] is still active, reusing ccache [%s].\n",
+-              uid, ccname));
+-        *result = true;
+-    }
+     return EOK;
+ }
+ 
+@@ -1157,10 +1139,9 @@ cc_check_template(const char *cc_template)
+ errno_t
+ cc_file_check_existing(const char *location, uid_t uid,
+                        const char *realm, const char *princ,
+-                       const char *cc_template, bool *_active, bool *_valid)
++                       const char *cc_template, bool *_valid)
+ {
+     errno_t ret;
+-    bool active;
+     bool valid;
+     const char *filename;
+ 
+@@ -1175,14 +1156,13 @@ cc_file_check_existing(const char *location, uid_t uid,
+         return EINVAL;
+     }
+ 
+-    ret = cc_residual_is_used(uid, filename, SSS_KRB5_TYPE_FILE, &active);
++    ret = cc_residual_exists(uid, filename, SSS_KRB5_TYPE_FILE);
+     if (ret != EOK) {
+         if (ret != ENOENT) {
+             DEBUG(SSSDBG_OP_FAILURE,
+                   ("Could not check if ccache is active.\n"));
+         }
+         cc_check_template(cc_template);
+-        active = false;
+         return ret;
+     }
+ 
+@@ -1191,7 +1171,6 @@ cc_file_check_existing(const char *location, uid_t uid,
+         return ret;
+     }
+ 
+-    *_active = active;
+     *_valid = valid;
+     return EOK;
+ }
+@@ -1222,10 +1201,8 @@ cc_dir_create(const char *location, pcre *illegal_re,
+ errno_t
+ cc_dir_check_existing(const char *location, uid_t uid,
+                       const char *realm, const char *princ,
+-                      const char *cc_template, bool *_active, bool *_valid)
++                      const char *cc_template, bool *_valid)
+ {
+-    bool active;
+-    bool active_primary = false;
+     bool valid;
+     enum sss_krb5_cc_type type;
+     const char *filename;
+@@ -1279,7 +1256,7 @@ cc_dir_check_existing(const char *location, uid_t uid,
+         dir = tmp;
+     }
+ 
+-    ret = cc_residual_is_used(uid, dir, SSS_KRB5_TYPE_DIR, &active);
++    ret = cc_residual_exists(uid, dir, SSS_KRB5_TYPE_DIR);
+     if (ret != EOK) {
+         if (ret != ENOENT) {
+             DEBUG(SSSDBG_OP_FAILURE,
+@@ -1298,8 +1275,7 @@ cc_dir_check_existing(const char *location, uid_t uid,
+         ret = ENOMEM;
+         goto done;
+     }
+-    ret = cc_residual_is_used(uid, primary_file, SSS_KRB5_TYPE_FILE,
+-                              &active_primary);
++    ret = cc_residual_exists(uid, primary_file, SSS_KRB5_TYPE_FILE);
+     if (ret != EOK && ret != ENOENT) {
+         DEBUG(SSSDBG_OP_FAILURE,
+               ("Could not check if file 'primary' [%s] in dir ccache"
+@@ -1312,7 +1288,6 @@ cc_dir_check_existing(const char *location, uid_t uid,
+         goto done;
+     }
+ 
+-    *_active = active;
+     *_valid = valid;
+     ret = EOK;
+ 
+@@ -1351,11 +1326,9 @@ cc_keyring_create(const char *location, pcre *illegal_re,
+ errno_t
+ cc_keyring_check_existing(const char *location, uid_t uid,
+                           const char *realm, const char *princ,
+-                          const char *cc_template, bool *_active,
+-                          bool *_valid)
++                          const char *cc_template, bool *_valid)
+ {
+     errno_t ret;
+-    bool active;
+     bool valid;
+     const char *residual;
+ 
+@@ -1366,16 +1339,12 @@ cc_keyring_check_existing(const char *location, uid_t uid,
+         return EINVAL;
+     }
+ 
+-    /* The keyring cache is always active */
+-    active = true;
+-
+     /* Check if any user is actively using this cache */
+     ret = check_cc_validity(location, realm, princ, &valid);
+     if (ret != EOK) {
+         return ret;
+     }
+ 
+-    *_active = active;
+     *_valid = valid;
+     return EOK;
+ }
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index a73098d4090199c5a49bdf0adf5115e9120eeb5b..ca33205817cbb726a75b809f71d1fb1589744e15 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -47,8 +47,7 @@ typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
+                                    uid_t uid, gid_t gid, bool private_path);
+ typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
+                                         const char *realm, const char *princ,
+-                                        const char *cc_template, bool *active,
+-                                        bool *valid);
++                                        const char *cc_template, bool *valid);
+ 
+ /* A ccache back end */
+ struct sss_krb5_cc_be {
+-- 
+1.8.3.1
+
diff --git a/0006-krb5-move-template-check-to-initializzation.patch b/0006-krb5-move-template-check-to-initializzation.patch
new file mode 100644
index 0000000..63b350f
--- /dev/null
+++ b/0006-krb5-move-template-check-to-initializzation.patch
@@ -0,0 +1,160 @@
+From 5dc3b01fd9b2fa244e7c2820ce04602c9f059370 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 12:21:39 -0400
+Subject: [PATCH 06/14] krb5: move template check to initializzation
+
+The randomized template check realy only makes sense for the FILE ccache
+which is the only one that normally needs to use randomizing chars.
+Also it is better to warn the admin early rather than to warn 'when it
+is too late'.
+So move the check at initialization time when we determine what the
+template actually is.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c   |  5 +----
+ src/providers/krb5/krb5_common.c | 17 +++++++++++++++++
+ src/providers/krb5/krb5_utils.c  | 22 +++-------------------
+ src/providers/krb5/krb5_utils.h  |  2 +-
+ 4 files changed, 22 insertions(+), 24 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index 178f18a3c5dec4772a59c6d6cfbcdc419c20d48c..ca00ce7a3aefa6dae3116f57c994d1f5cd1f50ea 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -60,7 +60,6 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+                  const char *realm, bool *active, bool *valid)
+ {
+     struct sss_krb5_cc_be *old_cc_ops;
+-    const char *cc_template;
+     errno_t ret;
+ 
+     /* ccache file might be of a different type if the user changed
+@@ -73,10 +72,8 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+         return EINVAL;
+     }
+ 
+-    cc_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL);
+-
+     ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm, kr->upn,
+-                                     cc_template, valid);
++                                     valid);
+     if (ret == ENOENT) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               ("Saved ccache %s doesn't exist.\n", old_ccache));
+diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
+index c7ce574d513702132cb7e0c8ca4f1f1b80430f0b..de7ae0a8fe345c38f9458fb9642a5c1b83c906f5 100644
+--- a/src/providers/krb5/krb5_common.c
++++ b/src/providers/krb5/krb5_common.c
+@@ -144,6 +144,19 @@ static errno_t sss_get_system_ccname_template(TALLOC_CTX *mem_ctx,
+ }
+ #endif
+ 
++static void sss_check_cc_template(const char *cc_template)
++{
++    size_t template_len;
++
++    template_len = strlen(cc_template);
++    if (template_len >= 6 &&
++        strcmp(cc_template + (template_len - 6), "XXXXXX") != 0) {
++        DEBUG(SSSDBG_CONF_SETTINGS, ("ccache file name template [%s] doesn't "
++                   "contain randomizing characters (XXXXXX), file might not "
++                   "be rewritable\n", cc_template));
++    }
++}
++
+ errno_t check_and_export_options(struct dp_option *opts,
+                                  struct sss_domain_info *dom,
+                                  struct krb5_ctx *krb5_ctx)
+@@ -282,6 +295,10 @@ errno_t check_and_export_options(struct dp_option *opts,
+     switch (cc_be) {
+     case SSS_KRB5_TYPE_FILE:
+         DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n"));
++        /* warn if the file type (which is usally created in a sticky bit
++         * laden directory) does not have randomizing chracters */
++        sss_check_cc_template(ccname);
++
+         krb5_ctx->cc_be = &file_cc;
+         if (ccname[0] != '/') {
+             /* FILE:/path/to/cc */
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index 7f2ca2d5ba570e3467ec7dc4060f58f38b1f3428..b174462ee4e8f3992e6d9c06f91118098c598149 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -1122,24 +1122,10 @@ cc_residual_exists(uid_t uid, const char *ccname,
+     return EOK;
+ }
+ 
+-static void
+-cc_check_template(const char *cc_template)
+-{
+-    size_t template_len;
+-
+-    template_len = strlen(cc_template);
+-    if (template_len >= 6 &&
+-        strcmp(cc_template + (template_len - 6), "XXXXXX") != 0) {
+-        DEBUG(SSSDBG_CONF_SETTINGS, ("ccache file name template [%s] doesn't "
+-                   "contain randomizing characters (XXXXXX), file might not "
+-                   "be rewritable\n", cc_template));
+-    }
+-}
+-
+ errno_t
+ cc_file_check_existing(const char *location, uid_t uid,
+                        const char *realm, const char *princ,
+-                       const char *cc_template, bool *_valid)
++                       bool *_valid)
+ {
+     errno_t ret;
+     bool valid;
+@@ -1162,7 +1148,6 @@ cc_file_check_existing(const char *location, uid_t uid,
+             DEBUG(SSSDBG_OP_FAILURE,
+                   ("Could not check if ccache is active.\n"));
+         }
+-        cc_check_template(cc_template);
+         return ret;
+     }
+ 
+@@ -1201,7 +1186,7 @@ cc_dir_create(const char *location, pcre *illegal_re,
+ errno_t
+ cc_dir_check_existing(const char *location, uid_t uid,
+                       const char *realm, const char *princ,
+-                      const char *cc_template, bool *_valid)
++                      bool *_valid)
+ {
+     bool valid;
+     enum sss_krb5_cc_type type;
+@@ -1262,7 +1247,6 @@ cc_dir_check_existing(const char *location, uid_t uid,
+             DEBUG(SSSDBG_OP_FAILURE,
+                   ("Could not check if ccache is active.\n"));
+         }
+-        cc_check_template(cc_template);
+         goto done;
+     }
+ 
+@@ -1326,7 +1310,7 @@ cc_keyring_create(const char *location, pcre *illegal_re,
+ errno_t
+ cc_keyring_check_existing(const char *location, uid_t uid,
+                           const char *realm, const char *princ,
+-                          const char *cc_template, bool *_valid)
++                          bool *_valid)
+ {
+     errno_t ret;
+     bool valid;
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index ca33205817cbb726a75b809f71d1fb1589744e15..e241666289193bdc3c5eccadfffc4d3d669dff16 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -47,7 +47,7 @@ typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
+                                    uid_t uid, gid_t gid, bool private_path);
+ typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
+                                         const char *realm, const char *princ,
+-                                        const char *cc_template, bool *valid);
++                                        bool *valid);
+ 
+ /* A ccache back end */
+ struct sss_krb5_cc_be {
+-- 
+1.8.3.1
+
diff --git a/0007-krb5-Make-check_for_valid_tgt-static.patch b/0007-krb5-Make-check_for_valid_tgt-static.patch
new file mode 100644
index 0000000..377cfb3
--- /dev/null
+++ b/0007-krb5-Make-check_for_valid_tgt-static.patch
@@ -0,0 +1,201 @@
+From c121e65ed592bf3611053ee38032fd33c8d1b285 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 12:27:49 -0400
+Subject: [PATCH 07/14] krb5: Make check_for_valid_tgt() static
+
+check_for_valid_tgt() is used exclusively in krb5_uitls.c so move it there.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_utils.c | 74 +++++++++++++++++++++++++++++++++++++++++
+ src/util/sss_krb5.c             | 72 ---------------------------------------
+ src/util/sss_krb5.h             |  4 ---
+ 3 files changed, 74 insertions(+), 76 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index b174462ee4e8f3992e6d9c06f91118098c598149..463a5eb409d076825f25d45c034d58f4a89780eb 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -761,6 +761,80 @@ done:
+     return ret;
+ }
+ 
++static krb5_error_code check_for_valid_tgt(krb5_context context,
++                                           krb5_ccache ccache,
++                                           const char *realm,
++                                           const char *client_princ_str,
++                                           bool *result)
++{
++    krb5_error_code krberr;
++    TALLOC_CTX *tmp_ctx = NULL;
++    krb5_creds mcred;
++    krb5_creds cred;
++    char *server_name = NULL;
++    krb5_principal client_principal = NULL;
++    krb5_principal server_principal = NULL;
++
++    *result = false;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(1, ("talloc_new failed.\n"));
++        return ENOMEM;
++    }
++
++    server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
++    if (server_name == NULL) {
++        DEBUG(1, ("talloc_asprintf failed.\n"));
++        krberr = ENOMEM;
++        goto done;
++    }
++
++    krberr = krb5_parse_name(context, server_name, &server_principal);
++    if (krberr != 0) {
++        DEBUG(1, ("krb5_parse_name failed.\n"));
++        goto done;
++    }
++
++    krberr = krb5_parse_name(context, client_princ_str, &client_principal);
++    if (krberr != 0) {
++        DEBUG(1, ("krb5_parse_name failed.\n"));
++        goto done;
++    }
++
++    memset(&mcred, 0, sizeof(mcred));
++    memset(&cred, 0, sizeof(mcred));
++    mcred.client = client_principal;
++    mcred.server = server_principal;
++
++    krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
++    if (krberr != 0) {
++        DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
++        krberr = 0;
++        goto done;
++    }
++
++    DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
++
++    if (cred.times.endtime > time(NULL)) {
++        DEBUG(3, ("TGT is valid.\n"));
++        *result = true;
++    }
++    krb5_free_cred_contents(context, &cred);
++
++    krberr = 0;
++
++done:
++    if (client_principal != NULL) {
++        krb5_free_principal(context, client_principal);
++    }
++    if (server_principal != NULL) {
++        krb5_free_principal(context, server_principal);
++    }
++    talloc_free(tmp_ctx);
++    return krberr;
++}
++
+ static errno_t
+ check_cc_validity(const char *location,
+                   const char *realm,
+diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
+index b25ed24919555666422e6a87ded8688ca76c345f..440edab8a4624b33b7d358e64ead93949fc3de88 100644
+--- a/src/util/sss_krb5.c
++++ b/src/util/sss_krb5.c
+@@ -546,78 +546,6 @@ void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
+ }
+ 
+ 
+-krb5_error_code check_for_valid_tgt(krb5_context context,
+-                                    krb5_ccache ccache, const char *realm,
+-                                    const char *client_princ_str, bool *result)
+-{
+-    krb5_error_code krberr;
+-    TALLOC_CTX *tmp_ctx = NULL;
+-    krb5_creds mcred;
+-    krb5_creds cred;
+-    char *server_name = NULL;
+-    krb5_principal client_principal = NULL;
+-    krb5_principal server_principal = NULL;
+-
+-    *result = false;
+-
+-    tmp_ctx = talloc_new(NULL);
+-    if (tmp_ctx == NULL) {
+-        DEBUG(1, ("talloc_new failed.\n"));
+-        return ENOMEM;
+-    }
+-
+-    server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
+-    if (server_name == NULL) {
+-        DEBUG(1, ("talloc_asprintf failed.\n"));
+-        krberr = ENOMEM;
+-        goto done;
+-    }
+-
+-    krberr = krb5_parse_name(context, server_name, &server_principal);
+-    if (krberr != 0) {
+-        DEBUG(1, ("krb5_parse_name failed.\n"));
+-        goto done;
+-    }
+-
+-    krberr = krb5_parse_name(context, client_princ_str, &client_principal);
+-    if (krberr != 0) {
+-        DEBUG(1, ("krb5_parse_name failed.\n"));
+-        goto done;
+-    }
+-
+-    memset(&mcred, 0, sizeof(mcred));
+-    memset(&cred, 0, sizeof(mcred));
+-    mcred.client = client_principal;
+-    mcred.server = server_principal;
+-
+-    krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
+-    if (krberr != 0) {
+-        DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
+-        krberr = 0;
+-        goto done;
+-    }
+-
+-    DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
+-
+-    if (cred.times.endtime > time(NULL)) {
+-        DEBUG(3, ("TGT is valid.\n"));
+-        *result = true;
+-    }
+-    krb5_free_cred_contents(context, &cred);
+-
+-    krberr = 0;
+-
+-done:
+-    if (client_principal != NULL) {
+-        krb5_free_principal(context, client_principal);
+-    }
+-    if (server_principal != NULL) {
+-        krb5_free_principal(context, server_principal);
+-    }
+-    talloc_free(tmp_ctx);
+-    return krberr;
+-}
+-
+ krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback(
+                                                    krb5_context context,
+                                                    krb5_get_init_creds_opt *opt,
+diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
+index b1074f813a6b12d132b8c3d0290ad914b003e70f..aaf2a64882254ba173fb57c5dab47d246082392c 100644
+--- a/src/util/sss_krb5.h
++++ b/src/util/sss_krb5.h
+@@ -70,10 +70,6 @@ void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
+ 
+ void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name);
+ 
+-krb5_error_code check_for_valid_tgt(krb5_context context,
+-                                    krb5_ccache ccache, const char *realm,
+-                                    const char *client_princ_str, bool *result);
+-
+ int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
+                               krb5_context context, krb5_keytab keytab);
+ 
+-- 
+1.8.3.1
+
diff --git a/0008-krb5-Use-new-function-to-validate-ccaches.patch b/0008-krb5-Use-new-function-to-validate-ccaches.patch
new file mode 100644
index 0000000..9274577
--- /dev/null
+++ b/0008-krb5-Use-new-function-to-validate-ccaches.patch
@@ -0,0 +1,568 @@
+From 84ce563e3f430eec1225a6f8493eb0a6c9a3013a Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 16:35:43 -0400
+Subject: [PATCH 08/14] krb5: Use new function to validate ccaches
+
+This function replaces and combines check_for_valid_tgt() and type specific
+functions that checked for ccache existence by using generic krb5 cache
+function and executing them as the target user (implicitly validate the
+target use rcan properly access the ccache).
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c  |  30 ++-
+ src/providers/krb5/krb5_utils.c | 423 +++++++---------------------------------
+ src/providers/krb5/krb5_utils.h |   6 +-
+ 3 files changed, 88 insertions(+), 371 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index ca00ce7a3aefa6dae3116f57c994d1f5cd1f50ea..1ea179be3af48b16129aeb4c2d850a66244f7d08 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -59,27 +59,25 @@ static errno_t
+ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+                  const char *realm, bool *active, bool *valid)
+ {
+-    struct sss_krb5_cc_be *old_cc_ops;
+     errno_t ret;
+ 
+-    /* ccache file might be of a different type if the user changed
+-     * configuration
+-     */
+-    old_cc_ops = get_cc_be_ops_ccache(old_ccache);
+-    if (old_cc_ops == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("Cannot get operations on saved ccache %s\n", old_ccache));
+-        return EINVAL;
+-    }
++    *active = false;
++    *valid = false;
+ 
+-    ret = old_cc_ops->check_existing(old_ccache, kr->uid, realm, kr->upn,
+-                                     valid);
+-    if (ret == ENOENT) {
++    ret = sss_krb5_cc_verify_ccache(old_ccache,
++                                    kr->uid, kr->gid,
++                                    realm, kr->upn);
++    switch (ret) {
++    case ERR_NOT_FOUND:
+         DEBUG(SSSDBG_TRACE_FUNC,
+               ("Saved ccache %s doesn't exist.\n", old_ccache));
+-        return ret;
+-    }
+-    if (ret != EOK) {
++        return ENOENT;
++    case EINVAL:
++        /* cache found but no tgt or expired */
++    case EOK:
++        *valid = true;
++        break;
++    default:
+         DEBUG(SSSDBG_OP_FAILURE,
+               ("Cannot check if saved ccache %s is valid\n",
+                old_ccache));
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index 463a5eb409d076825f25d45c034d58f4a89780eb..c4849e74bd43b096b585398970f5b81e946212e9 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -761,136 +761,6 @@ done:
+     return ret;
+ }
+ 
+-static krb5_error_code check_for_valid_tgt(krb5_context context,
+-                                           krb5_ccache ccache,
+-                                           const char *realm,
+-                                           const char *client_princ_str,
+-                                           bool *result)
+-{
+-    krb5_error_code krberr;
+-    TALLOC_CTX *tmp_ctx = NULL;
+-    krb5_creds mcred;
+-    krb5_creds cred;
+-    char *server_name = NULL;
+-    krb5_principal client_principal = NULL;
+-    krb5_principal server_principal = NULL;
+-
+-    *result = false;
+-
+-    tmp_ctx = talloc_new(NULL);
+-    if (tmp_ctx == NULL) {
+-        DEBUG(1, ("talloc_new failed.\n"));
+-        return ENOMEM;
+-    }
+-
+-    server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
+-    if (server_name == NULL) {
+-        DEBUG(1, ("talloc_asprintf failed.\n"));
+-        krberr = ENOMEM;
+-        goto done;
+-    }
+-
+-    krberr = krb5_parse_name(context, server_name, &server_principal);
+-    if (krberr != 0) {
+-        DEBUG(1, ("krb5_parse_name failed.\n"));
+-        goto done;
+-    }
+-
+-    krberr = krb5_parse_name(context, client_princ_str, &client_principal);
+-    if (krberr != 0) {
+-        DEBUG(1, ("krb5_parse_name failed.\n"));
+-        goto done;
+-    }
+-
+-    memset(&mcred, 0, sizeof(mcred));
+-    memset(&cred, 0, sizeof(mcred));
+-    mcred.client = client_principal;
+-    mcred.server = server_principal;
+-
+-    krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
+-    if (krberr != 0) {
+-        DEBUG(1, ("krb5_cc_retrieve_cred failed.\n"));
+-        krberr = 0;
+-        goto done;
+-    }
+-
+-    DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime));
+-
+-    if (cred.times.endtime > time(NULL)) {
+-        DEBUG(3, ("TGT is valid.\n"));
+-        *result = true;
+-    }
+-    krb5_free_cred_contents(context, &cred);
+-
+-    krberr = 0;
+-
+-done:
+-    if (client_principal != NULL) {
+-        krb5_free_principal(context, client_principal);
+-    }
+-    if (server_principal != NULL) {
+-        krb5_free_principal(context, server_principal);
+-    }
+-    talloc_free(tmp_ctx);
+-    return krberr;
+-}
+-
+-static errno_t
+-check_cc_validity(const char *location,
+-                  const char *realm,
+-                  const char *princ,
+-                  bool *_valid)
+-{
+-    errno_t ret;
+-    bool valid = false;
+-    krb5_ccache ccache = NULL;
+-    krb5_context context = NULL;
+-    krb5_error_code krberr;
+-
+-    krberr = krb5_init_context(&context);
+-    if (krberr) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to init kerberos context\n"));
+-        return EIO;
+-    }
+-
+-    krberr = krb5_cc_resolve(context, location, &ccache);
+-    if (krberr == KRB5_FCC_NOFILE || ccache == NULL) {
+-        /* KRB5_FCC_NOFILE would be returned if the directory components
+-         * of the DIR cache do not exist, which is the case in /run
+-         * after a reboot
+-         */
+-        DEBUG(SSSDBG_TRACE_FUNC,
+-              ("ccache %s is missing or empty\n", location));
+-        valid = false;
+-        ret = EOK;
+-        goto done;
+-    } else if (krberr != 0) {
+-        KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("krb5_cc_resolve failed.\n"));
+-        ret = EIO;
+-        goto done;
+-    }
+-
+-    krberr = check_for_valid_tgt(context, ccache, realm, princ, &valid);
+-    if (krberr != EOK) {
+-        KRB5_DEBUG(SSSDBG_OP_FAILURE, context, krberr);
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("Could not check if ccache contains a valid principal\n"));
+-        ret = EIO;
+-        goto done;
+-    }
+-
+-    ret = EOK;
+-
+-done:
+-    if (ret == EOK) {
+-        *_valid = valid;
+-    }
+-    if (ccache) krb5_cc_close(context, ccache);
+-    krb5_free_context(context);
+-    return ret;
+-}
+-
+ 
+ struct sss_krb5_ccache {
+     struct sss_creds *creds;
+@@ -1085,6 +955,78 @@ done:
+     return ret;
+ }
+ 
++errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
++                                  const char *realm, const char *principal)
++{
++    struct sss_krb5_ccache *cc = NULL;
++    TALLOC_CTX *tmp_ctx = NULL;
++    krb5_principal tgt_princ = NULL;
++    krb5_principal princ = NULL;
++    char *tgt_name;
++    krb5_creds mcred = { 0 };
++    krb5_creds cred = { 0 };
++    krb5_error_code kerr;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
++        return ENOMEM;
++    }
++
++    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
++    if (ret) {
++        goto done;
++    }
++
++    tgt_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
++    if (!tgt_name) {
++        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
++        ret = ENOMEM;
++        goto done;
++    }
++
++    kerr = krb5_parse_name(cc->context, tgt_name, &tgt_princ);
++    if (kerr) {
++        KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
++        if (kerr == KRB5_PARSE_MALFORMED) ret = EINVAL;
++        else ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    kerr = krb5_parse_name(cc->context, principal, &princ);
++    if (kerr) {
++        KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
++        if (kerr == KRB5_PARSE_MALFORMED) ret = EINVAL;
++        else ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    mcred.client = princ;
++    mcred.server = tgt_princ;
++    mcred.times.endtime = time(NULL);
++
++    kerr = krb5_cc_retrieve_cred(cc->context, cc->ccache,
++                                 KRB5_TC_MATCH_TIMES, &mcred, &cred);
++    if (kerr) {
++        if (kerr == KRB5_CC_NOTFOUND) {
++            DEBUG(SSSDBG_TRACE_INTERNAL, ("TGT not found or expired.\n"));
++            ret = EINVAL;
++        } else {
++            KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
++            ret = ERR_INTERNAL;
++        }
++    }
++    krb5_free_cred_contents(cc->context, &cred);
++
++done:
++    if (tgt_princ) krb5_free_principal(cc->context, tgt_princ);
++    if (princ) krb5_free_principal(cc->context, princ);
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
++
+ /*======== ccache back end utilities ========*/
+ struct sss_krb5_cc_be *
+ get_cc_be_ops(enum sss_krb5_cc_type type)
+@@ -1139,105 +1081,9 @@ cc_file_create(const char *location, pcre *illegal_re,
+     return create_ccache_dir_head(filename, illegal_re, uid, gid, private_path);
+ }
+ 
+-static errno_t
+-cc_residual_exists(uid_t uid, const char *ccname,
+-                   enum sss_krb5_cc_type type)
+-{
+-    int ret;
+-    struct stat stat_buf;
+-
+-    if (ccname == NULL || *ccname == '\0') {
+-        return EINVAL;
+-    }
+-
+-    ret = lstat(ccname, &stat_buf);
+-
+-    if (ret == -1) {
+-        ret = errno;
+-        if (ret == ENOENT) {
+-            DEBUG(SSSDBG_FUNC_DATA, ("Cache file [%s] does not exist, "
+-                                     "it will be recreated\n", ccname));
+-            return ENOENT;
+-        }
+-
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              ("stat failed [%d][%s].\n", ret, strerror(ret)));
+-        return ret;
+-    }
+-
+-    if (stat_buf.st_uid != uid) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              ("Cache file [%s] exists, but is owned by [%d] instead of "
+-               "[%d].\n", ccname, stat_buf.st_uid, uid));
+-        return EINVAL;
+-    }
+-
+-    switch (type) {
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-        case SSS_KRB5_TYPE_DIR:
+-            ret = S_ISDIR(stat_buf.st_mode);
+-            break;
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-        case SSS_KRB5_TYPE_FILE:
+-            ret = S_ISREG(stat_buf.st_mode);
+-            break;
+-        default:
+-            DEBUG(SSSDBG_CRIT_FAILURE, ("Unsupported ccache type\n"));
+-            return EINVAL;
+-    }
+-
+-    if (ret == 0) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              ("Cache file [%s] exists, but is not the expected type\n",
+-              ccname));
+-        return EINVAL;
+-    }
+-
+-    return EOK;
+-}
+-
+-errno_t
+-cc_file_check_existing(const char *location, uid_t uid,
+-                       const char *realm, const char *princ,
+-                       bool *_valid)
+-{
+-    errno_t ret;
+-    bool valid;
+-    const char *filename;
+-
+-    filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
+-    if (!filename) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type FILE:\n", location));
+-        return EINVAL;
+-    }
+-
+-    if (filename[0] != '/') {
+-        DEBUG(SSSDBG_OP_FAILURE, ("Only absolute path names are allowed.\n"));
+-        return EINVAL;
+-    }
+-
+-    ret = cc_residual_exists(uid, filename, SSS_KRB5_TYPE_FILE);
+-    if (ret != EOK) {
+-        if (ret != ENOENT) {
+-            DEBUG(SSSDBG_OP_FAILURE,
+-                  ("Could not check if ccache is active.\n"));
+-        }
+-        return ret;
+-    }
+-
+-    ret = check_cc_validity(location, realm, princ, &valid);
+-    if (ret != EOK) {
+-        return ret;
+-    }
+-
+-    *_valid = valid;
+-    return EOK;
+-}
+-
+ struct sss_krb5_cc_be file_cc = {
+     .type               = SSS_KRB5_TYPE_FILE,
+     .create             = cc_file_create,
+-    .check_existing     = cc_file_check_existing,
+ };
+ 
+ #ifdef HAVE_KRB5_CC_COLLECTION
+@@ -1257,107 +1103,9 @@ cc_dir_create(const char *location, pcre *illegal_re,
+     return create_ccache_dir_head(dir_name, illegal_re, uid, gid, private_path);
+ }
+ 
+-errno_t
+-cc_dir_check_existing(const char *location, uid_t uid,
+-                      const char *realm, const char *princ,
+-                      bool *_valid)
+-{
+-    bool valid;
+-    enum sss_krb5_cc_type type;
+-    const char *filename;
+-    const char *dir;
+-    char *tmp;
+-    char *primary_file;
+-    errno_t ret;
+-    TALLOC_CTX *tmp_ctx;
+-
+-    type = sss_krb5_get_type(location);
+-    if (type != SSS_KRB5_TYPE_DIR) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("%s is not of type DIR:\n", location));
+-        return EINVAL;
+-    }
+-
+-    filename = sss_krb5_cc_file_path(location);
+-    if (!filename) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("Existing ccname does not contain path into the collection"));
+-        return EINVAL;
+-    }
+-
+-    if (filename[0] != '/') {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("Only absolute path names are allowed.\n"));
+-        return EINVAL;
+-    }
+-
+-    tmp_ctx = talloc_new(NULL);
+-    if (tmp_ctx == NULL) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+-        return ENOMEM;
+-    }
+-
+-    tmp = talloc_strdup(tmp_ctx, filename);
+-    if (!tmp) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
+-        ret = ENOMEM;
+-        goto done;
+-    }
+-
+-    if (0 == strncmp(location, "DIR::", 5)) {
+-        dir = dirname(tmp);
+-        if (!dir) {
+-            DEBUG(SSSDBG_CRIT_FAILURE,
+-                  ("Cannot get base directory of %s.\n", tmp));
+-            ret = EINVAL;
+-            goto done;
+-        }
+-    } else {
+-        dir = tmp;
+-    }
+-
+-    ret = cc_residual_exists(uid, dir, SSS_KRB5_TYPE_DIR);
+-    if (ret != EOK) {
+-        if (ret != ENOENT) {
+-            DEBUG(SSSDBG_OP_FAILURE,
+-                  ("Could not check if ccache is active.\n"));
+-        }
+-        goto done;
+-    }
+-
+-    /* If primary file isn't in ccache dir, we will ignore it.
+-     * But if primary file has wrong permissions, we will fail.
+-     */
+-    primary_file = talloc_asprintf(tmp_ctx, "%s/primary", dir);
+-    if (!primary_file) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf failed.\n"));
+-        ret = ENOMEM;
+-        goto done;
+-    }
+-    ret = cc_residual_exists(uid, primary_file, SSS_KRB5_TYPE_FILE);
+-    if (ret != EOK && ret != ENOENT) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              ("Could not check if file 'primary' [%s] in dir ccache"
+-               " is active.\n", primary_file));
+-        goto done;
+-    }
+-
+-    ret = check_cc_validity(location, realm, princ, &valid);
+-    if (ret != EOK) {
+-        goto done;
+-    }
+-
+-    *_valid = valid;
+-    ret = EOK;
+-
+-done:
+-    talloc_free(tmp_ctx);
+-    return ret;
+-}
+-
+ struct sss_krb5_cc_be dir_cc = {
+     .type               = SSS_KRB5_TYPE_DIR,
+     .create             = cc_dir_create,
+-    .check_existing     = cc_dir_check_existing,
+ };
+ 
+ 
+@@ -1381,36 +1129,9 @@ cc_keyring_create(const char *location, pcre *illegal_re,
+     return EOK;
+ }
+ 
+-errno_t
+-cc_keyring_check_existing(const char *location, uid_t uid,
+-                          const char *realm, const char *princ,
+-                          bool *_valid)
+-{
+-    errno_t ret;
+-    bool valid;
+-    const char *residual;
+-
+-    residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
+-    if (!residual) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("%s is not of type KEYRING:\n", location));
+-        return EINVAL;
+-    }
+-
+-    /* Check if any user is actively using this cache */
+-    ret = check_cc_validity(location, realm, princ, &valid);
+-    if (ret != EOK) {
+-        return ret;
+-    }
+-
+-    *_valid = valid;
+-    return EOK;
+-}
+-
+ struct sss_krb5_cc_be keyring_cc = {
+     .type               = SSS_KRB5_TYPE_KEYRING,
+     .create             = cc_keyring_create,
+-    .check_existing     = cc_keyring_check_existing,
+ };
+ 
+ #endif /* HAVE_KRB5_CC_COLLECTION */
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index e241666289193bdc3c5eccadfffc4d3d669dff16..b364f87aa6e6f0070e8acb5559ee92f2e001e0a5 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -45,16 +45,12 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
+ /* Operations on a credential cache */
+ typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
+                                    uid_t uid, gid_t gid, bool private_path);
+-typedef errno_t (*cc_be_check_existing)(const char *location, uid_t uid,
+-                                        const char *realm, const char *princ,
+-                                        bool *valid);
+ 
+ /* A ccache back end */
+ struct sss_krb5_cc_be {
+     enum sss_krb5_cc_type type;
+ 
+     cc_be_create_fn create;
+-    cc_be_check_existing check_existing;
+ };
+ 
+ extern struct sss_krb5_cc_be file_cc;
+@@ -83,6 +79,8 @@ errno_t restore_creds(struct sss_creds *saved_creds);
+ errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
+ errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
+                                     const char *ccname, const char *principal);
++errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
++                                  const char *realm, const char *principal);
+ 
+ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                              struct tgt_times *tgtt);
+-- 
+1.8.3.1
+
diff --git a/0009-krb5-Unify-function-to-create-ccache-files.patch b/0009-krb5-Unify-function-to-create-ccache-files.patch
new file mode 100644
index 0000000..00797d2
--- /dev/null
+++ b/0009-krb5-Unify-function-to-create-ccache-files.patch
@@ -0,0 +1,348 @@
+From 1c022b3556f442f57326c4a3f250128b1bd232ae Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 17:25:01 -0400
+Subject: [PATCH 09/14] krb5: Unify function to create ccache files
+
+Only 2 types (FILE and DIR) need to precreate files or directories
+on the file system, and the 2 functions were basically identical.
+
+Consolidate all in one common function and use that function directly
+where needed instead of using indirection.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c  |  6 ++--
+ src/providers/krb5/krb5_utils.c | 71 ++++++++++-------------------------------
+ src/providers/krb5/krb5_utils.h | 14 ++------
+ src/tests/krb5_child-test.c     |  6 ++--
+ src/tests/krb5_utils-tests.c    | 40 +++++++++++------------
+ 5 files changed, 43 insertions(+), 94 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index 1ea179be3af48b16129aeb4c2d850a66244f7d08..d2c53f98c04cda01c2a8e0efe038f5cd5fa82839 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -333,9 +333,9 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
+                 return EINVAL;
+             }
+ 
+-            ret = kr->cc_be->create(kr->ccname,
+-                                    kr->krb5_ctx->illegal_path_re,
+-                                    kr->uid, kr->gid, private_path);
++            ret = sss_krb5_precreate_ccache(kr->ccname,
++                                            kr->krb5_ctx->illegal_path_re,
++                                            kr->uid, kr->gid, private_path);
+             if (ret != EOK) {
+                 DEBUG(SSSDBG_OP_FAILURE, ("ccache creation failed.\n"));
+                 return ret;
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index c4849e74bd43b096b585398970f5b81e946212e9..83e61e14ecc116b9556231c5d8a0f55b63260c77 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -722,19 +722,31 @@ done:
+     return EOK;
+ }
+ 
+-static errno_t
+-create_ccache_dir_head(const char *parent, pcre *illegal_re,
+-                       uid_t uid, gid_t gid, bool private_path)
++errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
++                                  uid_t uid, gid_t gid, bool private_path)
+ {
++    TALLOC_CTX *tmp_ctx = NULL;
++    const char *filename;
+     char *ccdirname;
+-    TALLOC_CTX *tmp_ctx = NULL;
+     char *end;
+     errno_t ret;
+ 
++    if (ccname[0] == '/') {
++        filename = ccname;
++    } else if (strncmp(ccname, "FILE:", 5) == 0) {
++        filename = ccname + 5;
++    } else if (strncmp(ccname, "DIR:", 4) == 0) {
++        filename = ccname + 4;
++    } else {
++        /* only FILE and DIR types need precreation so far, we ignore any
++         * other type */
++        return EOK;
++    }
++
+     tmp_ctx = talloc_new(NULL);
+     if (!tmp_ctx) return ENOMEM;
+ 
+-    ccdirname = talloc_strdup(tmp_ctx, parent);
++    ccdirname = talloc_strdup(tmp_ctx, filename);
+     if (ccdirname == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup failed.\n"));
+         ret = ENOMEM;
+@@ -1066,72 +1078,23 @@ get_cc_be_ops_ccache(const char *ccache)
+ }
+ 
+ /*======== Operations on the FILE: back end ========*/
+-errno_t
+-cc_file_create(const char *location, pcre *illegal_re,
+-               uid_t uid, gid_t gid, bool private_path)
+-{
+-    const char *filename;
+-
+-    filename = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_FILE);
+-    if (filename == NULL) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("Bad ccache type %s\n", location));
+-        return EINVAL;
+-    }
+-
+-    return create_ccache_dir_head(filename, illegal_re, uid, gid, private_path);
+-}
+ 
+ struct sss_krb5_cc_be file_cc = {
+     .type               = SSS_KRB5_TYPE_FILE,
+-    .create             = cc_file_create,
+ };
+ 
+ #ifdef HAVE_KRB5_CC_COLLECTION
+ /*======== Operations on the DIR: back end ========*/
+-errno_t
+-cc_dir_create(const char *location, pcre *illegal_re,
+-              uid_t uid, gid_t gid, bool private_path)
+-{
+-    const char *dir_name;
+-
+-    dir_name = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_DIR);
+-    if (dir_name == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, ("Bad residual type\n"));
+-        return EINVAL;
+-    }
+-
+-    return create_ccache_dir_head(dir_name, illegal_re, uid, gid, private_path);
+-}
+ 
+ struct sss_krb5_cc_be dir_cc = {
+     .type               = SSS_KRB5_TYPE_DIR,
+-    .create             = cc_dir_create,
+ };
+ 
+ 
+ /*======== Operations on the KEYRING: back end ========*/
+ 
+-errno_t
+-cc_keyring_create(const char *location, pcre *illegal_re,
+-                  uid_t uid, gid_t gid, bool private_path)
+-{
+-    const char *residual;
+-
+-    residual = sss_krb5_residual_check_type(location, SSS_KRB5_TYPE_KEYRING);
+-    if (residual == NULL) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("Bad ccache type %s\n", location));
+-        return EINVAL;
+-    }
+-
+-    /* No special steps are needed to create a kernel keyring.
+-     * Everything is handled in libkrb5.
+-     */
+-    return EOK;
+-}
+-
+ struct sss_krb5_cc_be keyring_cc = {
+     .type               = SSS_KRB5_TYPE_KEYRING,
+-    .create             = cc_keyring_create,
+ };
+ 
+ #endif /* HAVE_KRB5_CC_COLLECTION */
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index b364f87aa6e6f0070e8acb5559ee92f2e001e0a5..5f720335aab1ac6e493843ac197c5af881a9b998 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -42,15 +42,9 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
+                                          const char *user,
+                                          const char *upn);
+ 
+-/* Operations on a credential cache */
+-typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re,
+-                                   uid_t uid, gid_t gid, bool private_path);
+-
+ /* A ccache back end */
+ struct sss_krb5_cc_be {
+     enum sss_krb5_cc_type type;
+-
+-    cc_be_create_fn create;
+ };
+ 
+ extern struct sss_krb5_cc_be file_cc;
+@@ -58,9 +52,6 @@ extern struct sss_krb5_cc_be file_cc;
+ errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
+                           uid_t uid, gid_t gid, bool private_path);
+ 
+-errno_t cc_file_create(const char *filename, pcre *illegal_re,
+-                       uid_t uid, gid_t gid, bool private_path);
+-
+ struct sss_krb5_cc_be *get_cc_be_ops(enum sss_krb5_cc_type type);
+ struct sss_krb5_cc_be *get_cc_be_ops_ccache(const char *ccache);
+ 
+@@ -76,6 +67,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
+                      struct sss_creds **saved_creds);
+ errno_t restore_creds(struct sss_creds *saved_creds);
+ 
++errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
++                                  uid_t uid, gid_t gid, bool private_path);
+ errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
+ errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
+                                     const char *ccname, const char *principal);
+@@ -90,9 +83,6 @@ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+ extern struct sss_krb5_cc_be dir_cc;
+ extern struct sss_krb5_cc_be keyring_cc;
+ 
+-errno_t cc_dir_create(const char *location, pcre *illegal_re,
+-                      uid_t uid, gid_t gid, bool private_path);
+-
+ #endif /* HAVE_KRB5_CC_COLLECTION */
+ 
+ 
+diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
+index dff62ab64dd1948d20da6b640a0570ee8ea6b11d..5ea30014f9c8f748e85506627b7f40d72b913b1b 100644
+--- a/src/tests/krb5_child-test.c
++++ b/src/tests/krb5_child-test.c
+@@ -287,9 +287,9 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
+     DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
+             kr->ccname, kr->uid, kr->gid));
+ 
+-    ret = kr->krb5_ctx->cc_be->create(kr->ccname,
+-                                      kr->krb5_ctx->illegal_path_re,
+-                                      kr->uid, kr->gid, private);
++    ret = sss_krb5_precreate_ccache(kr->ccname,
++                                    kr->krb5_ctx->illegal_path_re,
++                                    kr->uid, kr->gid, private);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, ("create_ccache_dir failed.\n"));
+         goto fail;
+diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
+index 4715774ff189700bc1cbeb6c90f4438445a594b0..ea0292569135e0fc22a44251cfc4e8719a15837f 100644
+--- a/src/tests/krb5_utils-tests.c
++++ b/src/tests/krb5_utils-tests.c
+@@ -117,14 +117,14 @@ START_TEST(test_pub_ccache_dir)
+ 
+     ret = chmod(testpath, 0754);
+     fail_unless(ret == EOK, "chmod failed.");
+-    ret = cc_file_create(filename, NULL, 12345, 12345, false);
+-    fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
++    ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, false);
++    fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
+                                "while x-bit is missing.");
+ 
+     ret = chmod(testpath, 0755);
+     fail_unless(ret == EOK, "chmod failed.");
+-    ret = cc_file_create(filename, NULL, 12345, 12345, false);
+-    fail_unless(ret == EOK, "cc_file_create failed.");
++    ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, false);
++    fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
+ 
+     check_dir(subdirname, 0, 0, 01777);
+     RMDIR(subdirname);
+@@ -158,7 +158,7 @@ START_TEST(test_pub_ccache_dir_in_user_dir)
+     filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
+     fail_unless(filename != NULL, "talloc_asprintf failed.");
+ 
+-    ret = cc_file_create(filename, NULL, 12345, 12345, false);
++    ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, false);
+     fail_unless(ret == EINVAL, "Creating public ccache dir in user dir "
+                                "does not failed with EINVAL.");
+ 
+@@ -193,14 +193,14 @@ START_TEST(test_priv_ccache_dir)
+ 
+     ret = chmod(testpath, 0754);
+     fail_unless(ret == EOK, "chmod failed.");
+-    ret = cc_file_create(filename, NULL, uid, gid, true);
+-    fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
++    ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
++    fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
+                                "while x-bit is missing.");
+ 
+     ret = chmod(testpath, 0755);
+     fail_unless(ret == EOK, "chmod failed.");
+-    ret = cc_file_create(filename, NULL, uid, gid, true);
+-    fail_unless(ret == EOK, "cc_file_create failed.");
++    ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
++    fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
+ 
+     check_dir(subdir, uid, gid, 0700);
+     RMDIR(subdir);
+@@ -248,14 +248,14 @@ START_TEST(test_private_ccache_dir_in_user_dir)
+ 
+     ret = chmod(user_dir, 0600);
+     fail_unless(ret == EOK, "chmod failed.");
+-    ret = cc_file_create(filename, NULL, uid, gid, true);
+-    fail_unless(ret == EINVAL, "cc_file_create does not return EINVAL "
++    ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
++    fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
+                                "while x-bit is missing.");
+ 
+     ret = chmod(user_dir, 0700);
+     fail_unless(ret == EOK, "chmod failed.");
+-    ret = cc_file_create(filename, NULL, uid, gid, true);
+-    fail_unless(ret == EOK, "cc_file_create failed.");
++    ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid, true);
++    fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
+ 
+     check_dir(dn3, uid, gid, 0700);
+     RMDIR(dn3);
+@@ -292,7 +292,7 @@ START_TEST(test_private_ccache_dir_in_wrong_user_dir)
+     filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
+     fail_unless(filename != NULL, "talloc_asprintf failed.");
+ 
+-    ret = cc_file_create(filename, NULL, 12345, 12345, true);
++    ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345, true);
+     fail_unless(ret == EINVAL, "Creating private ccache dir in wrong user "
+                                "dir does not failed with EINVAL.");
+ 
+@@ -357,7 +357,6 @@ START_TEST(test_illegal_patterns)
+ }
+ END_TEST
+ 
+-#ifdef HAVE_KRB5_CC_COLLECTION
+ START_TEST(test_cc_dir_create)
+ {
+     char *residual;
+@@ -386,8 +385,8 @@ START_TEST(test_cc_dir_create)
+     residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir");
+     fail_unless(residual != NULL, "talloc_asprintf failed.");
+ 
+-    ret = cc_dir_create(residual, illegal_re, uid, gid, true);
+-    fail_unless(ret == EOK, "cc_dir_create failed\n");
++    ret = sss_krb5_precreate_ccache(residual, illegal_re, uid, gid, true);
++    fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
+     ret = rmdir(dirname);
+     if (ret < 0) ret = errno;
+     fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
+@@ -399,8 +398,8 @@ START_TEST(test_cc_dir_create)
+     residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir/");
+     fail_unless(residual != NULL, "talloc_asprintf failed.");
+ 
+-    ret = cc_dir_create(residual, illegal_re, uid, gid, true);
+-    fail_unless(ret == EOK, "cc_dir_create failed\n");
++    ret = sss_krb5_precreate_ccache(residual, illegal_re, uid, gid, true);
++    fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
+     ret = rmdir(dirname);
+     if (ret < 0) ret = errno;
+     fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
+@@ -408,7 +407,6 @@ START_TEST(test_cc_dir_create)
+     free(cwd);
+ }
+ END_TEST
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+ 
+ 
+ void setup_talloc_context(void)
+@@ -774,9 +772,7 @@ Suite *krb5_utils_suite (void)
+     tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
+                                teardown_create_dir);
+     tcase_add_test (tc_create_dir, test_illegal_patterns);
+-#ifdef HAVE_KRB5_CC_COLLECTION
+     tcase_add_test (tc_create_dir, test_cc_dir_create);
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+     if (getuid() == 0) {
+         tcase_add_test (tc_create_dir, test_priv_ccache_dir);
+         tcase_add_test (tc_create_dir, test_private_ccache_dir_in_user_dir);
+-- 
+1.8.3.1
+
diff --git a/0010-krb5-Remove-unused-ccache-backend-infrastructure.patch b/0010-krb5-Remove-unused-ccache-backend-infrastructure.patch
new file mode 100644
index 0000000..93ccba0
--- /dev/null
+++ b/0010-krb5-Remove-unused-ccache-backend-infrastructure.patch
@@ -0,0 +1,337 @@
+From d20a5a74666413cadbf64c02eb656a5a3b4bb1de Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 20:11:42 -0400
+Subject: [PATCH 10/14] krb5: Remove unused ccache backend infrastructure
+
+Remove struct sss_krb5_cc_be and the remaining functions that reference
+it as they are all unused now.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c   | 26 -----------------
+ src/providers/krb5/krb5_auth.h   |  1 -
+ src/providers/krb5/krb5_common.c | 54 ++++++++++--------------------------
+ src/providers/krb5/krb5_common.h |  2 --
+ src/providers/krb5/krb5_utils.c  | 60 ----------------------------------------
+ src/providers/krb5/krb5_utils.h  | 17 ------------
+ src/tests/krb5_child-test.c      | 23 ---------------
+ 7 files changed, 15 insertions(+), 168 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index d2c53f98c04cda01c2a8e0efe038f5cd5fa82839..1585f709655853827f2778010452a58657add5d0 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -324,15 +324,6 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
+                 return ENOMEM;
+             }
+ 
+-            if (kr->cc_be == NULL) {
+-                kr->cc_be = get_cc_be_ops_ccache(kr->ccname);
+-            }
+-            if (kr->cc_be == NULL) {
+-                DEBUG(SSSDBG_CRIT_FAILURE,
+-                      ("Cannot get operations on new ccache %s\n", kr->ccname));
+-                return EINVAL;
+-            }
+-
+             ret = sss_krb5_precreate_ccache(kr->ccname,
+                                             kr->krb5_ctx->illegal_path_re,
+                                             kr->uid, kr->gid, private_path);
+@@ -340,19 +331,6 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
+                 DEBUG(SSSDBG_OP_FAILURE, ("ccache creation failed.\n"));
+                 return ret;
+             }
+-    } else {
+-        DEBUG(SSSDBG_MINOR_FAILURE,
+-              ("Saved ccache %s if of different type than ccache in "
+-               "configuration file, reusing the old ccache\n",
+-               kr->old_ccname));
+-
+-        kr->cc_be = get_cc_be_ops_ccache(kr->old_ccname);
+-        if (kr->cc_be == NULL) {
+-            DEBUG(SSSDBG_CRIT_FAILURE,
+-                  ("Cannot get operations on saved ccache %s\n",
+-                   kr->old_ccname));
+-            return EINVAL;
+-        }
+     }
+ 
+     return EOK;
+@@ -614,10 +592,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
+             goto done;
+         }
+ 
+-        /* The type of the ccache might change during the request if we
+-         * end up reusing an old ccache */
+-        kr->cc_be = krb5_ctx->cc_be;
+-
+         ccache_file = ldb_msg_find_attr_as_string(res->msgs[0],
+                                                   SYSDB_CCACHE_FILE,
+                                                   NULL);
+diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
+index d31925dae6187b3c839e32502fd349e4d64deb32..022dc9b7645f18d01a8a334371e178aa470d92a1 100644
+--- a/src/providers/krb5/krb5_auth.h
++++ b/src/providers/krb5/krb5_auth.h
+@@ -41,7 +41,6 @@ struct krb5child_req {
+     struct pam_data *pd;
+     struct krb5_ctx *krb5_ctx;
+ 
+-    struct sss_krb5_cc_be *cc_be;
+     const char *ccname;
+     const char *old_ccname;
+     const char *homedir;
+diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
+index de7ae0a8fe345c38f9458fb9642a5c1b83c906f5..dedb734fc397d3df3eb7717b19c56051fb2243bb 100644
+--- a/src/providers/krb5/krb5_common.c
++++ b/src/providers/krb5/krb5_common.c
+@@ -167,7 +167,6 @@ errno_t check_and_export_options(struct dp_option *opts,
+     const char *dummy;
+     char *use_fast_str;
+     char *fast_principal;
+-    enum sss_krb5_cc_type cc_be;
+     char *ccname;
+ 
+     tmp_ctx = talloc_new(NULL);
+@@ -291,53 +290,30 @@ errno_t check_and_export_options(struct dp_option *opts,
+         }
+     }
+ 
+-    cc_be = sss_krb5_get_type(ccname);
+-    switch (cc_be) {
+-    case SSS_KRB5_TYPE_FILE:
++    if ((ccname[0] == '/') || (strncmp(ccname, "FILE:", 5) == 0)) {
+         DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type FILE\n"));
+         /* warn if the file type (which is usally created in a sticky bit
+          * laden directory) does not have randomizing chracters */
+         sss_check_cc_template(ccname);
+ 
+-        krb5_ctx->cc_be = &file_cc;
+-        if (ccname[0] != '/') {
+-            /* FILE:/path/to/cc */
+-            break;
+-        }
+-
+-        DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
++        if (ccname[0] == '/') {
++            /* /path/to/cc  prepend FILE: */
++            DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
+               "missing an explicit type, but is an absolute "
+               "path specifier. Assuming FILE:\n"));
+ 
+-        ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname);
+-        if (!ccname) {
+-            ret = ENOMEM;
+-            goto done;
++            ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname);
++            if (!ccname) {
++                ret = ENOMEM;
++                goto done;
++            }
++
++            ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, ccname);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
++                goto done;
++            }
+         }
+-
+-        ret = dp_opt_set_string(opts, KRB5_CCNAME_TMPL, ccname);
+-        if (ret != EOK) {
+-            DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
+-            goto done;
+-        }
+-        break;
+-
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-    case SSS_KRB5_TYPE_DIR:
+-        DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type DIR\n"));
+-        krb5_ctx->cc_be = &dir_cc;
+-        break;
+-
+-    case SSS_KRB5_TYPE_KEYRING:
+-        DEBUG(SSSDBG_CONF_SETTINGS, ("ccache is of type KEYRING\n"));
+-        krb5_ctx->cc_be = &keyring_cc;
+-        break;
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-    default:
+-        DEBUG(SSSDBG_OP_FAILURE, ("Unknown ccname database\n"));
+-        ret = EINVAL;
+-        goto done;
+     }
+ 
+     ret = EOK;
+diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
+index e56bd496e04a7a5c8776a34648aabe0f2d73a3b9..eac0d6b1f0c0fec4a107a7b830d8b0c927f4fe42 100644
+--- a/src/providers/krb5/krb5_common.h
++++ b/src/providers/krb5/krb5_common.h
+@@ -89,7 +89,6 @@ struct krb5_service {
+ struct fo_service;
+ struct deferred_auth_ctx;
+ struct renew_tgt_ctx;
+-struct sss_krb5_cc_be;
+ 
+ enum krb5_config_type {
+     K5C_GENERIC,
+@@ -127,7 +126,6 @@ struct krb5_ctx {
+     struct krb5_service *kpasswd_service;
+     int child_debug_fd;
+ 
+-    struct sss_krb5_cc_be *cc_be;
+     pcre *illegal_path_re;
+ 
+     struct deferred_auth_ctx *deferred_auth_ctx;
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index 83e61e14ecc116b9556231c5d8a0f55b63260c77..d0ccd2d7e03bcabe07113b5abb43d9119b35321c 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -1039,66 +1039,6 @@ done:
+ }
+ 
+ 
+-/*======== ccache back end utilities ========*/
+-struct sss_krb5_cc_be *
+-get_cc_be_ops(enum sss_krb5_cc_type type)
+-{
+-    struct sss_krb5_cc_be *be = NULL;
+-
+-    switch (type) {
+-        case SSS_KRB5_TYPE_FILE:
+-            be = &file_cc;
+-            break;
+-
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-        case SSS_KRB5_TYPE_DIR:
+-            be = &dir_cc;
+-            break;
+-
+-        case SSS_KRB5_TYPE_KEYRING:
+-            be = &keyring_cc;
+-            break;
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-        case SSS_KRB5_TYPE_UNKNOWN:
+-            be = NULL;
+-            break;
+-    }
+-
+-    return be;
+-}
+-
+-struct sss_krb5_cc_be *
+-get_cc_be_ops_ccache(const char *ccache)
+-{
+-    enum sss_krb5_cc_type type;
+-
+-    type = sss_krb5_get_type(ccache);
+-    return get_cc_be_ops(type);
+-}
+-
+-/*======== Operations on the FILE: back end ========*/
+-
+-struct sss_krb5_cc_be file_cc = {
+-    .type               = SSS_KRB5_TYPE_FILE,
+-};
+-
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-/*======== Operations on the DIR: back end ========*/
+-
+-struct sss_krb5_cc_be dir_cc = {
+-    .type               = SSS_KRB5_TYPE_DIR,
+-};
+-
+-
+-/*======== Operations on the KEYRING: back end ========*/
+-
+-struct sss_krb5_cc_be keyring_cc = {
+-    .type               = SSS_KRB5_TYPE_KEYRING,
+-};
+-
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+ errno_t get_domain_or_subdomain(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx,
+                                 char *domain_name,
+                                 struct sss_domain_info **dom)
+diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
+index 5f720335aab1ac6e493843ac197c5af881a9b998..e41309e765b58f7cd2567f1d13fea30d093fd344 100644
+--- a/src/providers/krb5/krb5_utils.h
++++ b/src/providers/krb5/krb5_utils.h
+@@ -42,19 +42,9 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
+                                          const char *user,
+                                          const char *upn);
+ 
+-/* A ccache back end */
+-struct sss_krb5_cc_be {
+-    enum sss_krb5_cc_type type;
+-};
+-
+-extern struct sss_krb5_cc_be file_cc;
+-
+ errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
+                           uid_t uid, gid_t gid, bool private_path);
+ 
+-struct sss_krb5_cc_be *get_cc_be_ops(enum sss_krb5_cc_type type);
+-struct sss_krb5_cc_be *get_cc_be_ops_ccache(const char *ccache);
+-
+ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
+                              const char *template, bool file_mode,
+                              bool case_sensitive, bool *private_path);
+@@ -78,13 +68,6 @@ errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
+ errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
+                              struct tgt_times *tgtt);
+ 
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-
+-extern struct sss_krb5_cc_be dir_cc;
+-extern struct sss_krb5_cc_be keyring_cc;
+-
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+ 
+ errno_t get_domain_or_subdomain(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx,
+                                 char *domain_name,
+diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
+index 5ea30014f9c8f748e85506627b7f40d72b913b1b..c32ccc318e9826d598bb29a766ed1839fd9bf066 100644
+--- a/src/tests/krb5_child-test.c
++++ b/src/tests/krb5_child-test.c
+@@ -196,7 +196,6 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
+                  const char *ccname, const char *ccname_template,
+                  int timeout)
+ {
+-    enum sss_krb5_cc_type cc_be;
+     struct krb5child_req *kr;
+     struct passwd *pwd;
+     bool private = false;
+@@ -262,28 +261,6 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
+     }
+     if (!kr->ccname) goto fail;
+ 
+-    cc_be = sss_krb5_get_type(kr->ccname);
+-    switch (cc_be) {
+-    case SSS_KRB5_TYPE_FILE:
+-        kr->krb5_ctx->cc_be = &file_cc;
+-        break;
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-    case SSS_KRB5_TYPE_DIR:
+-        kr->krb5_ctx->cc_be = &dir_cc;
+-        break;
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-    default:
+-        if (tmpl[0] != '/') {
+-            DEBUG(SSSDBG_OP_FAILURE, ("Unkown ccname database\n"));
+-            ret = EINVAL;
+-            goto fail;
+-        }
+-        DEBUG(SSSDBG_CONF_SETTINGS, ("The ccname template was "
+-              "missing an explicit type, but looks like an absolute "
+-              "path specifier. Assuming FILE:\n"));
+-        kr->krb5_ctx->cc_be = &file_cc;
+-        break;
+-    }
+     DEBUG(SSSDBG_FUNC_DATA, ("ccname [%s] uid [%llu] gid [%llu]\n",
+             kr->ccname, kr->uid, kr->gid));
+ 
+-- 
+1.8.3.1
+
diff --git a/0011-krb5-Remove-unused-function.patch b/0011-krb5-Remove-unused-function.patch
new file mode 100644
index 0000000..d5019ea
--- /dev/null
+++ b/0011-krb5-Remove-unused-function.patch
@@ -0,0 +1,69 @@
+From 0dbcc64a5cee58d5fffaaef923302d9c7a951a7d Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Fri, 30 Aug 2013 20:55:38 -0400
+Subject: [PATCH 11/14] krb5: Remove unused function
+
+Related:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/util/sss_krb5.c | 30 ------------------------------
+ src/util/sss_krb5.h |  2 --
+ 2 files changed, 32 deletions(-)
+
+diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
+index 440edab8a4624b33b7d358e64ead93949fc3de88..d4fee42a0297d5bb46135669a5fc12857ea95936 100644
+--- a/src/util/sss_krb5.c
++++ b/src/util/sss_krb5.c
+@@ -921,36 +921,6 @@ sss_krb5_residual_by_type(const char *full_location,
+ }
+ 
+ const char *
+-sss_krb5_cc_file_path(const char *full_location)
+-{
+-    enum sss_krb5_cc_type cc_type;
+-    const char *residual;
+-
+-    cc_type = sss_krb5_get_type(full_location);
+-    residual = sss_krb5_residual_by_type(full_location, cc_type);
+-
+-    switch(cc_type) {
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-        case SSS_KRB5_TYPE_KEYRING:
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-        case SSS_KRB5_TYPE_FILE:
+-            return residual;
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-        case SSS_KRB5_TYPE_DIR:
+-            /* DIR::/run/user/tkt_foo */
+-            if (residual[0] == ':') {
+-                ++residual;
+-            }
+-            return residual;
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-        case SSS_KRB5_TYPE_UNKNOWN:
+-            break;
+-    }
+-
+-    return NULL;
+-}
+-
+-const char *
+ sss_krb5_residual_check_type(const char *full_location,
+                              enum sss_krb5_cc_type expected_type)
+ {
+diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
+index aaf2a64882254ba173fb57c5dab47d246082392c..efde48b62170a142ebfca907013c3558ec47f428 100644
+--- a/src/util/sss_krb5.h
++++ b/src/util/sss_krb5.h
+@@ -154,8 +154,6 @@ sss_krb5_get_type(const char *full_location);
+ const char *
+ sss_krb5_residual_by_type(const char *full_location, enum sss_krb5_cc_type type);
+ const char *
+-sss_krb5_cc_file_path(const char *full_location);
+-const char *
+ sss_krb5_residual_check_type(const char *full_location,
+                              enum sss_krb5_cc_type expected_type);
+ 
+-- 
+1.8.3.1
+
diff --git a/0012-krb5-Add-file-dir-path-precheck.patch b/0012-krb5-Add-file-dir-path-precheck.patch
new file mode 100644
index 0000000..f4c5a5c
--- /dev/null
+++ b/0012-krb5-Add-file-dir-path-precheck.patch
@@ -0,0 +1,97 @@
+From 14050f35224360883e20ebd810d3eb40f39267cf Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Sat, 31 Aug 2013 14:21:22 -0400
+Subject: [PATCH 12/14] krb5: Add file/dir path precheck
+
+Add a precheck on the actual existence at all of the file/dir ccname
+targeted (for FILE/DIR types), and bail early if nothing is available.
+
+While testing I found out that without this check, the krb5_cc_resolve()
+function we call as user to check old paths would try to create the
+directory if it didn't exist.
+
+With a ccname of DIR:/tmp/ccdir_1000 saved in the user entry this would
+cause two undesirable side effects:
+
+First it would actually create a directory with the old name, when it
+should not.
+
+Second, because for some reason the umask is set to 0127 in sssd_be, it
+would create the directory with permission 600 (missing the 'x' traverse
+bit on the directory. If the new ccache has the same name it would cause
+the krb5_child process to fal to store the credential cache in it.
+
+Related:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_auth.c  |  1 +
+ src/providers/krb5/krb5_utils.c | 34 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index 1585f709655853827f2778010452a58657add5d0..7cfa3e943c15c0f515f3372079cee18dd7978c92 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -69,6 +69,7 @@ check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
+                                     realm, kr->upn);
+     switch (ret) {
+     case ERR_NOT_FOUND:
++    case ENOENT:
+         DEBUG(SSSDBG_TRACE_FUNC,
+               ("Saved ccache %s doesn't exist.\n", old_ccache));
+         return ENOENT;
+diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
+index d0ccd2d7e03bcabe07113b5abb43d9119b35321c..bb933d7f722cbef90b73f4a721382165572c69b9 100644
+--- a/src/providers/krb5/krb5_utils.c
++++ b/src/providers/krb5/krb5_utils.c
+@@ -967,6 +967,30 @@ done:
+     return ret;
+ }
+ 
++static errno_t sss_low_level_path_check(const char *ccname)
++{
++    const char *filename;
++    struct stat buf;
++    int ret;
++
++    if (ccname[0] == '/') {
++        filename = ccname;
++    } else if (strncmp(ccname, "FILE:", 5) == 0) {
++        filename = ccname + 5;
++    } else if (strncmp(ccname, "DIR:", 4) == 0) {
++        filename = ccname + 4;
++        if (filename[0] == ':') filename += 1;
++    } else {
++        /* only FILE and DIR types need file checks so far, we ignore any
++         * other type */
++        return EOK;
++    }
++
++    ret = stat(filename, &buf);
++    if (ret == -1) return errno;
++    return EOK;
++}
++
+ errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
+                                   const char *realm, const char *principal)
+ {
+@@ -980,6 +1004,16 @@ errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
+     krb5_error_code kerr;
+     errno_t ret;
+ 
++    /* first of all verify if the old ccache file/dir exists as we may be
++     * trying to verify if an old ccache exists at all. If no file/dir
++     * exists bail out immediately otherwise a following krb5_cc_resolve()
++     * call may actually create paths and files we do not want to have
++     * around */
++    ret = sss_low_level_path_check(ccname);
++    if (ret) {
++        return ret;
++    }
++
+     tmp_ctx = talloc_new(NULL);
+     if (tmp_ctx == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n"));
+-- 
+1.8.3.1
+
diff --git a/0013-krb5_child-Simplify-ccache-creation.patch b/0013-krb5_child-Simplify-ccache-creation.patch
new file mode 100644
index 0000000..ab4c6f8
--- /dev/null
+++ b/0013-krb5_child-Simplify-ccache-creation.patch
@@ -0,0 +1,582 @@
+From a6a0d4edebccd3cf04f9813fc65185845626b5d4 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Mon, 2 Sep 2013 23:52:46 -0400
+Subject: [PATCH 13/14] krb5_child: Simplify ccache creation
+
+The containing ccache directory is precreated by the parent code,
+so there is no special need to do so here for any type.
+Also the special handling for the FILE ccache temporary file is not really
+useful, because libkrb5 internally unlinks and then recreate the file, so
+mkstemp cannot really prevent subtle races, it can only make sure the file is
+unique at creation time.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/providers/krb5/krb5_child.c | 480 ++++++++--------------------------------
+ 1 file changed, 90 insertions(+), 390 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
+index 842b50e6e23cf9b00f51c0a01cfd960e4156ee21..4f56736de152d1443add8b69db261faf3b75529f 100644
+--- a/src/providers/krb5/krb5_child.c
++++ b/src/providers/krb5/krb5_child.c
+@@ -424,11 +424,7 @@ static krb5_error_code create_empty_cred(krb5_context ctx, krb5_principal princ,
+ 
+ done:
+     if (kerr != 0) {
+-        if (cred != NULL && cred->client != NULL) {
+-            krb5_free_principal(ctx, cred->client);
+-        }
+-
+-        free(cred);
++        krb5_free_creds(ctx, cred);
+     } else {
+         *_cred = cred;
+     }
+@@ -436,281 +432,38 @@ done:
+     return kerr;
+ }
+ 
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-static bool need_switch_to_principal(krb5_context ctx, krb5_principal princ)
+-{
+-    krb5_error_code kerr;
+-    krb5_ccache default_cc = NULL;
+-    krb5_principal default_princ = NULL;
+-    char *default_full_name = NULL;
+-    char *full_name = NULL;
+-    bool ret = false;
+-
+-    kerr = krb5_cc_default(ctx, &default_cc);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
+-        goto done;
+-    }
+-
+-    kerr = krb5_cc_get_principal(ctx, default_cc, &default_princ);
+-    if (kerr == KRB5_FCC_NOFILE) {
+-        /* There is not any default cache. */
+-        ret = true;
+-        goto done;
+-    } else if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
+-        goto done;
+-    }
+-
+-    kerr = krb5_unparse_name(ctx, default_princ, &default_full_name);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
+-        goto done;
+-    }
+-
+-    kerr = krb5_unparse_name(ctx, princ, &full_name);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_TRACE_INTERNAL, kerr);
+-        goto done;
+-    }
+-
+-    DEBUG(SSSDBG_FUNC_DATA,
+-          ("Comparing default principal [%s] and new principal [%s].\n",
+-           default_full_name, full_name));
+-    if (0 == strcmp(default_full_name, full_name)) {
+-        ret = true;
+-    }
+-
+-done:
+-    if (default_cc != NULL) {
+-        kerr = krb5_cc_close(ctx, default_cc);
+-        if (kerr != 0) {
+-            KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-            goto done;
+-        }
+-    }
+-
+-    /* all functions can be safely called with NULL. */
+-    krb5_free_principal(ctx, default_princ);
+-    krb5_free_unparsed_name(ctx, default_full_name);
+-    krb5_free_unparsed_name(ctx, full_name);
+-
+-    return ret;
+-}
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-static krb5_error_code
+-store_creds_in_ccache(krb5_context ctx, krb5_principal princ,
+-                      krb5_ccache cc, krb5_creds *creds)
+-{
+-    krb5_error_code kerr;
+-    krb5_creds *l_cred;
+-    char *ccname;
+-
+-    if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
+-        kerr = krb5_cc_get_full_name(ctx, cc, &ccname);
+-        if (kerr != 0) {
+-            DEBUG(SSSDBG_TRACE_ALL,
+-                  ("Couldn't determine full name of ccache\n"));
+-        } else {
+-            DEBUG(SSSDBG_TRACE_ALL,
+-                  ("Storing credentials in [%s]\n", ccname));
+-            krb5_free_string(ctx, ccname);
+-        }
+-    }
+-
+-    kerr = krb5_cc_initialize(ctx, cc, princ);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-        goto done;
+-    }
+-
+-    if (creds == NULL) {
+-        kerr = create_empty_cred(ctx, princ, &l_cred);
+-        if (kerr != 0) {
+-            KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-            goto done;
+-        }
+-    } else {
+-        l_cred = creds;
+-    }
+-
+-    kerr = krb5_cc_store_cred(ctx, cc, l_cred);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-        goto done;
+-    }
+-
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-    if (need_switch_to_principal(ctx, princ)) {
+-        kerr = krb5_cc_switch(ctx, cc);
+-        if (kerr != 0) {
+-            KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-            goto done;
+-        }
+-    }
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-    kerr = krb5_cc_close(ctx, cc);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-        goto done;
+-    }
+-
+-done:
+-    return kerr;
+-}
+ 
+-static krb5_error_code create_ccache_file(krb5_context ctx,
+-                                          krb5_principal princ,
+-                                          char *ccname, krb5_creds *creds)
++static errno_t handle_randomized(char *in)
+ {
+-    krb5_error_code kerr;
+-    krb5_ccache tmp_cc = NULL;
+-    char *cc_file_name;
+-    int fd = -1;
+     size_t ccname_len;
+-    char *dummy;
+-    char *tmp_ccname;
+-    TALLOC_CTX *tmp_ctx = NULL;
+-    mode_t old_umask;
++    char *ccname = NULL;
++    int ret;
++    int fd;
+ 
+-    DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
+-
+-    if (strncmp(ccname, "FILE:", 5) == 0) {
+-        cc_file_name = ccname + 5;
++    /* We only treat the FILE type case in a special way due to the history
++     * of storing FILE type ccache in /tmp and associated security issues */
++    if (in[0] == '/') {
++        ccname = in;
++    } else if (strncmp(in, "FILE:", 5) == 0) {
++        ccname = in + 5;
+     } else {
+-        cc_file_name = ccname;
+-    }
+-
+-    if (cc_file_name[0] != '/') {
+-        DEBUG(1, ("Ccache filename is not an absolute path.\n"));
+-        return EINVAL;
+-    }
+-
+-    tmp_ctx = talloc_new(tmp_ctx);
+-    if (tmp_ctx == NULL) {
+-        DEBUG(1, ("talloc_new failed.\n"));
+-        return ENOMEM;
+-    }
+-
+-    dummy = strrchr(cc_file_name, '/');
+-    tmp_ccname = talloc_strndup(tmp_ctx, cc_file_name,
+-                                (size_t) (dummy-cc_file_name));
+-    if (tmp_ccname == NULL) {
+-        DEBUG(1, ("talloc_strdup failed.\n"));
+-        kerr = ENOMEM;
+-        goto done;
+-    }
+-    tmp_ccname = talloc_asprintf_append(tmp_ccname, "/.krb5cc_dummy_XXXXXX");
+-    if (tmp_ccname == NULL) {
+-        kerr = ENOMEM;
+-        goto done;
+-    }
+-
+-    old_umask = umask(077);
+-    fd = mkstemp(tmp_ccname);
+-    umask(old_umask);
+-    if (fd == -1) {
+-        kerr = errno;
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
+-        goto done;
+-    }
+-
+-    kerr = krb5_cc_resolve(ctx, tmp_ccname, &tmp_cc);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+-        goto done;
+-    }
+-
+-    kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
+-    if (fd != -1) {
+-        close(fd);
+-        fd = -1;
+-    }
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+-        goto done;
+-    }
+-
+-
+-    ccname_len = strlen(cc_file_name);
+-    if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len - 6), "XXXXXX") == 0) {
+-        fd = mkstemp(cc_file_name);
++        return EOK;
++    }
++
++    ccname_len = strlen(ccname);
++    if (ccname_len >= 6 && strcmp(ccname + (ccname_len - 6), "XXXXXX") == 0) {
++        /* NOTE: this call is only used to create a unique name, as later
++         * krb5_cc_initialize() will unlink and recreate the file.
++         * This is ok because this part of the code is called with
++         * privileges already dropped when handling user ccache, or the ccache
++         * is stored in a private directory. So we do not have huge issues if
++         * something races, we mostly care only about not accidentally use
++         * an existing name and thus failing in the process of saving the
++         * cache. Malicious races can only be avoided by libkrb5 itself. */
++        fd = mkstemp(ccname);
+         if (fd == -1) {
+-            kerr = errno;
+-            DEBUG(SSSDBG_CRIT_FAILURE,
+-                  ("mkstemp failed [%d][%s].\n", kerr, strerror(kerr)));
+-            goto done;
+-        }
+-    }
+-
+-    kerr = rename(tmp_ccname, cc_file_name);
+-    if (kerr == -1) {
+-        kerr = errno;
+-        DEBUG(1, ("rename failed [%d][%s].\n", kerr, strerror(kerr)));
+-    }
+-
+-    DEBUG(SSSDBG_TRACE_LIBS, ("Created ccache file: [%s]\n", ccname));
+-
+-done:
+-    if (kerr != 0 && tmp_cc != NULL) {
+-        krb5_cc_destroy(ctx, tmp_cc);
+-    }
+-
+-    if (fd != -1) {
+-        close(fd);
+-    }
+-
+-    talloc_free(tmp_ctx);
+-    return kerr;
+-}
+-
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-
+-static errno_t
+-create_ccdir(const char *dirname, uid_t uid, gid_t gid)
+-{
+-    mode_t old_umask;
+-    struct stat statbuf;
+-    errno_t ret;
+-
+-    old_umask = umask(0000);
+-    ret = mkdir(dirname, 0700);
+-    umask(old_umask);
+-    if (ret == -1) {
+-        /* Failing the mkdir is only OK if the directory already
+-         * exists AND it is owned by the same user and group and
+-         * has the correct permissions.
+-         */
+-        ret = errno;
+-        if (ret == EEXIST) {
+-            errno = 0;
+-            ret = stat(dirname, &statbuf);
+-            if (ret == -1) {
+-                ret = errno;
+-                DEBUG(SSSDBG_CRIT_FAILURE,
+-                        ("stat failed [%d]: %s\n", ret, strerror(ret)));
+-                return EIO;
+-            }
+-
+-            if (statbuf.st_uid != uid || statbuf.st_gid != gid) {
+-                DEBUG(SSSDBG_CRIT_FAILURE,
+-                      ("The directory %s is owned by %d/%d, expected %d/%d\n",
+-                       dirname, statbuf.st_uid, statbuf.st_gid, uid, gid));
+-                return EACCES;
+-            }
+-
+-            if ((statbuf.st_mode & ~S_IFMT) != 0700) {
+-                DEBUG(SSSDBG_CRIT_FAILURE,
+-                      ("The directory %s has wrong permissions %o, expected 0700\n",
+-                       dirname, (statbuf.st_mode & ~S_IFMT)));
+-                return EACCES;
+-            }
+-        } else {
+-            DEBUG(SSSDBG_CRIT_FAILURE, ("mkdir [%s] failed [%d]: %s\n",
+-                  dirname, ret, strerror(ret)));
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE, ("mkstemp(\"%s\") failed!\n", ccname));
+             return ret;
+         }
+     }
+@@ -718,136 +471,79 @@ create_ccdir(const char *dirname, uid_t uid, gid_t gid)
+     return EOK;
+ }
+ 
+-static krb5_error_code
+-create_ccache_in_dir(uid_t uid, gid_t gid,
+-                     krb5_context ctx,
+-                     krb5_principal princ,
+-                     char *ccname, krb5_creds *creds)
++/* NOTE: callers rely on 'name' being *changed* if it needs to be randomized,
++ * as they will then send the name back to the new name via the return call
++ * k5c_attach_ccname_msg(). Callers will send in a copy of the name if they
++ * do not care for changes. */
++static krb5_error_code create_ccache(char *ccname, krb5_creds *creds)
+ {
++    krb5_context kctx = NULL;
++    krb5_ccache kcc = NULL;
++    const char *type;
+     krb5_error_code kerr;
+-    krb5_ccache tmp_cc = NULL;
+-    const char *dirname;
+-
+-    DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
+-
+-    dirname = sss_krb5_residual_check_type(ccname, SSS_KRB5_TYPE_DIR);
+-    if (dirname == NULL) {
+-        return EIO;
++#ifdef HAVE_KRB5_CC_COLLECTION
++    krb5_ccache cckcc;
++    bool switch_to_cc = false;
++#endif
++
++    /* Set a restrictive umask, just in case we end up creating any file */
++    umask(077);
++
++    /* we create a new context here as the main process one may have been
++     * opened as root and contain possibly references (even open handles ?)
++     * to resources we do not have or do not want to have access to */
++    kerr = krb5_init_context(&kctx);
++    if (kerr) {
++        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
++        return ERR_INTERNAL;
+     }
+ 
+-    if (dirname[0] == ':') {
+-        /* Cache name in the form of DIR::filepath represents a single
+-         * ccache in a collection that we are trying to reuse.
+-         * See src/lib/krb5/ccache/cc_dir.c in the MIT Kerberos tree.
+-         */
+-        kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
+-        if (kerr != 0) {
+-            KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-            goto done;
+-        }
+-    } else if (dirname[0] == '/') {
+-        /* An absolute path denotes that krb5_child should create a new
+-         * ccache. We can afford to just call mkdir(dirname) because we
+-         * only want the last component to be created.
+-         */
++    kerr = handle_randomized(ccname);
++    if (kerr) goto done;
+ 
+-        kerr = create_ccdir(dirname, uid, gid);
+-        if (kerr) {
+-            DEBUG(SSSDBG_OP_FAILURE,
+-                  ("Cannot create directory %s\n", dirname));
+-            goto done;
+-        }
++    kerr = krb5_cc_resolve(kctx, ccname, &kcc);
++    if (kerr) goto done;
+ 
+-        kerr = krb5_cc_set_default_name(ctx, ccname);
+-        if (kerr != 0) {
+-            KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-            goto done;
+-        }
++    type = krb5_cc_get_type(kctx, kcc);
++    DEBUG(SSSDBG_TRACE_ALL, ("Initializing ccache of type [%s]\n", type));
+ 
+-        kerr = krb5_cc_new_unique(ctx, "DIR", NULL, &tmp_cc);
+-        if (kerr != 0) {
+-            KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-            goto done;
++#ifdef HAVE_KRB5_CC_COLLECTION
++    if (krb5_cc_support_switch(kctx, type)) {
++        kerr = krb5_cc_set_default_name(kctx, ccname);
++        if (kerr) goto done;
++
++        kerr = krb5_cc_cache_match(kctx, creds->client, &cckcc);
++        if (kerr == KRB5_CC_NOTFOUND) {
++            kerr = krb5_cc_new_unique(kctx, type, NULL, &cckcc);
++            switch_to_cc = true;
+         }
+-    } else {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              ("Wrong residual format for DIR in ccache %s\n", ccname));
+-        return EIO;
++        if (kerr) goto done;
++        krb5_cc_close(kctx, kcc);
++        kcc = cckcc;
+     }
++#endif
+ 
+-    kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr);
+-        goto done;
+-    }
+-
+-done:
+-    if (kerr != 0 && tmp_cc != NULL) {
+-        krb5_cc_destroy(ctx, tmp_cc);
+-    }
+-    return kerr;
+-}
+-
+-static krb5_error_code
+-create_ccache_keyring(krb5_context ctx,
+-                      krb5_principal princ,
+-                      char *ccname,
+-                      krb5_creds *creds)
+-{
+-    krb5_error_code kerr;
+-    krb5_ccache tmp_cc = NULL;
+-
+-    DEBUG(SSSDBG_FUNC_DATA, ("Creating ccache at [%s]\n", ccname));
++    kerr = krb5_cc_initialize(kctx, kcc, creds->client);
++    if (kerr) goto done;
+ 
+-    kerr = krb5_cc_resolve(ctx, ccname, &tmp_cc);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+-        goto done;
+-    }
++    kerr = krb5_cc_store_cred(kctx, kcc, creds);
++    if (kerr) goto done;
+ 
+-    kerr = store_creds_in_ccache(ctx, princ, tmp_cc, creds);
+-    if (kerr != 0) {
+-        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+-        goto done;
++#ifdef HAVE_KRB5_CC_COLLECTION
++    if (switch_to_cc) {
++        kerr = krb5_cc_switch(kctx, kcc);
++        if (kerr) goto done;
+     }
++#endif
+ 
+ done:
+-    if (kerr != 0 && tmp_cc != NULL) {
+-        krb5_cc_destroy(ctx, tmp_cc);
++    if (kcc) {
++        /* FIXME: should we krb5_cc_destroy in case of error ? */
++        krb5_cc_close(kctx, kcc);
+     }
+-
+     return kerr;
+ }
+ 
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-static krb5_error_code
+-create_ccache(uid_t uid, gid_t gid, krb5_context ctx,
+-              krb5_principal princ, char *ccname, krb5_creds *creds)
+-{
+-    enum sss_krb5_cc_type cctype;
+-
+-    cctype = sss_krb5_get_type(ccname);
+-    switch (cctype) {
+-        case SSS_KRB5_TYPE_FILE:
+-            return create_ccache_file(ctx, princ, ccname, creds);
+-
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-        case SSS_KRB5_TYPE_DIR:
+-            return create_ccache_in_dir(uid, gid, ctx, princ, ccname, creds);
+-
+-        case SSS_KRB5_TYPE_KEYRING:
+-            return create_ccache_keyring(ctx, princ, ccname, creds);
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-        default:
+-            DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown cache type\n"));
+-            return EINVAL;
+-    }
+-
+-    return EINVAL;  /* Should never get here */
+-}
+-
+ static errno_t pack_response_packet(TALLOC_CTX *mem_ctx, errno_t error,
+                                     struct response_data *resp_list,
+                                     uint8_t **_buf, size_t *_len)
+@@ -1176,7 +872,7 @@ static krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx,
+     }
+ 
+     /* Use the updated principal in the creds in case canonicalized */
+-    kerr = create_ccache_file(ctx, creds.client, ccname, &creds);
++    kerr = create_ccache(ccname, &creds);
+     if (kerr != 0) {
+         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+         goto done;
+@@ -1255,8 +951,7 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
+     }
+ 
+     /* Use the updated principal in the creds in case canonicalized */
+-    kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
+-                         principal, cc_name, kr->creds);
++    kerr = create_ccache(cc_name, kr->creds);
+     if (kerr != 0) {
+         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+         goto done;
+@@ -1647,18 +1342,23 @@ done:
+ 
+ static errno_t create_empty_ccache(struct krb5_req *kr)
+ {
++    krb5_creds *creds = NULL;
+     krb5_error_code kerr;
+ 
+     DEBUG(SSSDBG_TRACE_LIBS, ("Creating empty ccache\n"));
+ 
+-    kerr = create_ccache(kr->uid, kr->gid, kr->ctx,
+-                         kr->princ, kr->ccname, NULL);
++    kerr = create_empty_cred(kr->ctx, kr->princ, &creds);
++    if (kerr == 0) {
++        kerr = create_ccache(kr->ccname, creds);
++    }
+     if (kerr != 0) {
+         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+     } else {
+         kerr = k5c_attach_ccname_msg(kr);
+     }
+ 
++    krb5_free_creds(kr->ctx, creds);
++
+     return map_krb5_error(kerr);
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/0014-krb5-Remove-unused-helper-functions.patch b/0014-krb5-Remove-unused-helper-functions.patch
new file mode 100644
index 0000000..bbfec9e
--- /dev/null
+++ b/0014-krb5-Remove-unused-helper-functions.patch
@@ -0,0 +1,127 @@
+From 077fa994f62641a13665b6a07d38b3d5a903dcdc Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo at redhat.com>
+Date: Tue, 3 Sep 2013 20:57:58 -0400
+Subject: [PATCH 14/14] krb5: Remove unused helper functions
+
+these functions are not needed anymore.
+
+Related:
+https://fedorahosted.org/sssd/ticket/2061
+---
+ src/util/sss_krb5.c | 80 -----------------------------------------------------
+ src/util/sss_krb5.h |  8 ------
+ 2 files changed, 88 deletions(-)
+
+diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
+index d4fee42a0297d5bb46135669a5fc12857ea95936..f8a7e6f9be15c7b2dfee9906af914533bd8ac4cd 100644
+--- a/src/util/sss_krb5.c
++++ b/src/util/sss_krb5.c
+@@ -854,86 +854,6 @@ sss_krb5_free_keytab_entry_contents(krb5_context context,
+ }
+ #endif
+ 
+-#define SSS_KRB5_FILE   "FILE:"
+-#define SSS_KRB5_DIR    "DIR:"
+-#define SSS_KRB5_KEYRING "KEYRING:"
+-
+-enum sss_krb5_cc_type
+-sss_krb5_get_type(const char *full_location)
+-{
+-    if (!full_location) {
+-        return SSS_KRB5_TYPE_UNKNOWN;
+-    }
+-
+-    if (strncmp(full_location, SSS_KRB5_FILE,
+-                sizeof(SSS_KRB5_FILE)-1) == 0) {
+-        return SSS_KRB5_TYPE_FILE;
+-    }
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-    else if (strncmp(full_location, SSS_KRB5_DIR,
+-               sizeof(SSS_KRB5_DIR)-1) == 0) {
+-        return SSS_KRB5_TYPE_DIR;
+-    }
+-    else if (strncmp(full_location, SSS_KRB5_KEYRING,
+-               sizeof(SSS_KRB5_KEYRING)-1) == 0) {
+-        return SSS_KRB5_TYPE_KEYRING;
+-    }
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-    else if (full_location[0] == '/') {
+-        return SSS_KRB5_TYPE_FILE;
+-    }
+-
+-    return SSS_KRB5_TYPE_UNKNOWN;
+-}
+-
+-const char *
+-sss_krb5_residual_by_type(const char *full_location,
+-                          enum sss_krb5_cc_type type)
+-{
+-    size_t offset;
+-
+-    if (full_location == NULL) return NULL;
+-
+-    switch (type) {
+-        case SSS_KRB5_TYPE_FILE:
+-            if (full_location[0] == '/') {
+-                offset = 0;
+-            } else {
+-                offset = sizeof(SSS_KRB5_FILE)-1;
+-            }
+-            break;
+-#ifdef HAVE_KRB5_CC_COLLECTION
+-        case SSS_KRB5_TYPE_DIR:
+-            offset = sizeof(SSS_KRB5_DIR)-1;
+-            break;
+-
+-        case SSS_KRB5_TYPE_KEYRING:
+-            offset = sizeof(SSS_KRB5_KEYRING)-1;
+-            break;
+-#endif /* HAVE_KRB5_CC_COLLECTION */
+-
+-        default:
+-            return NULL;
+-    }
+-
+-    return full_location + offset;
+-}
+-
+-const char *
+-sss_krb5_residual_check_type(const char *full_location,
+-                             enum sss_krb5_cc_type expected_type)
+-{
+-    enum sss_krb5_cc_type type;
+-
+-    type = sss_krb5_get_type(full_location);
+-    if (type != expected_type) {
+-        DEBUG(SSSDBG_OP_FAILURE, ("Unexpected ccache type\n"));
+-        return NULL;
+-    }
+-
+-    return sss_krb5_residual_by_type(full_location, type);
+-}
+ 
+ #ifdef HAVE_KRB5_SET_TRACE_CALLBACK
+ 
+diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
+index efde48b62170a142ebfca907013c3558ec47f428..db47e0a6b61fc706cdadc74ad1d4c1e9e7ef3589 100644
+--- a/src/util/sss_krb5.h
++++ b/src/util/sss_krb5.h
+@@ -149,14 +149,6 @@ enum sss_krb5_cc_type {
+     SSS_KRB5_TYPE_UNKNOWN
+ };
+ 
+-enum sss_krb5_cc_type
+-sss_krb5_get_type(const char *full_location);
+-const char *
+-sss_krb5_residual_by_type(const char *full_location, enum sss_krb5_cc_type type);
+-const char *
+-sss_krb5_residual_check_type(const char *full_location,
+-                             enum sss_krb5_cc_type expected_type);
+-
+ /* === Compatibility routines for the Heimdal Kerberos implementation === */
+ 
+ void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
+-- 
+1.8.3.1
+
diff --git a/sssd.spec b/sssd.spec
index e76a9f5..82b306e 100644
--- a/sssd.spec
+++ b/sssd.spec
@@ -8,7 +8,7 @@
 
 Name: sssd
 Version: 1.11.0
-Release: 1%{?dist}
+Release: 2%{?dist}
 Group: Applications/System
 Summary: System Security Services Daemon
 License: GPLv3+
@@ -17,6 +17,20 @@ Source0: https://fedorahosted.org/released/sssd/%{name}-%{version}.tar.gz
 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
 ### Patches ###
+Patch0001: 0001-krb5-Add-calls-to-change-and-restore-credentials.patch
+Patch0002: 0002-krb5-Add-helper-to-destroy-ccache-as-user.patch
+Patch0003: 0003-krb5-Use-krb5_cc_destroy-to-remove-old-ccaches.patch
+Patch0004: 0004-krb5-Replace-type-specific-ccache-principal-check.patch
+Patch0005: 0005-krb5-Move-determination-of-user-being-active.patch
+Patch0006: 0006-krb5-move-template-check-to-initializzation.patch
+Patch0007: 0007-krb5-Make-check_for_valid_tgt-static.patch
+Patch0008: 0008-krb5-Use-new-function-to-validate-ccaches.patch
+Patch0009: 0009-krb5-Unify-function-to-create-ccache-files.patch
+Patch0010: 0010-krb5-Remove-unused-ccache-backend-infrastructure.patch
+Patch0011: 0011-krb5-Remove-unused-function.patch
+Patch0012: 0012-krb5-Add-file-dir-path-precheck.patch
+Patch0013: 0013-krb5_child-Simplify-ccache-creation.patch
+Patch0014: 0014-krb5-Remove-unused-helper-functions.patch
 
 ### Dependencies ###
 Requires: sssd-common = %{version}-%{release}
@@ -676,6 +690,10 @@ fi
 %postun -n libsss_idmap -p /sbin/ldconfig
 
 %changelog
+* Wed Aug 28 2013 Jakub Hrozek <jhrozek at redhat.com> - 1.11.0-2
+- Backport simplification of ccache management from 1.11.1
+- Resolves: rhbz#1010553 - sssd setting KRB5CCNAME=(null) on login
+
 * Wed Aug 28 2013 Jakub Hrozek <jhrozek at redhat.com> - 1.11.0-1
 - New upstream release 1.11.0
 - https://fedorahosted.org/sssd/wiki/Releases/Notes-1.11.0


More information about the scm-commits mailing list