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