Compare commits

...

No commits in common. "c8" and "c9" have entirely different histories.
c8 ... c9

12 changed files with 1546 additions and 890 deletions

View File

@ -0,0 +1,50 @@
From 8bf31924265baf81372fe42580dee4064a642375 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 23 Jan 2024 09:28:26 +0100
Subject: [PATCH] sss-client: handle key value in destructor
When the pthread key destructor is called the key value is already set
to NULL by the caller. As a result the data stored in the value can only
be accessed by the first argument passed to the destructor and not by
pthread_getspecific() as the previous code did.
Resolves: https://github.com/SSSD/sssd/issues/7189
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
(cherry picked from commit b439847bc88ad7b89f0596af822c0ffbf2a579df)
---
src/sss_client/common.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 702d0597d..32555edf3 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -93,8 +93,22 @@ void sss_cli_close_socket(void)
#ifdef HAVE_PTHREAD_EXT
static void sss_at_thread_exit(void *v)
{
- sss_cli_close_socket();
+ /* At this point the key value is already set to NULL and the only way to
+ * access the data from the value is via the argument passed to the
+ * destructor (sss_at_thread_exit). See e.g.
+ * https://www.man7.org/linux/man-pages/man3/pthread_key_create.3p.html
+ * for details. */
+
+ struct sss_socket_descriptor_t *descriptor = (struct sss_socket_descriptor_t *) v;
+
+ if (descriptor->sd != -1) {
+ close(descriptor->sd);
+ descriptor->sd = -1;
+ }
+
free(v);
+
+ /* Most probably redudant, but better safe than sorry. */
pthread_setspecific(sss_sd_key, NULL);
}
--
2.42.0

View File

@ -0,0 +1,104 @@
From 23849f751315ea218e125f35cd419cce55d27355 Mon Sep 17 00:00:00 2001
From: Justin Stephenson <jstephen@redhat.com>
Date: Thu, 1 Feb 2024 14:22:09 -0500
Subject: [PATCH 6/7] krb5: Allow fallback between responder questions
Add support to try the next Preauth type when answering
krb5 questions. Fixes an issue when an IPA user has
both authtype passkey and authtype password set at
the same time.
Resolves: https://github.com/SSSD/sssd/issues/7152
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
(cherry picked from commit c9a333c5215b9ee6080038881a249c329141d0cf)
---
src/providers/krb5/krb5_child.c | 37 +++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index d3e3d859a..26b0090b4 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -784,11 +784,14 @@ static krb5_error_code answer_pkinit(krb5_context ctx,
"krb5_responder_set_answer failed.\n");
}
+ goto done;
+ } else {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected authentication token type [%s]\n",
+ sss_authtok_type_to_str(sss_authtok_get_type(kr->pd->authtok)));
+ kerr = EAGAIN;
goto done;
}
- kerr = EOK;
-
done:
krb5_responder_pkinit_challenge_free(ctx, rctx, chl);
@@ -914,9 +917,9 @@ static krb5_error_code answer_idp_oauth2(krb5_context kctx,
type = sss_authtok_get_type(kr->pd->authtok);
if (type != SSS_AUTHTOK_TYPE_OAUTH2) {
- DEBUG(SSSDBG_OP_FAILURE, "Unexpected authentication token type [%s]\n",
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected authentication token type [%s]\n",
sss_authtok_type_to_str(type));
- kerr = EINVAL;
+ kerr = EAGAIN;
goto done;
}
@@ -1141,9 +1144,9 @@ static krb5_error_code answer_passkey(krb5_context kctx,
type = sss_authtok_get_type(kr->pd->authtok);
if (type != SSS_AUTHTOK_TYPE_PASSKEY_REPLY) {
- DEBUG(SSSDBG_OP_FAILURE, "Unexpected authentication token type [%s]\n",
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected authentication token type [%s]\n",
sss_authtok_type_to_str(type));
- kerr = EINVAL;
+ kerr = EAGAIN;
goto done;
}
@@ -1244,17 +1247,33 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx,
return kerr;
}
+
+ kerr = EOK;
} else if (strcmp(question_list[c],
KRB5_RESPONDER_QUESTION_PKINIT) == 0
&& (sss_authtok_get_type(kr->pd->authtok)
== SSS_AUTHTOK_TYPE_SC_PIN
|| sss_authtok_get_type(kr->pd->authtok)
== SSS_AUTHTOK_TYPE_SC_KEYPAD)) {
- return answer_pkinit(ctx, kr, rctx);
+ kerr = answer_pkinit(ctx, kr, rctx);
} else if (strcmp(question_list[c], SSSD_IDP_OAUTH2_QUESTION) == 0) {
- return answer_idp_oauth2(ctx, kr, rctx);
+ kerr = answer_idp_oauth2(ctx, kr, rctx);
} else if (strcmp(question_list[c], SSSD_PASSKEY_QUESTION) == 0) {
- return answer_passkey(ctx, kr, rctx);
+ kerr = answer_passkey(ctx, kr, rctx);
+ } else {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Unknown question type [%s]\n", question_list[c]);
+ kerr = EINVAL;
+ }
+
+ /* Continue to the next question when the given authtype cannot be
+ * handled by the answer_* function. This allows fallback between auth
+ * types, such as passkey -> password. */
+ if (kerr == EAGAIN) {
+ DEBUG(SSSDBG_TRACE_ALL, "Auth type [%s] could not be handled by answer function, "
+ "continuing to next question.\n", question_list[c]);
+ continue;
+ } else {
+ return kerr;
}
}
}
--
2.42.0

