Blame SOURCES/0055-KCM-Fill-empty-cache-do-not-initialize-a-new-one.patch

d6181b
From dbcd8411643a641316696f221860517ab06879ba Mon Sep 17 00:00:00 2001
d6181b
From: Jakub Hrozek <jhrozek@redhat.com>
d6181b
Date: Wed, 28 Aug 2019 14:23:18 +0200
d6181b
Subject: [PATCH 55/55] KCM: Fill empty cache, do not initialize a new one
d6181b
MIME-Version: 1.0
d6181b
Content-Type: text/plain; charset=UTF-8
d6181b
Content-Transfer-Encoding: 8bit
d6181b
d6181b
Related:
d6181b
https://pagure.io/SSSD/sssd/issue/4017
d6181b
d6181b
openssh uses this sequence of calls:
d6181b
    gen_new()
d6181b
    switch()
d6181b
    initialize()
d6181b
d6181b
What happened before was that if there was already some cache, gen_new
d6181b
would create a new empty cache, then switch would set it as the default.
d6181b
But then, during the initialize call, the cache that used to be the
d6181b
default was deleted, another one created and used as the default. This
d6181b
meant. Afterwards, KCM would store the credentials in the previous
d6181b
cache, which would no longer be the default.
d6181b
d6181b
The logic behind was that KCM didn't anticipate the client generating
d6181b
the new and setting the default on its own.
d6181b
d6181b
Reviewed-by: Michal Židek <mzidek@redhat.com>
d6181b
---
d6181b
 src/responder/kcm/kcmsrv_ops.c | 84 +++++++++++++++++++++++++++++++++-
d6181b
 1 file changed, 82 insertions(+), 2 deletions(-)
d6181b
d6181b
diff --git a/src/responder/kcm/kcmsrv_ops.c b/src/responder/kcm/kcmsrv_ops.c
d6181b
index 8bd63165b..2181ec6e6 100644
d6181b
--- a/src/responder/kcm/kcmsrv_ops.c
d6181b
+++ b/src/responder/kcm/kcmsrv_ops.c
d6181b
@@ -367,6 +367,8 @@ struct kcm_op_initialize_state {
d6181b
 static void kcm_op_initialize_got_byname(struct tevent_req *subreq);
d6181b
 static void kcm_op_initialize_cc_create_done(struct tevent_req *subreq);
d6181b
 static void kcm_op_initialize_cc_delete_done(struct tevent_req *subreq);
d6181b
+static void kcm_op_initialize_fill_princ_step(struct tevent_req *req);
d6181b
+static void kcm_op_initialize_fill_princ_done(struct tevent_req *subreq);
d6181b
 static void kcm_op_initialize_create_step(struct tevent_req *req);
d6181b
 static void kcm_op_initialize_got_default(struct tevent_req *subreq);
d6181b
 static void kcm_op_initialize_set_default_done(struct tevent_req *subreq);
d6181b
@@ -450,6 +452,15 @@ static void kcm_op_initialize_got_byname(struct tevent_req *subreq)
d6181b
     }
d6181b
 
