From 042600d08a9d3188d7d3135fc235e6a7c2237a4b Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Fri, 24 Jul 2015 13:13:08 +0200 Subject: IPA: Always re-fetch the keytab from the IPA server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even if a keytab for one-way trust exists, re-fetch the keytab again and try to use it. Fall back to the previous one if it exists. This is in order to allow the admin to re-establish the trust keytabs with a simple sssd restart. Reviewed-by: Pavel Březina --- src/providers/ipa/ipa_subdomains_server.c | 83 ++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 23 deletions(-) (limited to 'src/providers/ipa/ipa_subdomains_server.c') diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c index 4bfea61e6..dfecab1bc 100644 --- a/src/providers/ipa/ipa_subdomains_server.c +++ b/src/providers/ipa/ipa_subdomains_server.c @@ -445,6 +445,17 @@ static void ipa_getkeytab_exec(const char *ccache, exit(1); } + /* ipa-getkeytab cannot add keys to an empty file, let's unlink it and only + * use the filename */ + ret = unlink(keytab_path); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to unlink the temporary ccname [%d][%s]\n", + ret, sss_strerror(ret)); + exit(1); + } + errno = 0; ret = execle(IPA_GETKEYTAB_PATH, IPA_GETKEYTAB_PATH, "-r", "-s", server, "-p", principal, "-k", keytab_path, NULL, @@ -561,6 +572,7 @@ struct ipa_server_trust_add_state { uint32_t direction; const char *forest; const char *keytab; + char *new_keytab; const char *principal; const char *forest_realm; const char *ccache; @@ -660,21 +672,20 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req) return EIO; } - ret = ipa_check_keytab(state->keytab, - state->id_ctx->server_mode->kt_owner_uid, - state->id_ctx->server_mode->kt_owner_gid); - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_FUNC, - "Keytab already present, can add the trust\n"); - return EOK; - } else if (ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to check for keytab: %d\n", ret); + state->new_keytab = talloc_asprintf(state, "%sXXXXXX", state->keytab); + if (state->new_keytab == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n"); + return ENOMEM; + } + + ret = sss_unique_filename(state, state->new_keytab); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create temporary keytab name\n"); return ret; } DEBUG(SSSDBG_TRACE_FUNC, - "No keytab for %s\n", state->subdom->name); + "Will re-fetch keytab for %s\n", state->subdom->name); hostname = dp_opt_get_string(state->id_ctx->ipa_options->basic, IPA_HOSTNAME); @@ -691,7 +702,7 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req) state->ccache, hostname, state->principal, - state->keytab); + state->new_keytab); if (subreq == NULL) { return ENOMEM; } @@ -710,23 +721,49 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq) ret = ipa_getkeytab_recv(subreq, NULL); talloc_zfree(subreq); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret); - tevent_req_error(req, ret); - return; + /* Do not fail here, but try to check and use the previous keytab, + * if any */ + DEBUG(SSSDBG_MINOR_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret); + } else { + DEBUG(SSSDBG_TRACE_FUNC, + "Keytab successfully retrieved to %s\n", state->new_keytab); } - DEBUG(SSSDBG_TRACE_FUNC, - "Keytab successfully retrieved to %s\n", state->keytab); - - ret = ipa_check_keytab(state->keytab, + ret = ipa_check_keytab(state->new_keytab, state->id_ctx->server_mode->kt_owner_uid, state->id_ctx->server_mode->kt_owner_gid); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_check_keytab failed: %d\n", ret); - tevent_req_error(req, ret); - return; + if (ret == EOK) { + ret = rename(state->new_keytab, state->keytab); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "rename failed [%d][%s].\n", ret, strerror(ret)); + tevent_req_error(req, ret); + return; + } + DEBUG(SSSDBG_TRACE_INTERNAL, "Keytab renamed to %s\n", state->keytab); + } else if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Trying to recover and use the previous keytab, if available\n"); + ret = ipa_check_keytab(state->keytab, + state->id_ctx->server_mode->kt_owner_uid, + state->id_ctx->server_mode->kt_owner_gid); + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, + "The previous keytab %s contains the expected principal\n", + state->keytab); + } else { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot use the old keytab: %d\n", ret); + /* Nothing we can do now */ + tevent_req_error(req, ret); + return; + } } + DEBUG(SSSDBG_TRACE_FUNC, + "Keytab %s contains the expected principals\n", state->new_keytab); + ret = ipa_server_trust_add_step(req); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, -- cgit