sssd/SOURCES/0007-krb5-Add-fallback-pass...

207 lines
7.8 KiB
Diff

From 8d9ae754b50dffafef719ad3fa44e5dd1dde47b3 Mon Sep 17 00:00:00 2001
From: Justin Stephenson <jstephen@redhat.com>
Date: Fri, 1 Mar 2024 14:31:25 -0500
Subject: [PATCH 7/7] krb5: Add fallback password change support
handle password changes for IPA users with multiple auth types set
(passkey, password)
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
(cherry picked from commit 6c1272edf174eb4bdf236dc1ffd4287b71a43392)
---
src/krb5_plugin/passkey/passkey_clpreauth.c | 5 ++
src/providers/ipa/ipa_auth.c | 13 +++++
src/providers/krb5/krb5_auth.c | 12 +++++
src/providers/krb5/krb5_auth.h | 3 ++
src/providers/krb5/krb5_child.c | 5 ++
src/providers/krb5/krb5_child_handler.c | 53 +++++++++++++++++++++
src/responder/pam/pamsrv_cmd.c | 10 ++++
7 files changed, 101 insertions(+)
diff --git a/src/krb5_plugin/passkey/passkey_clpreauth.c b/src/krb5_plugin/passkey/passkey_clpreauth.c
index d2dfe6fe1..35b6a3fed 100644
--- a/src/krb5_plugin/passkey/passkey_clpreauth.c
+++ b/src/krb5_plugin/passkey/passkey_clpreauth.c
@@ -279,6 +279,11 @@ sss_passkeycl_process(krb5_context context,
goto done;
}
+ if (prompter == NULL) {
+ ret = EINVAL;
+ goto done;
+ }
+
/* Get FAST armor key. */
as_key = cb->fast_armor(context, rock);
if (as_key == NULL) {
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
index 1d61a1052..e5e1bf30c 100644
--- a/src/providers/ipa/ipa_auth.c
+++ b/src/providers/ipa/ipa_auth.c
@@ -258,6 +258,19 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq)
if (dp_err != DP_ERR_OK) {
goto done;
}
+ if (state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM
+ && state->pd->pam_status == PAM_TRY_AGAIN) {
+ /* Reset this to fork a new krb5_child in handle_child_send() */
+ state->pd->child_pid = 0;
+ subreq = krb5_auth_queue_send(state, state->ev, state->be_ctx, state->pd,
+ state->auth_ctx->krb5_auth_ctx);
+ if (subreq == NULL) {
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ipa_pam_auth_handler_retry_done, req);
+ return;
+ }
if (state->pd->cmd == SSS_PAM_AUTHENTICATE
&& state->pd->pam_status == PAM_CRED_ERR
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index be34880b4..e34943b82 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -532,6 +532,18 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
ret = EOK;
goto done;
}
+
+ /* If krb5_child is still running from SSS_PAM_PREAUTH,
+ * terminate the waiting krb5_child and send the
+ * CHAUTHTOK_PRELIM request again */
+ if (pd->child_pid != 0) {
+ soft_terminate_krb5_child(state, pd, krb5_ctx);
+ state->pam_status = PAM_TRY_AGAIN;
+ state->dp_err = DP_ERR_OK;
+ ret = EOK;
+ goto done;
+ }
+
break;
case SSS_CMD_RENEW:
if (authtok_type != SSS_AUTHTOK_TYPE_CCFILE) {
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index bbdbf61fc..783292bc0 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -135,6 +135,9 @@ errno_t init_renew_tgt(struct krb5_ctx *krb5_ctx, struct be_ctx *be_ctx,
errno_t add_tgt_to_renew_table(struct krb5_ctx *krb5_ctx, const char *ccfile,
struct tgt_times *tgtt, struct pam_data *pd,
const char *upn);
+errno_t soft_terminate_krb5_child(TALLOC_CTX *mem_ctx,
+ struct pam_data *pd,
+ struct krb5_ctx *krb5_ctx);
/* krb5_access.c */
struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx,
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 26b0090b4..b8acae7d7 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -1259,6 +1259,11 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx,
} else if (strcmp(question_list[c], SSSD_IDP_OAUTH2_QUESTION) == 0) {
kerr = answer_idp_oauth2(ctx, kr, rctx);
} else if (strcmp(question_list[c], SSSD_PASSKEY_QUESTION) == 0) {
+ /* Skip answer_passkey for expired password changes, e.g. user with auth types
+ * passkey AND password set */
+ if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM || kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
+ continue;
+ }
kerr = answer_passkey(ctx, kr, rctx);
} else {
DEBUG(SSSDBG_MINOR_FAILURE, "Unknown question type [%s]\n", question_list[c]);
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
index 54088e4d6..cab84b37d 100644
--- a/src/providers/krb5/krb5_child_handler.c
+++ b/src/providers/krb5/krb5_child_handler.c
@@ -1020,3 +1020,56 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len,
*_res = res;
return EOK;
}
+
+/* Closes the write end of waiting krb5_child */
+errno_t soft_terminate_krb5_child(TALLOC_CTX *mem_ctx,
+ struct pam_data *pd,
+ struct krb5_ctx *krb5_ctx)
+{
+ char *io_key;
+ struct child_io_fds *io;
+ TALLOC_CTX *tmp_ctx;
+ int ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ if (pd->child_pid == 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Expected waiting krb5_child.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ io_key = talloc_asprintf(tmp_ctx, "%d", pd->child_pid);
+ if (io_key == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ io = sss_ptr_hash_lookup(krb5_ctx->io_table, io_key,
+ struct child_io_fds);
+ if (io == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "PTR hash lookup failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (io->write_to_child_fd != -1) {
+ ret = close(io->write_to_child_fd);
+ io->write_to_child_fd = -1;
+ if (ret != EOK) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "close failed [%d][%s].\n", ret, strerror(ret));
+ }
+ }
+
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index a7c181733..de408ced8 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1418,6 +1418,15 @@ void pam_reply(struct pam_auth_req *preq)
goto done;
}
+#if BUILD_PASSKEY
+ if(pd->cmd == SSS_PAM_AUTHENTICATE &&
+ pd->pam_status == PAM_NEW_AUTHTOK_REQD &&
+ sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_PASSKEY_REPLY) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Passkey authentication reply, ignoring "
+ "new authtok required status\n");
+ pd->pam_status = PAM_SUCCESS;
+ }
+
/* Passkey auth user notification if no TGT is granted */
if (pd->cmd == SSS_PAM_AUTHENTICATE &&
pd->pam_status == PAM_SUCCESS &&
@@ -1429,6 +1438,7 @@ void pam_reply(struct pam_auth_req *preq)
"User [%s] logged in with local passkey authentication, single "
"sign on ticket is not obtained.\n", pd->user);
}
+#endif /* BUILD_PASSKEY */
/* Account expiration warning is printed for sshd. If pam_verbosity
* is equal or above PAM_VERBOSITY_INFO then all services are informed
--
2.42.0