diff options
-rw-r--r-- | 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 c4d108fe..47ed5be8 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) { |