[SSSD] [PATCH] Delete cached ccache file if password is expired

Sumit Bose sbose at redhat.com
Wed Jun 8 16:10:08 UTC 2011


Hi,

this patch should fix https://fedorahosted.org/sssd/ticket/888 which
describes a corner case where an unused ccache file with a random name
is not recreated during the renewal of an expired password via sshd with
privilege separation.

I have tried to think of a situation where it might be a bad idea to
remove the on-disk ccache file but found none.

bye,
Sumit
-------------- next part --------------
From 635da599d1f7e0c707288f2938d16e5259467f46 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 8 Jun 2011 16:23:10 +0200
Subject: [PATCH] Delete cached ccache file if password is expired

---
 src/providers/krb5/krb5_auth.c |   71 +++++++++++++++++++++++++++++++++++----
 1 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 7bc4972..a7444d3 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -146,11 +146,12 @@ static errno_t check_if_ccache_file_is_used(uid_t uid, const char *ccname,
     return EOK;
 }
 
-static int krb5_save_ccname(TALLOC_CTX *mem_ctx,
-                            struct sysdb_ctx *sysdb,
-                            struct sss_domain_info *domain,
-                            const char *name,
-                            const char *ccname)
+static int krb5_mod_ccname(TALLOC_CTX *mem_ctx,
+                           struct sysdb_ctx *sysdb,
+                           struct sss_domain_info *domain,
+                           const char *name,
+                           const char *ccname,
+                           int mod_op)
 {
     TALLOC_CTX *tmpctx;
     struct sysdb_attrs *attrs;
@@ -161,7 +162,13 @@ static int krb5_save_ccname(TALLOC_CTX *mem_ctx,
         return EINVAL;
     }
 
-    DEBUG(9, ("Save ccname [%s] for user [%s].\n", ccname, name));
+    if (mod_op != SYSDB_MOD_REP && mod_op != SYSDB_MOD_DEL) {
+        DEBUG(1, ("Unsupported operation [%d].\n", mod_op));
+        return EINVAL;
+    }
+
+    DEBUG(9, ("%s ccname [%s] for user [%s].\n",
+              mod_op == SYSDB_MOD_REP ? "Save" : "Delete", ccname, name));
 
     tmpctx = talloc_new(mem_ctx);
     if (!tmpctx) {
@@ -187,7 +194,7 @@ static int krb5_save_ccname(TALLOC_CTX *mem_ctx,
     }
 
     ret = sysdb_set_user_attr(tmpctx, sysdb,
-                              domain, name, attrs, SYSDB_MOD_REP);
+                              domain, name, attrs, mod_op);
     if (ret != EOK) {
         DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
         sysdb_transaction_cancel(sysdb);
@@ -204,6 +211,26 @@ done:
     return ret;
 }
 
+static int krb5_save_ccname(TALLOC_CTX *mem_ctx,
+                            struct sysdb_ctx *sysdb,
+                            struct sss_domain_info *domain,
+                            const char *name,
+                            const char *ccname)
+{
+    return krb5_mod_ccname(mem_ctx, sysdb, domain, name, ccname,
+                           SYSDB_MOD_REP);
+}
+
+static int krb5_delete_ccname(TALLOC_CTX *mem_ctx,
+                              struct sysdb_ctx *sysdb,
+                              struct sss_domain_info *domain,
+                              const char *name,
+                              const char *ccname)
+{
+    return krb5_mod_ccname(mem_ctx, sysdb, domain, name, ccname,
+                           SYSDB_MOD_DEL);
+}
+
 static struct krb5_ctx *get_krb5_ctx(struct be_req *be_req)
 {
     struct pam_data *pd;
@@ -799,7 +826,8 @@ static void krb5_child_done(struct tevent_req *subreq)
     /* If the child request failed, but did not return an offline error code,
      * return with the status */
     if (msg_status != PAM_SUCCESS && msg_status != PAM_AUTHINFO_UNAVAIL &&
-        msg_status != PAM_AUTHTOK_LOCK_BUSY) {
+        msg_status != PAM_AUTHTOK_LOCK_BUSY &&
+        msg_status != PAM_NEW_AUTHTOK_REQD) {
         state->pam_status = msg_status;
         state->dp_err = DP_ERR_OK;
         ret = EOK;
@@ -808,6 +836,33 @@ static void krb5_child_done(struct tevent_req *subreq)
         state->pam_status = msg_status;
     }
 
+    /* If the password is expired we can safely remove the ccache from the
+     * cache and disk if it is not actively used anymore. This will allow to
+     * create a new random ccache if sshd with privilege separation is used. */
+    if (msg_status == PAM_NEW_AUTHTOK_REQD) {
+        if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache_present) {
+            if (kr->old_ccname != NULL) {
+                ret = safe_remove_old_ccache_file(kr->old_ccname, "dummy");
+                if (ret != EOK) {
+                    DEBUG(1, ("Failed to remove old ccache file [%s], "
+                              "please remove it manually.\n", kr->old_ccname));
+                }
+
+                ret = krb5_delete_ccname(state, state->be_ctx->sysdb,
+                                         state->be_ctx->domain,
+                                         pd->user, kr->old_ccname);
+                if (ret != EOK) {
+                    DEBUG(1, ("krb5_delete_ccname failed.\n"));
+                }
+            }
+        }
+
+        state->pam_status = msg_status;
+        state->dp_err = DP_ERR_OK;
+        ret = EOK;
+        goto done;
+    }
+
     /* If the child request was successful and we run the first pass of the
      * change password request just return success. */
     if (msg_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
-- 
1.7.5.1



More information about the sssd-devel mailing list