View File

@ -0,0 +1,206 @@
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

View File

@ -0,0 +1,30 @@
From bebb150720620aae97dcae5c11e0b9bea0119b5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Wed, 13 Mar 2024 13:27:02 +0100
Subject: [PATCH] pam: fix invalid #if condition
ifdef should be used as anywhere else, otherwise we hit a build
error if sssd is being built without passkey.
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
(cherry picked from commit 603399a43d7bd0b8b6de3b512388b08abb9521ed)
---
src/responder/pam/pamsrv_cmd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index de408ced8..13ba13131 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1418,7 +1418,7 @@ void pam_reply(struct pam_auth_req *preq)
goto done;
}
-#if BUILD_PASSKEY
+#ifdef 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) {
--
2.42.0

View File

@ -0,0 +1,185 @@
From 5b9bc0a1a6116e6fb001c7dce7497854fcdd40c4 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 14 Mar 2024 09:18:45 +0100
Subject: [PATCH 09/12] krb5: add OTP to krb5 response selection
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Originally where there was only password and OTP authentication we
checked for password authentication and used OTP as a fallback. This was
continued as other (pre)-authentication types were added. But so far
only one authentication type was returned.
This changed recently to allow the user a better selection and as a
result OTP cannot be handled as a fallback anymore but has to be added
to the selection. In case there are no types (questions) available now
password is used as a fallback.
Resolves: https://github.com/SSSD/sssd/issues/7152
Reviewed-by: Alejandro López <allopez@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(cherry picked from commit bf6cb6dcdd94d9f47e4e74acd51e30f86b488943)
---
src/providers/krb5/krb5_child.c | 107 ++++++++++++++++++++++----------
1 file changed, 75 insertions(+), 32 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index b8acae7d7..116f2adda 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -1200,6 +1200,44 @@ done:
#endif /* BUILD_PASSKEY */
}
+static krb5_error_code answer_password(krb5_context kctx,
+ struct krb5_req *kr,
+ krb5_responder_context rctx)
+{
+ krb5_error_code kerr;
+ int ret;
+ const char *pwd;
+
+ kr->password_prompting = true;
+
+ if ((kr->pd->cmd == SSS_PAM_AUTHENTICATE
+ || kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM
+ || kr->pd->cmd == SSS_PAM_CHAUTHTOK)
+ && sss_authtok_get_type(kr->pd->authtok)
+ == SSS_AUTHTOK_TYPE_PASSWORD) {
+ ret = sss_authtok_get_password(kr->pd->authtok, &pwd, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sss_authtok_get_password failed.\n");
+ return ret;
+ }
+
+ kerr = krb5_responder_set_answer(kctx, rctx,
+ KRB5_RESPONDER_QUESTION_PASSWORD,
+ pwd);
+ if (kerr != 0) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "krb5_responder_set_answer failed.\n");
+ }
+
+ return kerr;
+ }
+
+ /* For SSS_PAM_PREAUTH and the other remaining commands the caller should
+ * continue to iterate over the available authentication methods. */
+ return EAGAIN;
+}
+
static krb5_error_code sss_krb5_responder(krb5_context ctx,
void *data,
krb5_responder_context rctx)
@@ -1207,9 +1245,7 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx,
struct krb5_req *kr = talloc_get_type(data, struct krb5_req);
const char * const *question_list;
size_t c;
- const char *pwd;
- int ret;
- krb5_error_code kerr;
+ krb5_error_code kerr = EINVAL;
if (kr == NULL) {
return EINVAL;
@@ -1221,34 +1257,18 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx,
for (c = 0; question_list[c] != NULL; c++) {
DEBUG(SSSDBG_TRACE_ALL, "Got question [%s].\n", question_list[c]);
+ /* It is expected that the answer_*() functions only return EOK
+ * (success) if the authentication was successful, i.e. during
+ * SSS_PAM_AUTHENTICATE. In all other cases, e.g. during
+ * SSS_PAM_PREAUTH either EAGAIN should be returned to indicate
+ * that the other available authentication methods should be
+ * checked as well. Or some other error code to indicate a fatal
+ * error where no other methods should be tried.
+ * Especially if setting the answer failed neither EOK nor EAGAIN
+ * should be returned. */
if (strcmp(question_list[c],
KRB5_RESPONDER_QUESTION_PASSWORD) == 0) {
- kr->password_prompting = true;
-
- if ((kr->pd->cmd == SSS_PAM_AUTHENTICATE
- || kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM
- || kr->pd->cmd == SSS_PAM_CHAUTHTOK)
- && sss_authtok_get_type(kr->pd->authtok)
- == SSS_AUTHTOK_TYPE_PASSWORD) {
- ret = sss_authtok_get_password(kr->pd->authtok, &pwd, NULL);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sss_authtok_get_password failed.\n");
- return ret;
- }
-
- kerr = krb5_responder_set_answer(ctx, rctx,
- KRB5_RESPONDER_QUESTION_PASSWORD,
- pwd);
- if (kerr != 0) {
- DEBUG(SSSDBG_OP_FAILURE,
- "krb5_responder_set_answer failed.\n");
- }
-
- return kerr;
- }
-
- kerr = EOK;
+ kerr = answer_password(ctx, kr, rctx);
} else if (strcmp(question_list[c],
KRB5_RESPONDER_QUESTION_PKINIT) == 0
&& (sss_authtok_get_type(kr->pd->authtok)
@@ -1265,6 +1285,8 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx,
continue;
}
kerr = answer_passkey(ctx, kr, rctx);
+ } else if (strcmp(question_list[c], KRB5_RESPONDER_QUESTION_OTP) == 0) {
+ kerr = answer_otp(ctx, kr, rctx);
} else {
DEBUG(SSSDBG_MINOR_FAILURE, "Unknown question type [%s]\n", question_list[c]);
kerr = EINVAL;
@@ -1274,16 +1296,37 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx,
* handled by the answer_* function. This allows fallback between auth
* types, such as passkey -> password. */
if (kerr == EAGAIN) {
- DEBUG(SSSDBG_TRACE_ALL, "Auth type [%s] could not be handled by answer function, "
- "continuing to next question.\n", question_list[c]);
+ /* During pre-auth iterating over all authentication methods
+ * is expected and no message will be displayed. */
+ if (kr->pd->cmd == SSS_PAM_AUTHENTICATE) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Auth type [%s] could not be handled by answer "
+ "function, continuing to next question.\n",
+ question_list[c]);
+ }
continue;
} else {
return kerr;
}
}
+ } else {
+ kerr = answer_password(ctx, kr, rctx);
}
- return answer_otp(ctx, kr, rctx);
+ /* During SSS_PAM_PREAUTH 'EAGAIN' is expected because we will run
+ * through all offered authentication methods and all are expect to return
+ * 'EAGAIN' in the positive case to indicate that the other methods should
+ * be checked as well. If all methods are checked we are done and should
+ * return success.
+ * In the other steps, especially SSS_PAM_AUTHENTICATE, having 'EAGAIN' at
+ * this stage would mean that no method feels responsible for the provided
+ * credentials i.e. authentication failed and we should return an error.
+ */
+ if (kr->pd->cmd == SSS_PAM_PREAUTH) {
+ return kerr == EAGAIN ? 0 : kerr;
+ } else {
+ return kerr;
+ }
}
#endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_RESPONDER */
--
2.42.0

