From 674cccd352f2d7130e80ea80cce572149d206d11 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Mon, 10 Nov 2025 16:03:44 -0500 Subject: [PATCH 1/5] authtok: Set Kerberos passkey PIN to NULL when UV is false MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Iker Pedrosa Reviewed-by: Tomáš Halman (cherry picked from commit be5df34126b3755cd63f829a885b68cb93fb6fa6) --- src/util/authtok-utils.c | 6 +----- src/util/authtok.c | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/util/authtok-utils.c b/src/util/authtok-utils.c index ac3c8bb6631..f6b205e25b6 100644 --- a/src/util/authtok-utils.c +++ b/src/util/authtok-utils.c @@ -122,12 +122,8 @@ errno_t sss_auth_pack_passkey_blob(uint8_t *buf, /* Add provided PIN */ if (pin != NULL) { pin_len = strlen(pin) + 1; - /* User verification is false */ - } else { - pin = ""; - pin_len = 0; + memcpy(buf + len, pin, pin_len); } - memcpy(buf + len, pin, pin_len); return EOK; } diff --git a/src/util/authtok.c b/src/util/authtok.c index c6b6f85d2dc..df64ede57e3 100644 --- a/src/util/authtok.c +++ b/src/util/authtok.c @@ -716,12 +716,16 @@ errno_t sss_auth_unpack_passkey_blob(TALLOC_CTX *mem_ctx, } len += strlen(key) + 1; - pin = talloc_strdup(mem_ctx, (const char *) blob + len); - if (pin == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup pin failed.\n"); - talloc_free(prompt); - talloc_free(key); - return ENOMEM; + if ((strcasecmp(prompt, "true") == 0)) { + pin = talloc_strdup(mem_ctx, (const char *) blob + len); + if (pin == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup pin failed.\n"); + talloc_free(prompt); + talloc_free(key); + return ENOMEM; + } + } else { + pin = NULL; } *_prompt = prompt; @@ -842,7 +846,9 @@ errno_t sss_authtok_get_passkey(TALLOC_CTX *mem_ctx, goto done; } - pin_len = strlen(pin); + if (pin != NULL) { + pin_len = strlen(pin); + } *_prompt = prompt; *_key = key; From 1500c4fd13fafed97b8173e9a4a6d80299d7674e Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 5 Nov 2025 14:07:03 -0500 Subject: [PATCH 2/5] passkey: Remove SYSDB_PASSKEY_USER_VERIFICATION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove SYSDB_PASSKEY_USER_VERIFICATION and related functions. In phase 1 of passkey implementation we read passkey user verification from IPA LDAP tree, however now user verification is sent to the SSSD krb5 plugin from ipa-otpd. Reviewed-by: Iker Pedrosa Reviewed-by: Tomáš Halman (cherry picked from commit 879d073155cd73d9a0507fc59f8ab16d2f0b37bd) --- Makefile.am | 10 - src/db/sysdb.h | 1 - src/db/sysdb_passkey_user_verification.c | 236 --------------------- src/db/sysdb_passkey_user_verification.h | 49 ----- src/providers/ipa/ipa_subdomains.c | 41 ---- src/providers/ipa/ipa_subdomains_passkey.c | 148 ------------- src/providers/ipa/ipa_subdomains_passkey.h | 45 ---- src/responder/pam/pamsrv_passkey.c | 53 ++--- src/tests/cmocka/test_pam_srv.c | 33 --- 9 files changed, 15 insertions(+), 601 deletions(-) delete mode 100644 src/db/sysdb_passkey_user_verification.c delete mode 100644 src/db/sysdb_passkey_user_verification.h delete mode 100644 src/providers/ipa/ipa_subdomains_passkey.c delete mode 100644 src/providers/ipa/ipa_subdomains_passkey.h diff --git a/Makefile.am b/Makefile.am index a50e5eb1a7d..abc371f1293 100644 --- a/Makefile.am +++ b/Makefile.am @@ -807,7 +807,6 @@ dist_noinst_HEADERS = \ src/db/sysdb_ssh.h \ src/db/sysdb_subid.h \ src/db/sysdb_domain_resolution_order.h \ - src/db/sysdb_passkey_user_verification.h \ src/db/sysdb_iphosts.h \ src/db/sysdb_ipnetworks.h \ src/confdb/confdb.h \ @@ -866,7 +865,6 @@ dist_noinst_HEADERS = \ src/providers/ipa/ipa_auth.h \ src/providers/ipa/ipa_dyndns.h \ src/providers/ipa/ipa_subdomains.h \ - src/providers/ipa/ipa_subdomains_passkey.h \ src/providers/ipa/ipa_id.h \ src/providers/ipa/ipa_opts.h \ src/providers/ipa/ipa_srv.h \ @@ -1317,9 +1315,6 @@ endif if BUILD_SYSTEMTAP libsss_util_la_LIBADD += stap_generated_probes.lo endif -if BUILD_PASSKEY -libsss_util_la_SOURCES += src/db/sysdb_passkey_user_verification.c -endif # BUILD_PASSKEY libsss_util_la_LDFLAGS = -avoid-version pkglib_LTLIBRARIES += libsss_semanage.la @@ -4602,11 +4597,6 @@ if BUILD_SSH libsss_ipa_la_SOURCES += src/providers/ipa/ipa_hostid.c endif -if BUILD_PASSKEY -libsss_ipa_la_SOURCES += \ - src/providers/ipa/ipa_subdomains_passkey.c -endif # BUILD_PASSKEY - libsss_ad_la_SOURCES = \ src/providers/ad/ad_opts.c \ src/providers/ad/ad_common.c \ diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 0f397fc1dc5..a049460f0ee 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -216,7 +216,6 @@ #define SYSDB_DOMAIN_RESOLUTION_ORDER "domainResolutionOrder" #define SYSDB_DOMAIN_TEMPLATE_SHELL "templateLoginShell" #define SYSDB_DOMAIN_TEMPLATE_HOMEDIR "templateHomeDirectory" -#define SYSDB_PASSKEY_USER_VERIFICATION "passkeyUserVerification" #define SYSDB_SESSION_RECORDING "sessionRecording" #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)" diff --git a/src/db/sysdb_passkey_user_verification.c b/src/db/sysdb_passkey_user_verification.c deleted file mode 100644 index 428225b75a1..00000000000 --- a/src/db/sysdb_passkey_user_verification.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - Authors: - Justin Stephenson - - Copyright (C) 2022 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include "db/sysdb.h" -#include "db/sysdb_private.h" - -static errno_t -sysdb_get_passkey_user_verification_string_attr(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - struct ldb_dn *dn, - const char **_attr) -{ - TALLOC_CTX *tmp_ctx; - struct ldb_result *res; - const char *attr; - const char *attrs[] = { SYSDB_PASSKEY_USER_VERIFICATION, NULL }; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - return ENOMEM; - } - - ret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, - NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - if (res->count > 1) { - DEBUG(SSSDBG_OP_FAILURE, - "Base search returned [%d] results, expected 1.\n", res->count); - ret = EINVAL; - goto done; - } else if (res->count == 0) { - ret = ENOENT; - goto done; - } else { - /* res->count == 1 */ - attr = ldb_msg_find_attr_as_string(res->msgs[0], - SYSDB_PASSKEY_USER_VERIFICATION, - NULL); - if (attr == NULL) { - ret = ENOENT; - goto done; - } - } - - *_attr = talloc_steal(mem_ctx, attr); - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} - -errno_t -sysdb_get_passkey_user_verification(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - struct ldb_dn *dn, - const char **_passkey_user_verification) -{ - TALLOC_CTX *tmp_ctx; - const char *passkey_user_verification = NULL; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - return ENOMEM; - } - - ret = sysdb_get_passkey_user_verification_string_attr( - tmp_ctx, sysdb, dn, &passkey_user_verification); - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_get_passkey_user_verification_string_attr() failed " - "[%d]: [%s]", - ret, sss_strerror(ret)); - goto done; - } else if (ret == ENOENT) { - *_passkey_user_verification = NULL; - goto done; - } else { - /* ret == EOK */ - *_passkey_user_verification = talloc_steal(mem_ctx, - passkey_user_verification); - } - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} - -errno_t -sysdb_update_passkey_user_verification(struct sysdb_ctx *sysdb, - struct ldb_dn *dn, - const char *passkey_user_verification) -{ - TALLOC_CTX *tmp_ctx; - struct ldb_message *msg; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - return ENOMEM; - } - - msg = ldb_msg_new(tmp_ctx); - if (msg == NULL) { - ret = ENOMEM; - goto done; - } - - msg->dn = dn; - - ret = ldb_msg_add_empty(msg, SYSDB_PASSKEY_USER_VERIFICATION, - LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - if (passkey_user_verification != NULL) { - ret = ldb_msg_add_string(msg, SYSDB_PASSKEY_USER_VERIFICATION, - passkey_user_verification); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - } - - ret = ldb_modify(sysdb->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(SSSDBG_OP_FAILURE, - "ldb_modify()_failed: [%s][%d][%s]\n", - ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)); - ret = sysdb_error_to_errno(ret); - goto done; - } - - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} - -errno_t -sysdb_domain_get_passkey_user_verification(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - const char *domain_name, - const char **_user_verification) -{ - TALLOC_CTX *tmp_ctx; - struct ldb_dn *dn; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - return ENOMEM; - } - - dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, domain_name); - if (dn == NULL) { - ret = ENOMEM; - goto done; - } - - ret = sysdb_get_passkey_user_verification(mem_ctx, sysdb, dn, - _user_verification); - -done: - talloc_free(tmp_ctx); - return ret; -} - -errno_t -sysdb_domain_update_passkey_user_verification(struct sysdb_ctx *sysdb, - const char *domain_name, - const char *user_verification) -{ - - TALLOC_CTX *tmp_ctx; - struct ldb_dn *dn; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - return ENOMEM; - } - - dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_DOM_BASE, domain_name); - if (dn == NULL) { - ret = ENOMEM; - goto done; - } - - ret = sysdb_update_passkey_user_verification(sysdb, dn, - user_verification); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_update_passkey_user_verification() failed [%d]: [%s].\n", - ret, sss_strerror(ret)); - goto done; - } - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} diff --git a/src/db/sysdb_passkey_user_verification.h b/src/db/sysdb_passkey_user_verification.h deleted file mode 100644 index 5644c3c688e..00000000000 --- a/src/db/sysdb_passkey_user_verification.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Authors: - Justin Stephenson - - Copyright (C) 2022 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SYSDB_PASSKEY_USER_VERIFICATION_H_ -#define _SYSDB_PASSKEY_USER_VERIFICATION_H_ - -#include "db/sysdb.h" - -/* Retrieve passkey user verification value from sysdb */ -errno_t sysdb_get_passkey_user_verification(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - struct ldb_dn *dn, - const char **_user_verification); - -/* Replace passkey user verification value in sysdb with - * user_verification argument value */ -errno_t sysdb_update_passkey_user_verification(struct sysdb_ctx *sysdb, - struct ldb_dn *dn, - const char *user_verification); - -/* For a given domain, retrieve passkey user verification value from sysdb */ -errno_t sysdb_domain_get_passkey_user_verification(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - const char *domain_name, - const char **_user_verification); - -/* For a given domain, replace passkey user verification value from sysdb - * with user_verification argument value */ -errno_t sysdb_domain_update_passkey_user_verification(struct sysdb_ctx *sysdb, - const char *domain_name, - const char *user_verification); -#endif /* _SYSDB_PASSKEY_USER_VERIFICATION_H_ */ diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c index b526775e091..a6c282202c5 100644 --- a/src/providers/ipa/ipa_subdomains.c +++ b/src/providers/ipa/ipa_subdomains.c @@ -30,9 +30,6 @@ #include "providers/ipa/ipa_id.h" #include "providers/ipa/ipa_opts.h" #include "providers/ipa/ipa_config.h" -#ifdef BUILD_PASSKEY -#include "providers/ipa/ipa_subdomains_passkey.h" -#endif /* BUILD_PASSKEY */ #include @@ -67,8 +64,6 @@ #define IPA_ENABLED_FLAG "ipaEnabledFlag" #define IPA_TRUE_VALUE "TRUE" #define IPA_ASSOCIATED_DOMAIN "associatedDomain" -#define IPA_PASSKEY_VERIFICATION "ipaRequireUserVerification" -#define IPA_PASSKEY_CONFIG_FILTER "cn=passkeyconfig" #define OBJECTCLASS "objectClass" @@ -2908,9 +2903,6 @@ static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req); static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq); static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq); static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq); -#ifdef BUILD_PASSKEY -static void ipa_subdomains_refresh_passkey_done(struct tevent_req *subreq); -#endif /* BUILD_PASSKEY */ static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq); static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq); static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq); @@ -3065,39 +3057,6 @@ static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq) /* Not good, but let's try to continue with other server side options */ } -#ifdef BUILD_PASSKEY - subreq = ipa_subdomains_passkey_send(state, state->ev, state->sd_ctx, - sdap_id_op_handle(state->sdap_op)); - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(subreq, ipa_subdomains_refresh_passkey_done, req); - return; -} - -static void ipa_subdomains_refresh_passkey_done(struct tevent_req *subreq) -{ - - struct ipa_subdomains_refresh_state *state; - struct tevent_req *req; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct ipa_subdomains_refresh_state); - - ret = ipa_subdomains_passkey_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get passkey configuration " - "[%d]: %s\n", ret, sss_strerror(ret)); - /* Not good, but let's try to continue with other server side options */ - DEBUG(SSSDBG_IMPORTANT_INFO, "Passkey feature is not configured " - "on IPA server\n"); - } -#endif /* BUILD_PASSKEY */ - subreq = ipa_subdomains_master_send(state, state->ev, state->sd_ctx, sdap_id_op_handle(state->sdap_op)); if (subreq == NULL) { diff --git a/src/providers/ipa/ipa_subdomains_passkey.c b/src/providers/ipa/ipa_subdomains_passkey.c deleted file mode 100644 index 55d951f1540..00000000000 --- a/src/providers/ipa/ipa_subdomains_passkey.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - SSSD - - IPA Subdomains Passkey Module - - Authors: - Justin Stephenson - - Copyright (C) 2022 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "providers/ldap/sdap_async.h" -#include "providers/ldap/sdap_idmap.h" -#include "providers/ldap/sdap_ops.h" -#include "providers/ipa/ipa_subdomains.h" -#include "providers/ipa/ipa_common.h" -#include "providers/ipa/ipa_id.h" -#include "providers/ipa/ipa_opts.h" -#include "providers/ipa/ipa_config.h" -#include "providers/ipa/ipa_subdomains_passkey.h" -#include "db/sysdb_passkey_user_verification.h" - -#include -#define IPA_PASSKEY_VERIFICATION "ipaRequireUserVerification" -#define IPA_PASSKEY_CONFIG_FILTER "cn=passkeyconfig" - -void ipa_subdomains_passkey_done(struct tevent_req *subreq); - -struct tevent_req * -ipa_subdomains_passkey_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct ipa_subdomains_ctx *sd_ctx, - struct sdap_handle *sh) -{ - struct ipa_subdomains_passkey_state *state; - struct tevent_req *subreq; - struct tevent_req *req; - errno_t ret; - static const char *attrs[] = { IPA_PASSKEY_VERIFICATION, NULL }; - - req = tevent_req_create(mem_ctx, &state, - struct ipa_subdomains_passkey_state); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); - return NULL; - } - - state->domain = sd_ctx->be_ctx->domain; - state->sdap_opts = sd_ctx->sdap_id_ctx->opts; - - subreq = ipa_get_config_send(state, ev, sh, sd_ctx->sdap_id_ctx->opts, - state->domain->name, attrs, IPA_PASSKEY_CONFIG_FILTER, NULL); - - if (subreq == NULL) { - ret = ENOMEM; - goto immediately; - } - - tevent_req_set_callback(subreq, ipa_subdomains_passkey_done, req); - - return req; - -immediately: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - - return req; -} - -void ipa_subdomains_passkey_done(struct tevent_req *subreq) -{ - struct ipa_subdomains_passkey_state *state; - struct tevent_req *req; - struct sysdb_attrs *config; - const char *user_verification = NULL; - errno_t ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct ipa_subdomains_passkey_state); - - ret = ipa_get_config_recv(subreq, state, &config); - talloc_zfree(subreq); - if (ret == ENOENT) { - config = NULL; - } if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Unable to get data from LDAP [%d]: %s\n", - ret, sss_strerror(ret)); - goto done; - } - - if (config != NULL) { - ret = sysdb_attrs_get_string(config, IPA_PASSKEY_VERIFICATION, - &user_verification); - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_ALL, "Retrieved [%s] from [%s] attribute.\n", - user_verification, IPA_PASSKEY_VERIFICATION); - } - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to get passkey user verification " - "value [%d]: %s\n", - ret, sss_strerror(ret)); - goto done; - } else if (ret == ENOENT) { - user_verification = NULL; - } - } - - ret = sysdb_domain_update_passkey_user_verification( - state->domain->sysdb, state->domain->name, - user_verification); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_domain_passkey_user_verification() [%d]: [%s].\n", - ret, sss_strerror(ret)); - goto done; - } - - ret = EOK; - -done: - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -errno_t ipa_subdomains_passkey_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} diff --git a/src/providers/ipa/ipa_subdomains_passkey.h b/src/providers/ipa/ipa_subdomains_passkey.h deleted file mode 100644 index ecbf2391349..00000000000 --- a/src/providers/ipa/ipa_subdomains_passkey.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - SSSD - - IPA Subdomains Passkey Module - - Authors: - Justin Stephenson - - Copyright (C) 2022 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _IPA_SUBDOMAINS_PASSKEY_H_ -#define _IPA_SUBDOMAINS_PASSKEY_H_ - -#include "providers/backend.h" -#include "providers/ipa/ipa_common.h" -#include "config.h" - -struct ipa_subdomains_passkey_state { - struct sss_domain_info *domain; - struct sdap_options *sdap_opts; -}; - -struct tevent_req * -ipa_subdomains_passkey_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct ipa_subdomains_ctx *sd_ctx, - struct sdap_handle *sh); - -errno_t ipa_subdomains_passkey_recv(struct tevent_req *req); - -#endif /* _IPA_SUBDOMAINS_PASSKEY_H_ */ diff --git a/src/responder/pam/pamsrv_passkey.c b/src/responder/pam/pamsrv_passkey.c index 83f36793fe0..13e07ecf08a 100644 --- a/src/responder/pam/pamsrv_passkey.c +++ b/src/responder/pam/pamsrv_passkey.c @@ -22,7 +22,6 @@ #include "util/child_common.h" #include "util/authtok.h" #include "db/sysdb.h" -#include "db/sysdb_passkey_user_verification.h" #include "responder/pam/pamsrv.h" #include "responder/pam/pamsrv_passkey.h" @@ -390,7 +389,6 @@ static errno_t passkey_local_verification(TALLOC_CTX *mem_ctx, { TALLOC_CTX *tmp_ctx; errno_t ret; - const char *verification_from_ldap; char *verify_opts = NULL; bool debug_libfido2 = false; enum passkey_user_verification verification = PAM_PASSKEY_VERIFICATION_OMIT; @@ -400,17 +398,6 @@ static errno_t passkey_local_verification(TALLOC_CTX *mem_ctx, return ENOMEM; } - ret = sysdb_domain_get_passkey_user_verification(tmp_ctx, sysdb, domain_name, - &verification_from_ldap); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to read passkeyUserVerification from sysdb: [%d]: %s\n", - ret, sss_strerror(ret)); - /* This is expected for AD and LDAP */ - ret = EOK; - goto done; - } - ret = confdb_get_bool(pctx->pam_ctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_PASSKEY_DEBUG_LIBFIDO2, false, &debug_libfido2); @@ -421,34 +408,24 @@ static errno_t passkey_local_verification(TALLOC_CTX *mem_ctx, goto done; } - /* If require user verification setting is set in LDAP, use it */ - if (verification_from_ldap != NULL) { - if (strcasecmp(verification_from_ldap, "true") == 0) { - verification = PAM_PASSKEY_VERIFICATION_ON; - } else if (strcasecmp(verification_from_ldap, "false") == 0) { - verification = PAM_PASSKEY_VERIFICATION_OFF; - } - DEBUG(SSSDBG_TRACE_FUNC, "Passkey verification is being enforced from LDAP\n"); - } else { - /* No verification set in LDAP, fallback to local sssd.conf setting */ - ret = confdb_get_string(pctx->pam_ctx->rctx->cdb, tmp_ctx, CONFDB_MONITOR_CONF_ENTRY, - CONFDB_MONITOR_PASSKEY_VERIFICATION, NULL, - &verify_opts); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to read '"CONFDB_MONITOR_PASSKEY_VERIFICATION"' from confdb: [%d]: %s\n", - ret, sss_strerror(ret)); - goto done; - } + /* Check local sssd.conf setting */ + ret = confdb_get_string(pctx->pam_ctx->rctx->cdb, tmp_ctx, CONFDB_MONITOR_CONF_ENTRY, + CONFDB_MONITOR_PASSKEY_VERIFICATION, NULL, + &verify_opts); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to read '"CONFDB_MONITOR_PASSKEY_VERIFICATION"' from confdb: [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } - ret = read_passkey_conf_verification(tmp_ctx, verify_opts, &verification); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, "Unable to parse passkey verificaton options.\n"); - /* Continue anyway */ - } - DEBUG(SSSDBG_TRACE_FUNC, "Passkey verification is being enforced from local configuration\n"); + ret = read_passkey_conf_verification(tmp_ctx, verify_opts, &verification); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Unable to parse passkey verificaton options.\n"); + /* Continue anyway */ } + DEBUG(SSSDBG_TRACE_FUNC, "Passkey verification is being enforced from local configuration\n"); DEBUG(SSSDBG_TRACE_FUNC, "Passkey verification setting [%s]\n", pam_passkey_verification_enum_to_string(verification)); diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c index a08cda570f5..35ebfbafae2 100644 --- a/src/tests/cmocka/test_pam_srv.c +++ b/src/tests/cmocka/test_pam_srv.c @@ -35,7 +35,6 @@ #include "confdb/confdb.h" #ifdef BUILD_PASSKEY #include "src/responder/pam/pamsrv_passkey.h" -#include "db/sysdb_passkey_user_verification.h" #endif #include "util/crypto/sss_crypto.h" @@ -4678,17 +4677,9 @@ void test_pam_passkey_preauth_found(void **state) struct sysdb_attrs *attrs; const char *passkey = SSSD_TEST_PASSKEY; size_t pk_size; - const char *user_verification = "on"; set_passkey_auth_param(pam_test_ctx->pctx); - /* Add user verification attribute */ - ret = sysdb_domain_update_passkey_user_verification( - pam_test_ctx->tctx->dom->sysdb, - pam_test_ctx->tctx->dom->name, - user_verification); - assert_int_equal(ret, EOK); - mock_input_pam_passkey(pam_test_ctx, "pamuser", "1234", NULL, NULL, SSSD_TEST_PASSKEY); mock_parse_inp("pamuser", NULL, EOK); @@ -4729,17 +4720,9 @@ void test_pam_passkey_auth(void **state) struct sysdb_attrs *attrs; const char *passkey = SSSD_TEST_PASSKEY; size_t pk_size; - const char *user_verification = "on"; set_passkey_auth_param(pam_test_ctx->pctx); - /* Add user verification attribute */ - ret = sysdb_domain_update_passkey_user_verification( - pam_test_ctx->tctx->dom->sysdb, - pam_test_ctx->tctx->dom->name, - user_verification); - assert_int_equal(ret, EOK); - mock_input_pam_passkey(pam_test_ctx, "pamuser", "1234", NULL, NULL, SSSD_TEST_PASSKEY); @@ -4777,17 +4760,9 @@ void test_pam_passkey_pubkey_mapping(void **state) struct sysdb_attrs *attrs; const char *pubkey = SSSD_TEST_PUBKEY; size_t pk_size; - const char *user_verification = "on"; set_passkey_auth_param(pam_test_ctx->pctx); - /* Add user verification attribute */ - ret = sysdb_domain_update_passkey_user_verification( - pam_test_ctx->tctx->dom->sysdb, - pam_test_ctx->tctx->dom->name, - user_verification); - assert_int_equal(ret, EOK); - mock_input_pam_passkey(pam_test_ctx, "pamuser", "1234", NULL, NULL, SSSD_TEST_PASSKEY); mock_parse_inp("pamuser", NULL, EOK); @@ -4823,7 +4798,6 @@ void test_pam_passkey_pubkey_mapping(void **state) void test_pam_passkey_preauth_mapping_multi(void **state) { int ret; - const char *user_verification = "on"; struct sysdb_attrs *attrs; const char *passkey = SSSD_TEST_PASSKEY; const char *pubkey = SSSD_TEST_PUBKEY; @@ -4832,13 +4806,6 @@ void test_pam_passkey_preauth_mapping_multi(void **state) set_passkey_auth_param(pam_test_ctx->pctx); - /* Add user verification attribute */ - ret = sysdb_domain_update_passkey_user_verification( - pam_test_ctx->tctx->dom->sysdb, - pam_test_ctx->tctx->dom->name, - user_verification); - assert_int_equal(ret, EOK); - mock_input_pam_passkey(pam_test_ctx, "pamuser", "1234", NULL, NULL, SSSD_TEST_PASSKEY); From 386f3c69bb2c9eec0e814eea563e90d51a01537e Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 5 Nov 2025 13:33:36 -0500 Subject: [PATCH 3/5] pam: Skip passkey_local() in Kerberos auth flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Local auth functions should only be reached in AD/LDAP auth flows. Reviewed-by: Iker Pedrosa Reviewed-by: Tomáš Halman (cherry picked from commit 304f298c978138cc9efa7c9beced30aceb47a7fd) --- src/responder/pam/pamsrv_cmd.c | 5 ++++- src/responder/pam/pamsrv_passkey.c | 5 ++++- src/responder/pam/pamsrv_passkey.h | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index c6a4360699c..1b58439e169 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -1231,6 +1231,7 @@ void pam_reply(struct pam_auth_req *preq) bool local_passkey_auth_allow = false; #ifdef BUILD_PASSKEY bool pk_preauth_done = false; + bool pk_kerberos = false; #endif /* BUILD_PASSKEY */ pd = preq->pd; @@ -1514,7 +1515,8 @@ void pam_reply(struct pam_auth_req *preq) } #ifdef BUILD_PASSKEY - ret = pam_eval_passkey_response(pctx, pd, preq, &pk_preauth_done); + ret = pam_eval_passkey_response(pctx, pd, preq, &pk_preauth_done, + &pk_kerberos); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to eval passkey response\n"); goto done; @@ -1522,6 +1524,7 @@ void pam_reply(struct pam_auth_req *preq) if (may_do_passkey_auth(pctx, pd) && !pk_preauth_done + && !pk_kerberos && preq->passkey_data_exists && local_passkey_auth_allow) { ret = passkey_local(cctx, cctx->ev, pctx, preq, pd); diff --git a/src/responder/pam/pamsrv_passkey.c b/src/responder/pam/pamsrv_passkey.c index 13e07ecf08a..65d8d5dddca 100644 --- a/src/responder/pam/pamsrv_passkey.c +++ b/src/responder/pam/pamsrv_passkey.c @@ -1322,7 +1322,8 @@ errno_t save_passkey_data(TALLOC_CTX *mem_ctx, errno_t pam_eval_passkey_response(struct pam_ctx *pctx, struct pam_data *pd, struct pam_auth_req *preq, - bool *_pk_preauth_done) + bool *_pk_preauth_done, + bool *_kerberos) { struct response_data *pk_resp; struct pk_child_user_data *pk_data; @@ -1339,6 +1340,8 @@ errno_t pam_eval_passkey_response(struct pam_ctx *pctx, while (pk_resp != NULL) { switch (pk_resp->type) { case SSS_PAM_PASSKEY_KRB_INFO: + *_kerberos = true; + if (!pctx->passkey_auth) { /* Passkey auth is disabled. To avoid passkey prompts appearing, * don't send SSS_PAM_PASSKEY_KRB_INFO to the client and diff --git a/src/responder/pam/pamsrv_passkey.h b/src/responder/pam/pamsrv_passkey.h index 48074d04263..d64220d0f3e 100644 --- a/src/responder/pam/pamsrv_passkey.h +++ b/src/responder/pam/pamsrv_passkey.h @@ -76,7 +76,8 @@ errno_t pam_passkey_auth_recv(struct tevent_req *req, errno_t pam_eval_passkey_response(struct pam_ctx *pctx, struct pam_data *pd, struct pam_auth_req *preq, - bool *_pk_preauth_done); + bool *_pk_preauth_done, + bool *_kerberos); errno_t process_passkey_data(TALLOC_CTX *mem_ctx, struct ldb_message *user_mesg, const char *domain, From 04db917033e010a99a3c4e4590e105331b4a7417 Mon Sep 17 00:00:00 2001 From: Justin Stephenson Date: Wed, 5 Nov 2025 10:13:26 -0500 Subject: [PATCH 4/5] pam: Remove PAM_PASSKEY_VERIFICATION_OMIT mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove support of ambiguous "unset" state of passkey user verification. pam_sss prompting is binary, either on or off. The use of 'unset' passkey user verification state allows for ambiguous behavior in SSSD. For example, passkey_child may perform undefined behavior when '--user-verification' argument is not set, now SSSD will always send '--user-verification=false/true' to passkey_child. Reviewed-by: Iker Pedrosa Reviewed-by: Tomáš Halman (cherry picked from commit e9216fc1e90514db698259b93d1a6a47d0036b4c) --- src/responder/pam/pamsrv_passkey.c | 6 ++---- src/responder/pam/pamsrv_passkey.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/responder/pam/pamsrv_passkey.c b/src/responder/pam/pamsrv_passkey.c index 65d8d5dddca..540b3f63cd6 100644 --- a/src/responder/pam/pamsrv_passkey.c +++ b/src/responder/pam/pamsrv_passkey.c @@ -40,7 +40,6 @@ struct pam_passkey_table_data { struct pam_passkey_verification_enum_str pam_passkey_verification_enum_str[] = { { PAM_PASSKEY_VERIFICATION_ON, "on" }, { PAM_PASSKEY_VERIFICATION_OFF, "off" }, - { PAM_PASSKEY_VERIFICATION_OMIT, "unset" }, { PAM_PASSKEY_VERIFICATION_INVALID, NULL } }; @@ -391,7 +390,7 @@ static errno_t passkey_local_verification(TALLOC_CTX *mem_ctx, errno_t ret; char *verify_opts = NULL; bool debug_libfido2 = false; - enum passkey_user_verification verification = PAM_PASSKEY_VERIFICATION_OMIT; + enum passkey_user_verification verification = PAM_PASSKEY_VERIFICATION_ON; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { @@ -599,7 +598,7 @@ void pam_passkey_get_user_done(struct tevent_req *req) int timeout; struct cache_req_result *result = NULL; struct pk_child_user_data *pk_data = NULL; - enum passkey_user_verification verification = PAM_PASSKEY_VERIFICATION_OMIT; + enum passkey_user_verification verification = PAM_PASSKEY_VERIFICATION_ON; pctx = tevent_req_callback_data(req, struct passkey_ctx); @@ -968,7 +967,6 @@ pam_passkey_auth_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Calling child with user-verification false\n"); break; default: - DEBUG(SSSDBG_TRACE_FUNC, "Calling child with user-verification unset\n"); break; } diff --git a/src/responder/pam/pamsrv_passkey.h b/src/responder/pam/pamsrv_passkey.h index d64220d0f3e..8d35cbb2695 100644 --- a/src/responder/pam/pamsrv_passkey.h +++ b/src/responder/pam/pamsrv_passkey.h @@ -32,7 +32,6 @@ enum passkey_user_verification { PAM_PASSKEY_VERIFICATION_ON, PAM_PASSKEY_VERIFICATION_OFF, - PAM_PASSKEY_VERIFICATION_OMIT, PAM_PASSKEY_VERIFICATION_INVALID }; From 24b3a4ce790b1a7d2eea34c74207d39090c3f76d Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Tue, 28 Oct 2025 17:07:04 +0100 Subject: [PATCH 5/5] Responder: fix passkey auth when user-verification is off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When authenticating with a passkey, different PAM code paths within SSSD can result in the `authtok` containing data even when the user did not enter a PIN. Depending on the flow (e.g., triggered by `gdm` vs. `su`), this data might be an empty string or non-printable characters like `^L` (form feed). The previous code had two issues: 1. It only checked if the `authtok` was non-empty (`sss_authtok_get_type(...) != SSS_AUTHTOK_TYPE_EMPTY`). If user verification was disabled, this check would incorrectly pass for these 'junk' `authtok` values. This caused SSSD to prepare and send an erroneous PIN to the passkey helper. 2. In the case where the `authtok` *was* correctly empty, the check would fail, `write_buf_len` would remain 0, and the `if (write_buf_len != 0)` block containing the `write_pipe_send` call would be skipped. This stalled the authentication flow, as the callback to continue the process was never set. This patch fixes both issues: 1. The `user_verification` setting is now stored in the state struct. The logic is updated to only prepare the PIN buffer if the `authtok` is non-empty *and* user verification is required (`state->user_verification != PAM_PASSKEY_VERIFICATION_OFF`). 2. The `write_pipe_send` call is moved outside the conditional block so it always runs. This ensures that the asynchronous child communication (via `passkey_child_write_done`) is always triggered, even if the write buffer is empty (0-length). This resolves both failure modes: junk PINs are no longer sent when verification is off, and the auth flow no longer stalls when no PIN is present. Signed-off-by: Iker Pedrosa Reviewed-by: Justin Stephenson Reviewed-by: Sumit Bose (cherry picked from commit bc1460c3d1f90463e900bcc2673d0d2122428a99) Reviewed-by: Iker Pedrosa Reviewed-by: Tomáš Halman --- src/responder/pam/pamsrv_passkey.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/responder/pam/pamsrv_passkey.c b/src/responder/pam/pamsrv_passkey.c index 540b3f63cd6..ab8da72eee0 100644 --- a/src/responder/pam/pamsrv_passkey.c +++ b/src/responder/pam/pamsrv_passkey.c @@ -730,6 +730,7 @@ struct pam_passkey_auth_send_state { int timeout; int child_status; bool kerberos_pa; + enum passkey_user_verification user_verification; }; static errno_t passkey_child_exec(struct tevent_req *req); @@ -938,6 +939,7 @@ pam_passkey_auth_send(TALLOC_CTX *mem_ctx, state->timeout = timeout; state->kerberos_pa = kerberos_pa; + state->user_verification = verification; state->logfile = PASSKEY_CHILD_LOG_FILE; state->io = talloc(state, struct child_io_fds); if (state->io == NULL) { @@ -1103,8 +1105,9 @@ static errno_t passkey_child_exec(struct tevent_req *req) goto done; } - /* PIN is needed */ - if (sss_authtok_get_type(state->pd->authtok) != SSS_AUTHTOK_TYPE_EMPTY) { + /* PIN is needed only when user verification is required */ + if (sss_authtok_get_type(state->pd->authtok) != SSS_AUTHTOK_TYPE_EMPTY + && state->user_verification != PAM_PASSKEY_VERIFICATION_OFF) { ret = get_passkey_child_write_buffer(state, state->pd, &write_buf, &write_buf_len); if (ret != EOK) { @@ -1115,16 +1118,14 @@ static errno_t passkey_child_exec(struct tevent_req *req) } } - if (write_buf_len != 0) { - subreq = write_pipe_send(state, state->ev, write_buf, write_buf_len, - state->io->write_to_child_fd); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "write_pipe_send failed.\n"); - ret = ERR_PASSKEY_CHILD; - goto done; - } - tevent_req_set_callback(subreq, passkey_child_write_done, req); + subreq = write_pipe_send(state, state->ev, write_buf, write_buf_len, + state->io->write_to_child_fd); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "write_pipe_send failed.\n"); + ret = ERR_PASSKEY_CHILD; + goto done; } + tevent_req_set_callback(subreq, passkey_child_write_done, req); /* Now either wait for the timeout to fire or the child to finish */ } else { /* error */ ret = errno;