>From 01075bb071f45ad8f87730e63fac6d80414482a6 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Wed, 28 Aug 2013 23:18:37 -0400
Subject: [PATCH 03/15] 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                     |  1 +
 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, 20 insertions(+), 119 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index b913a12b895d68f1f3e23c185e493e576641d0e2..23a12d8b8daab9a21778bd7942e3db0867501316 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -927,6 +927,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 \
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 d6c3a6dc2427c33cc5eb56c915ee7ac7adefa990..1a74241e75b9b6ae794907549975325296dca567 100644
--- a/src/providers/krb5/krb5_utils.c
+++ b/src/providers/krb5/krb5_utils.c
@@ -1135,42 +1135,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
@@ -1348,32 +1317,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
 };
 
 
@@ -1500,30 +1448,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