View File

@ -0,0 +1,119 @@
From c3725a13ef694c2c34813953153f33ebfbaf1c27 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 15 Mar 2024 11:29:47 +0100
Subject: [PATCH 10/12] krb5: make sure answer_pkinit() use matching debug
messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolves: https://github.com/SSSD/sssd/issues/7152
Reviewed-by: Alejandro López <allopez@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(cherry picked from commit 7c33f9d57cebfff80778f930ff0cc3144a7cc261)
---
src/providers/krb5/krb5_child.c | 77 ++++++++++++++++++---------------
1 file changed, 42 insertions(+), 35 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 116f2adda..926109588 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -745,51 +745,58 @@ static krb5_error_code answer_pkinit(krb5_context ctx,
DEBUG(SSSDBG_TRACE_ALL, "Setting pkinit_prompting.\n");
kr->pkinit_prompting = true;
- if (kr->pd->cmd == SSS_PAM_AUTHENTICATE
- && (sss_authtok_get_type(kr->pd->authtok)
+ if (kr->pd->cmd == SSS_PAM_AUTHENTICATE) {
+ if ((sss_authtok_get_type(kr->pd->authtok)
== SSS_AUTHTOK_TYPE_SC_PIN
|| sss_authtok_get_type(kr->pd->authtok)
== SSS_AUTHTOK_TYPE_SC_KEYPAD)) {
- kerr = sss_authtok_get_sc(kr->pd->authtok, &pin, NULL,
- &token_name, NULL,
- &module_name, NULL,
- NULL, NULL, NULL, NULL);
- if (kerr != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sss_authtok_get_sc failed.\n");
- goto done;
- }
+ kerr = sss_authtok_get_sc(kr->pd->authtok, &pin, NULL,
+ &token_name, NULL,
+ &module_name, NULL,
+ NULL, NULL, NULL, NULL);
+ if (kerr != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "sss_authtok_get_sc failed.\n");
+ goto done;
+ }
- for (c = 0; chl->identities[c] != NULL; c++) {
- if (chl->identities[c]->identity != NULL
- && pkinit_identity_matches(chl->identities[c]->identity,
- token_name, module_name)) {
- break;
+ for (c = 0; chl->identities[c] != NULL; c++) {
+ if (chl->identities[c]->identity != NULL
+ && pkinit_identity_matches(chl->identities[c]->identity,
+ token_name, module_name)) {
+ break;
+ }
}
- }
- if (chl->identities[c] == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "No matching identity for [%s][%s] found in pkinit challenge.\n",
- token_name, module_name);
- kerr = EINVAL;
- goto done;
- }
+ if (chl->identities[c] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "No matching identity for [%s][%s] found in pkinit "
+ "challenge.\n", token_name, module_name);
+ kerr = EINVAL;
+ goto done;
+ }
- kerr = krb5_responder_pkinit_set_answer(ctx, rctx,
- chl->identities[c]->identity,
- pin);
- if (kerr != 0) {
- DEBUG(SSSDBG_OP_FAILURE,
- "krb5_responder_set_answer failed.\n");
- }
+ kerr = krb5_responder_pkinit_set_answer(ctx, rctx,
+ chl->identities[c]->identity,
+ pin);
+ if (kerr != 0) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "krb5_responder_set_answer failed.\n");
+ }
- goto done;
+ goto done;
+ } else {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Unexpected authentication token type [%s]\n",
+ sss_authtok_type_to_str(sss_authtok_get_type(kr->pd->authtok)));
+ kerr = EAGAIN;
+ goto done;
+ }
} else {
- DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected authentication token type [%s]\n",
- sss_authtok_type_to_str(sss_authtok_get_type(kr->pd->authtok)));
+ /* We only expect SSS_PAM_PREAUTH here, but also for all other
+ * commands the graceful solution would be to let the caller
+ * check other authentication methods as well. */
kerr = EAGAIN;
- goto done;
}
done:
--
2.42.0

