From 37da1e7cf4dbe91b166095e9c96a90a64a7a64f3 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 25 May 2010 13:59:41 +0200 Subject: [PATCH 2/2] Fix handling of ccache file when going offline The ccache file was removed too early if system is offline but the backend was not already marked offline. Now we remove the ccache file only if the successfully got a new one and it is not the same as the old one. --- src/providers/krb5/krb5_auth.c | 107 ++++++++++++++++++++++++++++------------ src/providers/krb5/krb5_auth.h | 1 + 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index a7aebe5..d43bb02 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -45,6 +45,49 @@ #define KRB5_CHILD SSSD_LIBEXEC_PATH"/krb5_child" #endif +static errno_t safe_remove_old_ccache_file(const char *old_ccache_file, + const char *new_ccache_file) +{ + int ret; + size_t old_offset = 0; + size_t new_offset = 0; + + if (new_ccache_file == NULL) { + DEBUG(1, ("Missing new ccache file, " + "old ccache file is not deleted.\n")); + return EINVAL; + } + + if (old_ccache_file != NULL) { + if (strncmp(old_ccache_file, "FILE:", 5) == 0) { + old_offset = 5; + } + if (strncmp(new_ccache_file, "FILE:", 5) == 0) { + new_offset = 5; + } + if (strcmp(old_ccache_file + old_offset, + new_ccache_file + new_offset) == 0) { + DEBUG(7, ("New and old ccache file are the same, " + "no one will be deleted.\n")); + return EOK; + } + if (old_ccache_file[old_offset] != '/') { + DEBUG(1, ("Ccache file name [%s] is not an absolute path.\n", + old_ccache_file + old_offset)); + return EINVAL; + } + ret = unlink(old_ccache_file + old_offset); + if (ret == -1 && errno != ENOENT) { + ret = errno; + DEBUG(1, ("unlink [%s] failed [%d][%s].\n", old_ccache_file, ret, + strerror(ret))); + return ret; + } + } + + return EOK; +} + static errno_t check_if_ccache_file_is_used(uid_t uid, const char *ccname, bool *result) { @@ -734,7 +777,18 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, ccache_file ? ccache_file : "not set", kr->active_ccache_present ? "" : "not", kr->valid_tgt_present ? "" : "not")); - kr->ccname = ccache_file; + if (ccache_file != NULL) { + kr->ccname = ccache_file; + kr->old_ccname = talloc_strdup(kr, ccache_file); + if (kr->old_ccname == NULL) { + DEBUG(1, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + } else { + kr->ccname = NULL; + kr->old_ccname = NULL; + } break; default: @@ -837,44 +891,29 @@ static void krb5_find_ccache_step(struct tevent_req *req) struct krb5child_req *kr = state->kr; struct pam_data *pd = kr->pd; char *msg; - size_t offset = 0; bool private_path = false; struct tevent_req *subreq = NULL; + if (!kr->is_offline) { + kr->is_offline = be_is_offline(state->be_ctx); + } + /* The ccache file should be (re)created if one of the following conditions * is true: * - it doesn't exist (kr->ccname == NULL) * - the backend is online and the current ccache file is not used, i.e * the related user is currently not logged in - * (!be_is_offline(state->be_ctx) && !kr->active_ccache_present) + * (!kr->is_offline && !kr->active_ccache_present) * - the backend is offline and the current cache file not used and * it does not contain a valid tgt - * (be_is_offline(state->be_ctx) && + * (kr->is_offline && * !kr->active_ccache_present && !kr->valid_tgt_present) */ if (kr->ccname == NULL || - (be_is_offline(state->be_ctx) && !kr->active_ccache_present && + (kr->is_offline && !kr->active_ccache_present && !kr->valid_tgt_present) || - (!be_is_offline(state->be_ctx) && !kr->active_ccache_present)) { + (!kr->is_offline && !kr->active_ccache_present)) { DEBUG(9, ("Recreating ccache file.\n")); - if (kr->ccname != NULL) { - if (strncmp(kr->ccname, "FILE:", 5) == 0) { - offset = 5; - } - if (kr->ccname[offset] != '/') { - DEBUG(1, ("Ccache file name [%s] is not an absolute path.\n", - kr->ccname + offset)); - ret = EINVAL; - goto done; - } - ret = unlink(kr->ccname + offset); - if (ret == -1 && errno != ENOENT) { - ret = errno; - DEBUG(1, ("unlink [%s] failed [%d][%s].\n", kr->ccname, ret, - strerror(ret))); - goto done; - } - } kr->ccname = expand_ccname_template(kr, kr, dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL), @@ -894,13 +933,13 @@ static void krb5_find_ccache_step(struct tevent_req *req) } } - if (be_is_offline(state->be_ctx)) { + if (kr->is_offline) { DEBUG(9, ("Preparing for offline operation.\n")); - kr->is_offline = true; if (kr->valid_tgt_present || kr->active_ccache_present) { DEBUG(9, ("Valid TGT available or " "ccache file is already in use.\n")); + kr->ccname = kr->old_ccname; msg = talloc_asprintf(pd, "%s=%s", CCACHE_ENV_NAME, kr->ccname); if (msg == NULL) { DEBUG(1, ("talloc_asprintf failed.\n")); @@ -1094,19 +1133,23 @@ static void krb5_child_done(struct tevent_req *subreq) fo_set_port_status(kr->srv, PORT_WORKING); } - /* The following cases are left now: - * - offline (msg_status == PAM_AUTHINFO_UNAVAIL or - * msg_status == PAM_AUTHTOK_LOCK_BUSY) - * - successful authentication or password change + /* Now only a successful authentication or password change is left. * - * For all these cases we expect that one of the messages for the - * received buffer contains the name of the credential cache file. */ + * We expect that one of the messages in the received buffer contains + * the name of the credential cache file. */ if (kr->ccname == NULL) { DEBUG(1, ("Missing ccache name in child response.\n")); ret = EINVAL; goto done; } + if (kr->old_ccname != NULL) { + ret = safe_remove_old_ccache_file(kr->old_ccname, kr->ccname); + if (ret != EOK) { + DEBUG(1, ("Failed to remove old ccache file [%s], please remove it manually.\n")); + } + } + struct sysdb_attrs *attrs; attrs = sysdb_new_attrs(state); ret = sysdb_attrs_add_string(attrs, SYSDB_CCACHE_FILE, kr->ccname); diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h index 61b8071..ec54f73 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -50,6 +50,7 @@ struct krb5child_req { struct tevent_timer *timeout_handler; const char *ccname; + const char *old_ccname; const char *homedir; const char *upn; uid_t uid; -- 1.6.6.1