d6181b
     if (state->new_cc != NULL) {
d6181b
+        if (kcm_cc_get_client_principal(state->new_cc) == NULL) {
d6181b
+            /* This is a cache that was pre-created w/o a principal (sshd does this),
d6181b
+             * let's fill in the principal and set the cache as default if not
d6181b
+             * already
d6181b
+             */
d6181b
+            kcm_op_initialize_fill_princ_step(req);
d6181b
+            return;
d6181b
+        }
d6181b
+
d6181b
         ok = kcm_cc_access(state->new_cc, state->op_ctx->client);
d6181b
         if (!ok) {
d6181b
             state->op_ret = EACCES;
d6181b
@@ -501,6 +512,70 @@ static void kcm_op_initialize_cc_delete_done(struct tevent_req *subreq)
d6181b
     kcm_op_initialize_create_step(req);
d6181b
 }
d6181b
 
d6181b
+static void kcm_op_initialize_fill_princ_step(struct tevent_req *req)
d6181b
+{
d6181b
+    struct tevent_req *subreq;
d6181b
+    struct kcm_op_initialize_state *state = tevent_req_data(req,
d6181b
+                                            struct kcm_op_initialize_state);
d6181b
+    errno_t ret;
d6181b
+    struct kcm_mod_ctx *mod_ctx;
d6181b
+    uuid_t uuid;
d6181b
+
d6181b
+    mod_ctx = kcm_mod_ctx_new(state);
d6181b
+    if (mod_ctx == NULL) {
d6181b
+        tevent_req_error(req, ENOMEM);
d6181b
+        return;
d6181b
+    }
d6181b
+    mod_ctx->client = state->princ;
d6181b
+
d6181b
+    ret = kcm_cc_get_uuid(state->new_cc, uuid);
d6181b
+    if (ret != EOK) {
d6181b
+        tevent_req_error(req, ret);
d6181b
+        return;
d6181b
+    }
d6181b
+
d6181b
+    subreq = kcm_ccdb_mod_cc_send(state,
d6181b
+                                  state->ev,
d6181b
+                                  state->op_ctx->kcm_data->db,
d6181b
+                                  state->op_ctx->client,
d6181b
+                                  uuid,
d6181b
+                                  mod_ctx);
d6181b
+    if (subreq == NULL) {
d6181b
+        tevent_req_error(req, ENOMEM);
d6181b
+        return;
d6181b
+    }
d6181b
+    tevent_req_set_callback(subreq, kcm_op_initialize_fill_princ_done, req);
d6181b
+}
d6181b
+
d6181b
+static void kcm_op_initialize_fill_princ_done(struct tevent_req *subreq)
d6181b
+{
d6181b
+    struct tevent_req *req = tevent_req_callback_data(subreq,
d6181b
+                                                      struct tevent_req);
d6181b
+    struct kcm_op_initialize_state *state = tevent_req_data(req,
d6181b
+                                            struct kcm_op_initialize_state);
d6181b
+    errno_t ret;
d6181b
+
d6181b
+    ret = kcm_ccdb_mod_cc_recv(subreq);
d6181b
+    talloc_zfree(subreq);
d6181b
+    if (ret != EOK) {
d6181b
+        DEBUG(SSSDBG_OP_FAILURE,
d6181b
+              "Cannot modify ccache [%d]: %s\n",
d6181b
+              ret, sss_strerror(ret));
d6181b
+        tevent_req_error(req, ret);
d6181b
+        return;
d6181b
+    }
d6181b
+
d6181b
+    /* Make sure the cache we just initialized is the default one */
d6181b
+    subreq = kcm_ccdb_get_default_send(state, state->ev,
d6181b
+                                       state->op_ctx->kcm_data->db,
d6181b
+                                       state->op_ctx->client);
d6181b
+    if (subreq == NULL) {
d6181b
+        tevent_req_error(req, ret);
d6181b
+        return;
d6181b
+    }
d6181b
+    tevent_req_set_callback(subreq, kcm_op_initialize_got_default, req);
d6181b
+}
d6181b
+
d6181b
 static void kcm_op_initialize_create_step(struct tevent_req *req)
d6181b
 {
d6181b
     struct tevent_req *subreq;
d6181b
@@ -588,11 +663,14 @@ static void kcm_op_initialize_got_default(struct tevent_req *subreq)
d6181b
         ret = kcm_cc_get_uuid(state->new_cc, dfl_uuid);
d6181b
         if (ret != EOK) {
d6181b
             DEBUG(SSSDBG_OP_FAILURE,
d6181b
-              "Cannot get new ccache UUID [%d]: %s\n",
d6181b
-              ret, sss_strerror(ret));
d6181b
+                  "Cannot get new ccache UUID [%d]: %s\n",
d6181b
+                  ret, sss_strerror(ret));
d6181b
             return;
d6181b
         }
d6181b
 
d6181b
+        DEBUG(SSSDBG_TRACE_FUNC,
d6181b
+              "The default ccached was not set, switching to the "
d6181b
+              "initialized\n");
d6181b
         subreq = kcm_ccdb_set_default_send(state,
d6181b
                                            state->ev,
d6181b
                                            state->op_ctx->kcm_data->db,
d6181b
@@ -1756,6 +1834,8 @@ static void kcm_op_set_default_create_step_done(struct tevent_req *subreq)
d6181b
         return;
d6181b
     }
d6181b
 
d6181b
+    DEBUG(SSSDBG_TRACE_FUNC, "The ccache was created, switching to it");
d6181b
+
d6181b
     ret = kcm_cc_get_uuid(state->new_cc, state->dfl_uuid);
d6181b
     if (ret != EOK) {
d6181b
         DEBUG(SSSDBG_OP_FAILURE,
d6181b
-- 
d6181b
2.20.1
d6181b