View File

@ -0,0 +1,67 @@
From 87b54bd8448760241e7071a585f95b3e2604355a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 15 Mar 2024 12:35:00 +0100
Subject: [PATCH 11/12] krb5: make prompter and pre-auth debug message less
irritating
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolves: https://github.com/SSSD/sssd/issues/7152
Reviewed-by: Alejandro López <allopez@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(cherry picked from commit e26cc69341bcfd2bbc758eca30df296431c70a28)
---
src/providers/krb5/krb5_child.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 926109588..494711de9 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -1355,13 +1355,14 @@ static krb5_error_code sss_krb5_prompter(krb5_context context, void *data,
int ret;
size_t c;
struct krb5_req *kr = talloc_get_type(data, struct krb5_req);
+ const char *err_msg;
if (kr == NULL) {
return EINVAL;
}
DEBUG(SSSDBG_TRACE_ALL,
- "sss_krb5_prompter name [%s] banner [%s] num_prompts [%d] EINVAL.\n",
+ "sss_krb5_prompter name [%s] banner [%s] num_prompts [%d].\n",
name, banner, num_prompts);
if (num_prompts != 0) {
@@ -1370,7 +1371,12 @@ static krb5_error_code sss_krb5_prompter(krb5_context context, void *data,
prompts[c].prompt);
}
- DEBUG(SSSDBG_FUNC_DATA, "Prompter interface isn't used for password prompts by SSSD.\n");
+ err_msg = krb5_get_error_message(context, KRB5_LIBOS_CANTREADPWD);
+ DEBUG(SSSDBG_FUNC_DATA,
+ "Prompter interface isn't used for prompting by SSSD."
+ "Returning the expected error [%ld/%s].\n",
+ KRB5_LIBOS_CANTREADPWD, err_msg);
+ krb5_free_error_message(context, err_msg);
return KRB5_LIBOS_CANTREADPWD;
}
@@ -2839,8 +2845,9 @@ static errno_t tgt_req_child(struct krb5_req *kr)
* should now know which authentication methods are available to
* update the password. */
DEBUG(SSSDBG_TRACE_FUNC,
- "krb5_get_init_creds_password returned [%d] during pre-auth, "
- "ignored.\n", kerr);
+ "krb5_get_init_creds_password returned [%d] while collecting "
+ "available authentication types, errors are expected "
+ "and ignored.\n", kerr);
ret = pam_add_prompting(kr);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_prompting failed.\n");
--
2.42.0

View File

@ -0,0 +1,70 @@
From d06b4a3eda612d1a54b6bdb3c3b779543bc23b0f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 20 Mar 2024 11:26:16 +0100
Subject: [PATCH 12/12] pam_sss: prefer Smartcard authentication
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The current behavior is that Smartcard authentication is preferred if
possible, i.e. if a Smartcard is present. Since the Smartcard (or
equivalent) must be inserted manually the assumption is that if the user
has inserted it they most probably want to use it for authentication.
With the latest patches pam_sss might receive multiple available
authentication methods. With this patch the checks for available
authentication types start Smartcard authentication to mimic the
existing behavior.
Resolves: https://github.com/SSSD/sssd/issues/7152
Reviewed-by: Alejandro López <allopez@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(cherry picked from commit 0d5e8f11714e8e6cc0ad28e03fecf0f5732528b3)
---
src/sss_client/pam_sss.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index a1c353604..41a528dda 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -2544,17 +2544,7 @@ static int get_authtok_for_authentication(pam_handle_t *pamh,
} else if (pi->pc != NULL) {
ret = prompt_by_config(pamh, pi);
} else {
- if (flags & PAM_CLI_FLAGS_USE_2FA
- || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
- && pi->otp_challenge != NULL)) {
- if (pi->password_prompting) {
- ret = prompt_2fa(pamh, pi, _("First Factor: "),
- _("Second Factor (optional): "));
- } else {
- ret = prompt_2fa(pamh, pi, _("First Factor: "),
- _("Second Factor: "));
- }
- } else if (pi->cert_list != NULL) {
+ if (pi->cert_list != NULL) {
if (pi->cert_list->next == NULL) {
/* Only one certificate */
pi->selected_cert = pi->cert_list;
@@ -2570,6 +2560,16 @@ static int get_authtok_for_authentication(pam_handle_t *pamh,
|| (pi->flags & PAM_CLI_FLAGS_REQUIRE_CERT_AUTH)) {
/* Use pin prompt as fallback for gdm-smartcard */
ret = prompt_sc_pin(pamh, pi);
+ } else if (flags & PAM_CLI_FLAGS_USE_2FA
+ || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
+ && pi->otp_challenge != NULL)) {
+ if (pi->password_prompting) {
+ ret = prompt_2fa(pamh, pi, _("First Factor: "),
+ _("Second Factor (optional): "));
+ } else {
+ ret = prompt_2fa(pamh, pi, _("First Factor: "),
+ _("Second Factor: "));
+ }
} else if (pi->passkey_prompt_pin) {
ret = prompt_passkey(pamh, pi,
_("Insert your passkey device, then press ENTER."),
--
2.42.0

View File

@ -0,0 +1,57 @@
From 163db8465e815984abac0ba9af097589045791da Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 22 Mar 2024 19:53:29 +0100
Subject: [PATCH] pam: fix storing auth types for offline auth
Before the recent patches which allow krb5_child to iterate over all
available authentication methods typically only one method was returned.
E.g. is Smartcard authentication (pkinit) was possible it was typically
the first method the in question list and the result of the
answer_pkinit() function was immediately returned. As a result only the
Smartcard authentication type was set and a missing password
authentication type while others were present might have been a
reasonable indicator for the online state.
With the recent patches, all available methods, including password
authentication if available, are return and a new indicator is needed.
---
src/responder/pam/pamsrv.h | 1 +
src/responder/pam/pamsrv_cmd.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
index 618836189..2aa14ae02 100644
--- a/src/responder/pam/pamsrv.h
+++ b/src/responder/pam/pamsrv.h
@@ -114,6 +114,7 @@ struct pam_resp_auth_type {
bool otp_auth;
bool cert_auth;
bool passkey_auth;
+ bool backend_returned_no_auth_type;
};
struct sss_cmd_table *get_pam_cmds(void);
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 13ba13131..94895d48e 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -915,6 +915,7 @@ errno_t pam_get_auth_types(struct pam_data *pd,
/* If the backend cannot determine which authentication types are
* available the default would be to prompt for a password. */
types.password_auth = true;
+ types.backend_returned_no_auth_type = true;
}
DEBUG(SSSDBG_TRACE_ALL, "Authentication types for user [%s] and service "
@@ -1002,7 +1003,7 @@ static errno_t pam_eval_local_auth_policy(TALLOC_CTX *mem_ctx,
}
/* Store the local auth types, in case we go offline */
- if (!auth_types.password_auth) {
+ if (!auth_types.backend_returned_no_auth_type) {
ret = set_local_auth_type(preq, sc_allow, passkey_allow);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
--
2.42.0

View File

@ -0,0 +1,49 @@
From a453f9625b40a0a1fbcf055ffa196121f2b248b5 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Date: Wed, 24 Jan 2024 23:03:04 +0100
Subject: [PATCH] tests: Drop -extensions from openssl command if there is no
-x509
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The 'openssl req' ignores the '-extensions' option without '-x509'.
OpenSSL versions prior 3.2 simply ignored it. Starting with version 3.2
an error is generated:
| /usr/bin/openssl req -batch -config
| ../../../../../src/tests/test_CA/intermediate_CA/SSSD_test_intermediate_CA.config
| -new -nodes -key
| …/build/../src/tests/test_CA/intermediate_CA/SSSD_test_intermediate_CA_key.pem
-sha256 -extensions v3_ca -out SSSD_test_intermediate_CA_req.pem
| Error adding request extensions from section v3_ca
| 003163BAB27F0000:error:11000079:X509 V3 routines:v2i_AUTHORITY_KEYID:no issuer certificate:../crypto/x509/v3_akid.c:156:
| 003163BAB27F0000:error:11000080:X509 V3 routines:X509V3_EXT_nconf_int:error in extension:../crypto/x509/v3_conf.c:48:section=v3_ca, name=authorityKeyIdentifier, value=keyid:always,issuer:always
|
Remove the '-extensions' option.
Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit 32b72c7c3303edb2bf55ae9a22e8db7855f3d7d1)
---
src/tests/test_CA/intermediate_CA/Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tests/test_CA/intermediate_CA/Makefile.am b/src/tests/test_CA/intermediate_CA/Makefile.am
index b439f82cb..50fcddb8d 100644
--- a/src/tests/test_CA/intermediate_CA/Makefile.am
+++ b/src/tests/test_CA/intermediate_CA/Makefile.am
@@ -33,7 +33,7 @@ SSSD_test_CA.pem:
ln -s $(builddir)/../$@
SSSD_test_intermediate_CA_req.pem: $(openssl_intermediate_ca_key) $(openssl_intermediate_ca_config) SSSD_test_CA.pem
- $(OPENSSL) req -batch -config ${openssl_intermediate_ca_config} -new -nodes -key $< -sha256 -extensions v3_ca -out $@
+ $(OPENSSL) req -batch -config ${openssl_intermediate_ca_config} -new -nodes -key $< -sha256 -out $@
SSSD_test_intermediate_CA.pem: SSSD_test_intermediate_CA_req.pem $(openssl_root_ca_config) $(openssl_root_ca_key)
cd .. && $(OPENSSL) ca -config ${openssl_root_ca_config} -batch -notext -keyfile $(openssl_root_ca_key) -in $(abs_builddir)/$< -days 200 -extensions v3_intermediate_ca -out $(abs_builddir)/$@
--
2.44.0

File diff suppressed because it is too large Load Diff