From 5a0b01d98a7a72cb8cb60e731b1fe7b25229d53a Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 30 Apr 2024 19:49:19 +0000 Subject: [PATCH] import CS sssd-2.9.4-6.el9_4 --- .gitignore | 2 +- .sssd.metadata | 2 +- ...sssd-adding-mail-as-case-insensitive.patch | 144 +++++++++++ ...m_watchdog-and-disarm_watchdog-calls.patch | 106 -------- ...-watchdog-for-sbus_connect_init_send.patch | 53 ---- ..._bases-option-to-groups_by_user_send.patch | 154 ++++++++++++ ...context-as-new-member-of-struct-sdap.patch | 194 +++++++++++++++ ...with-multiple-certs-and-missing-logi.patch | 233 ++++++++++++++++++ ...lient-handle-key-value-in-destructor.patch | 50 ++++ ...fallback-between-responder-questions.patch | 104 ++++++++ ...Add-fallback-password-change-support.patch | 206 ++++++++++++++++ .../0008-pam-fix-invalid-if-condition.patch | 30 +++ ...5-add-OTP-to-krb5-response-selection.patch | 185 ++++++++++++++ ...nswer_pkinit-use-matching-debug-mess.patch | 119 +++++++++ ...er-and-pre-auth-debug-message-less-i.patch | 67 +++++ ..._sss-prefer-Smartcard-authentication.patch | 70 ++++++ ...-storing-auth-types-for-offline-auth.patch | 57 +++++ ...e-hash-to-store-intermediate-results.patch | 218 ++++++++++++++++ ...sions-from-openssl-command-if-there-.patch | 49 ++++ SPECS/sssd.spec | 91 ++++++- 20 files changed, 1969 insertions(+), 165 deletions(-) create mode 100644 SOURCES/0001-sssd-adding-mail-as-case-insensitive.patch delete mode 100644 SOURCES/0001-watchdog-add-arm_watchdog-and-disarm_watchdog-calls.patch delete mode 100644 SOURCES/0002-sbus-arm-watchdog-for-sbus_connect_init_send.patch create mode 100644 SOURCES/0002-sdap-add-search_bases-option-to-groups_by_user_send.patch create mode 100644 SOURCES/0003-sdap-add-naming_context-as-new-member-of-struct-sdap.patch create mode 100644 SOURCES/0004-pam-fix-SC-auth-with-multiple-certs-and-missing-logi.patch create mode 100644 SOURCES/0005-sss-client-handle-key-value-in-destructor.patch create mode 100644 SOURCES/0006-krb5-Allow-fallback-between-responder-questions.patch create mode 100644 SOURCES/0007-krb5-Add-fallback-password-change-support.patch create mode 100644 SOURCES/0008-pam-fix-invalid-if-condition.patch create mode 100644 SOURCES/0009-krb5-add-OTP-to-krb5-response-selection.patch create mode 100644 SOURCES/0010-krb5-make-sure-answer_pkinit-use-matching-debug-mess.patch create mode 100644 SOURCES/0011-krb5-make-prompter-and-pre-auth-debug-message-less-i.patch create mode 100644 SOURCES/0012-pam_sss-prefer-Smartcard-authentication.patch create mode 100644 SOURCES/0013-pam-fix-storing-auth-types-for-offline-auth.patch create mode 100644 SOURCES/0014-ad-gpo-use-hash-to-store-intermediate-results.patch create mode 100644 SOURCES/0015-tests-Drop-extensions-from-openssl-command-if-there-.patch diff --git a/.gitignore b/.gitignore index 4714c8c..d510690 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/sssd-2.9.1.tar.gz +SOURCES/sssd-2.9.4.tar.gz diff --git a/.sssd.metadata b/.sssd.metadata index 9b2fbfd..eaa72f2 100644 --- a/.sssd.metadata +++ b/.sssd.metadata @@ -1 +1 @@ -5eb0d3e600aed685a7e3ea49154dadef52361f84 SOURCES/sssd-2.9.1.tar.gz +574f6cec9ee12dd943e4305286845343ab7bb891 SOURCES/sssd-2.9.4.tar.gz diff --git a/SOURCES/0001-sssd-adding-mail-as-case-insensitive.patch b/SOURCES/0001-sssd-adding-mail-as-case-insensitive.patch new file mode 100644 index 0000000..1e12d0b --- /dev/null +++ b/SOURCES/0001-sssd-adding-mail-as-case-insensitive.patch @@ -0,0 +1,144 @@ +From dd0f63246aa75d5f53b44cbc185e88833e79976e Mon Sep 17 00:00:00 2001 +From: Andre Boscatto +Date: Wed, 7 Feb 2024 12:28:28 +0100 +Subject: [PATCH] sssd: adding mail as case insensitive +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://github.com/SSSD/sssd/issues/7173 + +Reviewed-by: Iker Pedrosa +Reviewed-by: Tomáš Halman +(cherry picked from commit 945cebcf72ef53ea0368f19c09e710f7fff11b51) +--- + src/db/sysdb_init.c | 7 ++++++ + src/db/sysdb_private.h | 5 +++- + src/db/sysdb_upgrade.c | 56 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 67 insertions(+), 1 deletion(-) + +diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c +index c2ea6c369..38a9cd64a 100644 +--- a/src/db/sysdb_init.c ++++ b/src/db/sysdb_init.c +@@ -603,6 +603,13 @@ static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx, + } + } + ++ if (strcmp(version, SYSDB_VERSION_0_23) == 0) { ++ ret = sysdb_upgrade_23(sysdb, &version); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ + ret = EOK; + done: + sysdb->ldb = save_ldb; +diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h +index 1f55007bc..63f7b5601 100644 +--- a/src/db/sysdb_private.h ++++ b/src/db/sysdb_private.h +@@ -23,6 +23,7 @@ + #ifndef __INT_SYS_DB_H__ + #define __INT_SYS_DB_H__ + ++#define SYSDB_VERSION_0_24 "0.24" + #define SYSDB_VERSION_0_23 "0.23" + #define SYSDB_VERSION_0_22 "0.22" + #define SYSDB_VERSION_0_21 "0.21" +@@ -47,7 +48,7 @@ + #define SYSDB_VERSION_0_2 "0.2" + #define SYSDB_VERSION_0_1 "0.1" + +-#define SYSDB_VERSION SYSDB_VERSION_0_23 ++#define SYSDB_VERSION SYSDB_VERSION_0_24 + + #define SYSDB_BASE_LDIF \ + "dn: @ATTRIBUTES\n" \ +@@ -60,6 +61,7 @@ + "objectclass: CASE_INSENSITIVE\n" \ + "ipHostNumber: CASE_INSENSITIVE\n" \ + "ipNetworkNumber: CASE_INSENSITIVE\n" \ ++ "mail: CASE_INSENSITIVE\n" \ + "\n" \ + "dn: @INDEXLIST\n" \ + "@IDXATTR: cn\n" \ +@@ -191,6 +193,7 @@ int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver); + int sysdb_upgrade_20(struct sysdb_ctx *sysdb, const char **ver); + int sysdb_upgrade_21(struct sysdb_ctx *sysdb, const char **ver); + int sysdb_upgrade_22(struct sysdb_ctx *sysdb, const char **ver); ++int sysdb_upgrade_23(struct sysdb_ctx *sysdb, const char **ver); + + int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver); + +diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c +index 346a1cb0b..56083e6be 100644 +--- a/src/db/sysdb_upgrade.c ++++ b/src/db/sysdb_upgrade.c +@@ -2718,6 +2718,62 @@ done: + return ret; + } + ++int sysdb_upgrade_23(struct sysdb_ctx *sysdb, const char **ver) ++{ ++ TALLOC_CTX *tmp_ctx; ++ int ret; ++ struct ldb_message *msg; ++ struct upgrade_ctx *ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (!tmp_ctx) { ++ return ENOMEM; ++ } ++ ++ ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_24, &ctx); ++ if (ret) { ++ return ret; ++ } ++ ++ /* Add new indexes */ ++ msg = ldb_msg_new(tmp_ctx); ++ if (!msg) { ++ ret = ENOMEM; ++ goto done; ++ } ++ msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); ++ if (!msg->dn) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ /* Case insensitive search for mail */ ++ ret = ldb_msg_add_empty(msg, SYSDB_USER_EMAIL, LDB_FLAG_MOD_ADD, NULL); ++ if (ret != LDB_SUCCESS) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ret = ldb_msg_add_string(msg, SYSDB_USER_EMAIL, "CASE_INSENSITIVE"); ++ if (ret != LDB_SUCCESS) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = ldb_modify(sysdb->ldb, msg); ++ if (ret != LDB_SUCCESS) { ++ ret = sysdb_error_to_errno(ret); ++ goto done; ++ } ++ ++ /* conversion done, update version number */ ++ ret = update_version(ctx); ++ ++done: ++ ret = finish_upgrade(ret, &ctx, ver); ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ + int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver) + { + struct upgrade_ctx *ctx; +-- +2.41.0 + diff --git a/SOURCES/0001-watchdog-add-arm_watchdog-and-disarm_watchdog-calls.patch b/SOURCES/0001-watchdog-add-arm_watchdog-and-disarm_watchdog-calls.patch deleted file mode 100644 index 6a77149..0000000 --- a/SOURCES/0001-watchdog-add-arm_watchdog-and-disarm_watchdog-calls.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 2cd5a6a2c8fd1826177d6bb51e7d4f4ad368bcfb Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 9 Jun 2023 12:31:39 +0200 -Subject: [PATCH 1/2] watchdog: add arm_watchdog() and disarm_watchdog() calls -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Those two new calls can be used if there are requests stuck by e.g. -waiting on replies where there is no other way to handle the timeout and -get the system back into a stable state. They should be only used as a -last resort. - -Resolves: https://github.com/SSSD/sssd/issues/6803 - -Reviewed-by: Alexey Tikhonov -Reviewed-by: Pavel Březina -(cherry picked from commit 75f2b35ad3b9256de905d05c5108400d35688554) ---- - src/util/util.h | 12 ++++++++++++ - src/util/util_watchdog.c | 28 ++++++++++++++++++++++++++-- - 2 files changed, 38 insertions(+), 2 deletions(-) - -diff --git a/src/util/util.h b/src/util/util.h -index a8356e0cd..9dbcf3301 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -756,6 +756,18 @@ int setup_watchdog(struct tevent_context *ev, int interval); - void teardown_watchdog(void); - int get_watchdog_ticks(void); - -+/* The arm_watchdog() and disarm_watchdog() calls will disable and re-enable -+ * the watchdog reset, respectively. This means that after arm_watchdog() is -+ * called the watchdog will not be resetted anymore and it will kill the -+ * process if disarm_watchdog() wasn't called before. -+ * Those calls should only be used when there is no other way to handle -+ * waiting request and recover into a stable state. -+ * Those calls cannot be nested, i.e. after calling arm_watchdog() it should -+ * not be called a second time in a different request because then -+ * disarm_watchdog() will disable the watchdog coverage for both. */ -+void arm_watchdog(void); -+void disarm_watchdog(void); -+ - /* from files.c */ - int sss_remove_tree(const char *root); - int sss_remove_subtree(const char *root); -diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c -index b1534e499..abafd94b9 100644 ---- a/src/util/util_watchdog.c -+++ b/src/util/util_watchdog.c -@@ -40,6 +40,7 @@ struct watchdog_ctx { - time_t timestamp; - struct tevent_fd *tfd; - int pipefd[2]; -+ bool armed; /* if 'true' ticks counter will not be reset */ - } watchdog_ctx; - - static void watchdog_detect_timeshift(void) -@@ -89,8 +90,13 @@ static void watchdog_event_handler(struct tevent_context *ev, - struct timeval current_time, - void *private_data) - { -- /* first thing reset the watchdog ticks */ -- watchdog_reset(); -+ if (!watchdog_ctx.armed) { -+ /* first thing reset the watchdog ticks */ -+ watchdog_reset(); -+ } else { -+ DEBUG(SSSDBG_IMPORTANT_INFO, -+ "Watchdog armed, process might be terminated soon.\n"); -+ } - - /* then set a new watchodg event */ - watchdog_ctx.te = tevent_add_timer(ev, ev, -@@ -197,6 +203,7 @@ int setup_watchdog(struct tevent_context *ev, int interval) - watchdog_ctx.ev = ev; - watchdog_ctx.input_interval = interval; - watchdog_ctx.timestamp = time(NULL); -+ watchdog_ctx.armed = false; - - ret = pipe(watchdog_ctx.pipefd); - if (ret == -1) { -@@ -264,3 +271,20 @@ int get_watchdog_ticks(void) - { - return __sync_add_and_fetch(&watchdog_ctx.ticks, 0); - } -+ -+void arm_watchdog(void) -+{ -+ if (watchdog_ctx.armed) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "arm_watchdog() is called although the watchdog is already armed. " -+ "This indicates a programming error and should be avoided because " -+ "it will most probably not work as expected.\n"); -+ } -+ -+ watchdog_ctx.armed = true; -+} -+ -+void disarm_watchdog(void) -+{ -+ watchdog_ctx.armed = false; -+} --- -2.38.1 - diff --git a/SOURCES/0002-sbus-arm-watchdog-for-sbus_connect_init_send.patch b/SOURCES/0002-sbus-arm-watchdog-for-sbus_connect_init_send.patch deleted file mode 100644 index 99e7c04..0000000 --- a/SOURCES/0002-sbus-arm-watchdog-for-sbus_connect_init_send.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 55564defec8fdbb4d9df6b0124a8b18b31743230 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 9 Jun 2023 13:01:47 +0200 -Subject: [PATCH 2/2] sbus: arm watchdog for sbus_connect_init_send() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There seem to be conditions where the reply in the -sbus_call_DBus_Hello_send() request gets lost and the backend cannot -properly initialize its sbus/DBus server. Since the backend cannot be -connected by the frontends in this state the best way to recover would -be a restart. Since the event-loop is active in this state, e.g. waiting -for the reply, the watchdog will not consider the process as hung and -will not restart the process. - -To make the watchdog handle this case arm_watchdog() and -disarm_watchdog() are called before and after the request, respectively. - -Resolves: https://github.com/SSSD/sssd/issues/6803 - -Reviewed-by: Alexey Tikhonov -Reviewed-by: Pavel Březina -(cherry picked from commit cca9361d92501e0be34d264d370fe897a0c970af) ---- - src/sbus/connection/sbus_connection_connect.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/sbus/connection/sbus_connection_connect.c b/src/sbus/connection/sbus_connection_connect.c -index 45a0fa491..edc090e15 100644 ---- a/src/sbus/connection/sbus_connection_connect.c -+++ b/src/sbus/connection/sbus_connection_connect.c -@@ -67,6 +67,8 @@ sbus_connect_init_send(TALLOC_CTX *mem_ctx, - - tevent_req_set_callback(subreq, sbus_connect_init_hello_done, req); - -+ arm_watchdog(); -+ - return req; - } - -@@ -111,6 +113,8 @@ static void sbus_connect_init_done(struct tevent_req *subreq) - uint32_t res; - errno_t ret; - -+ disarm_watchdog(); -+ - req = tevent_req_callback_data(subreq, struct tevent_req); - - ret = sbus_call_DBus_RequestName_recv(subreq, &res); --- -2.38.1 - diff --git a/SOURCES/0002-sdap-add-search_bases-option-to-groups_by_user_send.patch b/SOURCES/0002-sdap-add-search_bases-option-to-groups_by_user_send.patch new file mode 100644 index 0000000..e7f048f --- /dev/null +++ b/SOURCES/0002-sdap-add-search_bases-option-to-groups_by_user_send.patch @@ -0,0 +1,154 @@ +From a7621a5b464af7a3c8409dcbde038b35fee2c895 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 23 Jan 2024 13:47:53 +0100 +Subject: [PATCH 2/3] sdap: add search_bases option to groups_by_user_send() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +AD handles users and computer objects very similar and so does SSSD's +GPO code when lookup up the host's group-memberships. But users and +computers might be stored in different sub-tree of the AD LDAP tree and +if a dedicated user search base is given with the ldap_user_search_base +option in sssd.conf the host object might be in a different sub-tree. To +make sure the host can still be found this patch uses the base DN of +the LDAP tree when searching for hosts in the GPO code. + +Resolves: https://github.com/SSSD/sssd/issues/5708 + +Reviewed-by: Alejandro López +Reviewed-by: Tomáš Halman +(cherry picked from commit 29a77c6e79020d7e8cb474b4d3b394d390eba196) +--- + src/providers/ad/ad_gpo.c | 10 ++++++++++ + src/providers/ldap/ldap_common.h | 1 + + src/providers/ldap/ldap_id.c | 6 +++++- + src/providers/ldap/sdap_async.h | 1 + + src/providers/ldap/sdap_async_initgroups.c | 4 +++- + 5 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index 94959c36b..b0ee3e616 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -2091,6 +2091,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) + char *server_uri; + LDAPURLDesc *lud; + struct sdap_domain *sdom; ++ struct sdap_search_base **search_bases; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ad_gpo_access_state); +@@ -2184,9 +2185,18 @@ ad_gpo_connect_done(struct tevent_req *subreq) + goto done; + } + ++ ret = common_parse_search_base(state, sdom->basedn, state->ldb_ctx, ++ "AD_HOSTS", NULL, &search_bases); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to create dedicated search base for host lookups, " ++ "trying with user search base."); ++ } ++ + subreq = groups_by_user_send(state, state->ev, + state->access_ctx->ad_id_ctx->sdap_id_ctx, + sdom, state->conn, ++ search_bases, + state->host_fqdn, + BE_FILTER_NAME, + NULL, +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index 7159d6356..2c984ef50 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -304,6 +304,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + struct sdap_id_ctx *ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn, ++ struct sdap_search_base **search_bases, + const char *filter_value, + int filter_type, + const char *extra_value, +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index da54816bd..b3ea2333f 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -1139,6 +1139,7 @@ struct groups_by_user_state { + struct sdap_id_op *op; + struct sysdb_ctx *sysdb; + struct sss_domain_info *domain; ++ struct sdap_search_base **search_bases; + + const char *filter_value; + int filter_type; +@@ -1160,6 +1161,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + struct sdap_id_ctx *ctx, + struct sdap_domain *sdom, + struct sdap_id_conn_ctx *conn, ++ struct sdap_search_base **search_bases, + const char *filter_value, + int filter_type, + const char *extra_value, +@@ -1192,6 +1194,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + state->extra_value = extra_value; + state->domain = sdom->dom; + state->sysdb = sdom->dom->sysdb; ++ state->search_bases = search_bases; + + if (state->domain->type == DOM_TYPE_APPLICATION || set_non_posix) { + state->non_posix = true; +@@ -1254,6 +1257,7 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) + sdap_id_op_handle(state->op), + state->ctx, + state->conn, ++ state->search_bases, + state->filter_value, + state->filter_type, + state->extra_value, +@@ -1449,7 +1453,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + } + + subreq = groups_by_user_send(state, be_ctx->ev, id_ctx, +- sdom, conn, ++ sdom, conn, NULL, + ar->filter_value, + ar->filter_type, + ar->extra_value, +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index 5458d21f1..89245f41f 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -158,6 +158,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, + struct sdap_id_conn_ctx *conn, ++ struct sdap_search_base **search_bases, + const char *name, + int filter_type, + const char *extra_value, +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 97be594a3..fb3d8fe24 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2732,6 +2732,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, + struct sdap_id_conn_ctx *conn, ++ struct sdap_search_base **search_bases, + const char *filter_value, + int filter_type, + const char *extra_value, +@@ -2764,7 +2765,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + state->orig_user = NULL; + state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT); + state->user_base_iter = 0; +- state->user_search_bases = sdom->user_search_bases; ++ state->user_search_bases = (search_bases == NULL) ? sdom->user_search_bases ++ : search_bases; + if (!state->user_search_bases) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Initgroups lookup request without a user search base\n"); +-- +2.41.0 + diff --git a/SOURCES/0003-sdap-add-naming_context-as-new-member-of-struct-sdap.patch b/SOURCES/0003-sdap-add-naming_context-as-new-member-of-struct-sdap.patch new file mode 100644 index 0000000..a7ff19e --- /dev/null +++ b/SOURCES/0003-sdap-add-naming_context-as-new-member-of-struct-sdap.patch @@ -0,0 +1,194 @@ +From 6a8e60df84d5d2565bec36be19c2def25a6ece1f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 24 Jan 2024 14:21:12 +0100 +Subject: [PATCH 3/3] sdap: add naming_context as new member of struct + sdap_domain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The naming_context could be a more reliable source than basedn for the +actual base DN because basedn is set very early from the domain name +given in sssd.conf. Although it is recommended to use the fully +qualified DNS domain name here it is not required. As a result basedn +might not reflect the actual based DN of the LDAP server. Also pure LDAP +server (i.e. not AD or FreeIPA) might use different schemes to set the +base DN which will not be based on the DNS domain of the LDAP server. + +Resolves: https://github.com/SSSD/sssd/issues/5708 + +Reviewed-by: Alejandro López +Reviewed-by: Tomáš Halman +(cherry picked from commit a153f13f296401247a862df2b99048bb1bbb8e2e) +--- + src/providers/ad/ad_gpo.c | 6 ++++-- + src/providers/ldap/sdap.c | 36 +++++++++++++----------------------- + src/providers/ldap/sdap.h | 11 +++++++++++ + 3 files changed, 28 insertions(+), 25 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index b0ee3e616..3d1ad39c7 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -2185,8 +2185,10 @@ ad_gpo_connect_done(struct tevent_req *subreq) + goto done; + } + +- ret = common_parse_search_base(state, sdom->basedn, state->ldb_ctx, +- "AD_HOSTS", NULL, &search_bases); ++ ret = common_parse_search_base(state, ++ sdom->naming_context == NULL ? sdom->basedn ++ : sdom->naming_context, ++ state->ldb_ctx, "AD_HOSTS", NULL, &search_bases); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to create dedicated search base for host lookups, " +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index f5637c5fb..956eba93a 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -1252,19 +1252,10 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + struct sdap_domain *sdom) + { + int ret; +- char *naming_context = NULL; + +- if (!sdom->search_bases +- || !sdom->user_search_bases +- || !sdom->group_search_bases +- || !sdom->netgroup_search_bases +- || !sdom->host_search_bases +- || !sdom->sudo_search_bases +- || !sdom->iphost_search_bases +- || !sdom->ipnetwork_search_bases +- || !sdom->autofs_search_bases) { +- naming_context = get_naming_context(opts->basic, rootdse); +- if (naming_context == NULL) { ++ if (!sdom->naming_context) { ++ sdom->naming_context = get_naming_context(sdom, rootdse); ++ if (sdom->naming_context == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "get_naming_context failed.\n"); + + /* This has to be non-fatal, since some servers offer +@@ -1280,7 +1271,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1288,7 +1279,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->user_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_USER_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1296,7 +1287,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->group_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_GROUP_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1304,7 +1295,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->netgroup_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_NETGROUP_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1312,7 +1303,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->host_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_HOST_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1320,7 +1311,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->sudo_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_SUDO_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1328,7 +1319,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->service_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_SERVICE_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1336,7 +1327,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->autofs_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_AUTOFS_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1344,7 +1335,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->iphost_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_IPHOST_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + +@@ -1352,14 +1343,13 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, + if (!sdom->ipnetwork_search_bases) { + ret = sdap_set_search_base(opts, sdom, + SDAP_IPNETWORK_SEARCH_BASE, +- naming_context); ++ sdom->naming_context); + if (ret != EOK) goto done; + } + + ret = EOK; + + done: +- talloc_free(naming_context); + return ret; + } + +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index 161bc5c26..103d50ed4 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -454,6 +454,17 @@ struct sdap_domain { + + char *basedn; + ++ /* The naming_context could be a more reliable source than basedn for the ++ * actual base DN because basedn is set very early from the domain name ++ * given in sssd.conf. Although it is recommended to use the fully ++ * qualified DNS domain name here it is not required. As a result basedn ++ * might not reflect the actual based DN of the LDAP server. Also pure ++ * LDAP server (i.e. not AD or FreeIPA) might use different schemes to set ++ * the base DN which will not be based on the DNS domain of the LDAP ++ * server. naming_context might be NULL even after connection to an LDAP ++ * server. */ ++ char *naming_context; ++ + struct sdap_search_base **search_bases; + struct sdap_search_base **user_search_bases; + struct sdap_search_base **group_search_bases; +-- +2.41.0 + diff --git a/SOURCES/0004-pam-fix-SC-auth-with-multiple-certs-and-missing-logi.patch b/SOURCES/0004-pam-fix-SC-auth-with-multiple-certs-and-missing-logi.patch new file mode 100644 index 0000000..7ba9ba5 --- /dev/null +++ b/SOURCES/0004-pam-fix-SC-auth-with-multiple-certs-and-missing-logi.patch @@ -0,0 +1,233 @@ +From 50077c3255177fe1b01837fbe31a7f8fd47dee74 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 18 Jan 2024 13:08:17 +0100 +Subject: [PATCH] pam: fix SC auth with multiple certs and missing login name + +While introducing the local_auth_policy option a quite specific use-case +was not covered correctly. If there are multiple matching certificates +on the Smartcard, 'local_auth_policy = only' is set and GDM's Smartcard +mode was used for login, i.e. there is no user name given and the user +has to be derived from the certificate used for login, authentication +failed. The main reason for the failure is that in this case the +Smartcard interaction and the user mapping has to be done first to +determine the user before local_auth_policy is evaluated. As a result +when checking if the authentication can be finished the request was in +an unexpected state because the indicator for local Smartcard +authentication was not enabled. + +Resolves: https://github.com/SSSD/sssd/issues/7109 + +Reviewed-by: Justin Stephenson +Reviewed-by: Scott Poore +(cherry picked from commit 44ec3e4638b0c6f7f45a3390a28c2e8745d52bc3) +--- + src/responder/pam/pamsrv.h | 10 ++++ + src/responder/pam/pamsrv_cmd.c | 17 +++++-- + src/tests/intg/Makefile.am | 2 + + src/tests/intg/test_pam_responder.py | 74 +++++++++++++++++++++++++++- + 4 files changed, 96 insertions(+), 7 deletions(-) + +diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h +index 7013a8edd..618836189 100644 +--- a/src/responder/pam/pamsrv.h ++++ b/src/responder/pam/pamsrv.h +@@ -93,7 +93,17 @@ struct pam_auth_req { + struct ldb_message *user_obj; + struct cert_auth_info *cert_list; + struct cert_auth_info *current_cert; ++ /* Switched to 'true' if the backend indicates that it cannot handle ++ * Smartcard authentication, but Smartcard authentication is ++ * possible and local Smartcard authentication is allowed. */ + bool cert_auth_local; ++ /* Switched to 'true' if authentication (not pre-authentication) was ++ * started without a login name and the name had to be lookup up with the ++ * certificate used for authentication. Since reading the certificate from ++ * the Smartcard already involves the PIN validation in this case there ++ * would be no need for an additional Smartcard interaction if only local ++ * Smartcard authentication is possible. */ ++ bool initial_cert_auth_successful; + + bool passkey_data_exists; + uint32_t client_id_num; +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index c23ea7ba4..a7c181733 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -2200,8 +2200,8 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) + ret = ENOENT; + goto done; + } +- +- if (cert_count > 1) { ++ /* Multiple certificates are only expected during pre-auth */ ++ if (cert_count > 1 && preq->pd->cmd == SSS_PAM_PREAUTH) { + for (preq->current_cert = preq->cert_list; + preq->current_cert != NULL; + preq->current_cert = sss_cai_get_next(preq->current_cert)) { +@@ -2285,7 +2285,9 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) + } + + /* If logon_name was not given during authentication add a +- * SSS_PAM_CERT_INFO message to send the name to the caller. */ ++ * SSS_PAM_CERT_INFO message to send the name to the caller. ++ * Additionally initial_cert_auth_successful is set to ++ * indicate that the user is already authenticated. */ + if (preq->pd->cmd == SSS_PAM_AUTHENTICATE + && preq->pd->logon_name == NULL) { + ret = add_pam_cert_response(preq->pd, +@@ -2297,6 +2299,8 @@ static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) + preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL; + goto done; + } ++ ++ preq->initial_cert_auth_successful = true; + } + + /* cert_user will be returned to the PAM client as user name, so +@@ -2851,12 +2855,15 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) + if (found) { + if (local_policy != NULL && strcasecmp(local_policy, "only") == 0) { + talloc_free(tmp_ctx); +- DEBUG(SSSDBG_IMPORTANT_INFO, "Local auth only set, skipping online auth\n"); ++ DEBUG(SSSDBG_IMPORTANT_INFO, ++ "Local auth only set and matching certificate was found, " ++ "skipping online auth\n"); + if (preq->pd->cmd == SSS_PAM_PREAUTH) { + preq->pd->pam_status = PAM_SUCCESS; + } else if (preq->pd->cmd == SSS_PAM_AUTHENTICATE + && IS_SC_AUTHTOK(preq->pd->authtok) +- && preq->cert_auth_local) { ++ && (preq->cert_auth_local ++ || preq->initial_cert_auth_successful)) { + preq->pd->pam_status = PAM_SUCCESS; + preq->callback = pam_reply; + } +diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am +index 3866d3ca6..0cfd268dc 100644 +--- a/src/tests/intg/Makefile.am ++++ b/src/tests/intg/Makefile.am +@@ -199,6 +199,7 @@ clean-local: + + PAM_CERT_DB_PATH="$(abs_builddir)/../test_CA/SSSD_test_CA.pem" + SOFTHSM2_CONF="$(abs_builddir)/../test_CA/softhsm2_one.conf" ++SOFTHSM2_TWO_CONF="$(abs_builddir)/../test_CA/softhsm2_two.conf" + + intgcheck-installed: config.py passwd group pam_sss_service pam_sss_alt_service pam_sss_sc_required pam_sss_try_sc pam_sss_allow_missing_name pam_sss_domains sss_netgroup_thread_test + pipepath="$(DESTDIR)$(pipepath)"; \ +@@ -233,6 +234,7 @@ intgcheck-installed: config.py passwd group pam_sss_service pam_sss_alt_service + PAM_CERT_DB_PATH=$(PAM_CERT_DB_PATH) \ + ABS_SRCDIR=$(abs_srcdir) \ + SOFTHSM2_CONF=$(SOFTHSM2_CONF) \ ++ SOFTHSM2_TWO_CONF=$(SOFTHSM2_TWO_CONF) \ + KCM_RENEW=$(KCM_RENEW) \ + FILES_PROVIDER=$(FILES_PROVIDER) \ + DBUS_SOCK_DIR="$(DESTDIR)$(runstatedir)/dbus/" \ +diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py +index 1fc3937e6..0fbf8065e 100644 +--- a/src/tests/intg/test_pam_responder.py ++++ b/src/tests/intg/test_pam_responder.py +@@ -168,7 +168,7 @@ def format_pam_cert_auth_conf(config, provider): + {provider.p} + + [certmap/auth_only/user1] +- matchrule = .*CN=SSSD test cert 0001.* ++ matchrule = .*CN=SSSD test cert 000[12].* + """).format(**locals()) + + +@@ -201,7 +201,7 @@ def format_pam_cert_auth_conf_name_format(config, provider): + {provider.p} + + [certmap/auth_only/user1] +- matchrule = .*CN=SSSD test cert 0001.* ++ matchrule = .*CN=SSSD test cert 000[12].* + """).format(**locals()) + + +@@ -380,6 +380,28 @@ def simple_pam_cert_auth_no_cert(request, passwd_ops_setup): + return None + + ++@pytest.fixture ++def simple_pam_cert_auth_two_certs(request, passwd_ops_setup): ++ """Setup SSSD with pam_cert_auth=True""" ++ config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH'] ++ ++ old_softhsm2_conf = os.environ['SOFTHSM2_CONF'] ++ softhsm2_two_conf = os.environ['SOFTHSM2_TWO_CONF'] ++ os.environ['SOFTHSM2_CONF'] = softhsm2_two_conf ++ ++ conf = format_pam_cert_auth_conf(config, provider_switch(request.param)) ++ create_conf_fixture(request, conf) ++ create_sssd_fixture(request) ++ ++ os.environ['SOFTHSM2_CONF'] = old_softhsm2_conf ++ ++ passwd_ops_setup.useradd(**USER1) ++ passwd_ops_setup.useradd(**USER2) ++ sync_files_provider(USER2['name']) ++ ++ return None ++ ++ + @pytest.fixture + def simple_pam_cert_auth_name_format(request, passwd_ops_setup): + """Setup SSSD with pam_cert_auth=True and full_name_format""" +@@ -522,6 +544,54 @@ def test_sc_auth(simple_pam_cert_auth, env_for_sssctl): + assert err.find("pam_authenticate for user [user1]: Success") != -1 + + ++@pytest.mark.parametrize('simple_pam_cert_auth_two_certs', provider_list(), indirect=True) ++def test_sc_auth_two(simple_pam_cert_auth_two_certs, env_for_sssctl): ++ ++ sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", ++ "--action=auth", "--service=pam_sss_service"], ++ universal_newlines=True, ++ env=env_for_sssctl, stdin=subprocess.PIPE, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ ++ try: ++ out, err = sssctl.communicate(input="2\n123456") ++ except Exception: ++ sssctl.kill() ++ out, err = sssctl.communicate() ++ ++ sssctl.stdin.close() ++ sssctl.stdout.close() ++ ++ if sssctl.wait() != 0: ++ raise Exception("sssctl failed") ++ ++ assert err.find("pam_authenticate for user [user1]: Success") != -1 ++ ++ ++@pytest.mark.parametrize('simple_pam_cert_auth_two_certs', provider_list(), indirect=True) ++def test_sc_auth_two_missing_name(simple_pam_cert_auth_two_certs, env_for_sssctl): ++ ++ sssctl = subprocess.Popen(["sssctl", "user-checks", "", ++ "--action=auth", "--service=pam_sss_allow_missing_name"], ++ universal_newlines=True, ++ env=env_for_sssctl, stdin=subprocess.PIPE, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ ++ try: ++ out, err = sssctl.communicate(input="2\n123456") ++ except Exception: ++ sssctl.kill() ++ out, err = sssctl.communicate() ++ ++ sssctl.stdin.close() ++ sssctl.stdout.close() ++ ++ if sssctl.wait() != 0: ++ raise Exception("sssctl failed") ++ ++ assert err.find("pam_authenticate for user [user1]: Success") != -1 ++ ++ + @pytest.mark.parametrize('simple_pam_cert_auth', ['proxy_password'], indirect=True) + def test_sc_proxy_password_fallback(simple_pam_cert_auth, env_for_sssctl): + """ +-- +2.41.0 + diff --git a/SOURCES/0005-sss-client-handle-key-value-in-destructor.patch b/SOURCES/0005-sss-client-handle-key-value-in-destructor.patch new file mode 100644 index 0000000..227157b --- /dev/null +++ b/SOURCES/0005-sss-client-handle-key-value-in-destructor.patch @@ -0,0 +1,50 @@ +From 8bf31924265baf81372fe42580dee4064a642375 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +Reviewed-by: Iker Pedrosa +(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 + diff --git a/SOURCES/0006-krb5-Allow-fallback-between-responder-questions.patch b/SOURCES/0006-krb5-Allow-fallback-between-responder-questions.patch new file mode 100644 index 0000000..f8dda3e --- /dev/null +++ b/SOURCES/0006-krb5-Allow-fallback-between-responder-questions.patch @@ -0,0 +1,104 @@ +From 23849f751315ea218e125f35cd419cce55d27355 Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +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 +Reviewed-by: Iker Pedrosa +(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 + diff --git a/SOURCES/0007-krb5-Add-fallback-password-change-support.patch b/SOURCES/0007-krb5-Add-fallback-password-change-support.patch new file mode 100644 index 0000000..875d831 --- /dev/null +++ b/SOURCES/0007-krb5-Add-fallback-password-change-support.patch @@ -0,0 +1,206 @@ +From 8d9ae754b50dffafef719ad3fa44e5dd1dde47b3 Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +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 +Reviewed-by: Iker Pedrosa +(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 + diff --git a/SOURCES/0008-pam-fix-invalid-if-condition.patch b/SOURCES/0008-pam-fix-invalid-if-condition.patch new file mode 100644 index 0000000..53fccda --- /dev/null +++ b/SOURCES/0008-pam-fix-invalid-if-condition.patch @@ -0,0 +1,30 @@ +From bebb150720620aae97dcae5c11e0b9bea0119b5b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +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 +(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 + diff --git a/SOURCES/0009-krb5-add-OTP-to-krb5-response-selection.patch b/SOURCES/0009-krb5-add-OTP-to-krb5-response-selection.patch new file mode 100644 index 0000000..87fbf45 --- /dev/null +++ b/SOURCES/0009-krb5-add-OTP-to-krb5-response-selection.patch @@ -0,0 +1,185 @@ +From 5b9bc0a1a6116e6fb001c7dce7497854fcdd40c4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +Reviewed-by: Justin Stephenson +(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 + diff --git a/SOURCES/0010-krb5-make-sure-answer_pkinit-use-matching-debug-mess.patch b/SOURCES/0010-krb5-make-sure-answer_pkinit-use-matching-debug-mess.patch new file mode 100644 index 0000000..db83f42 --- /dev/null +++ b/SOURCES/0010-krb5-make-sure-answer_pkinit-use-matching-debug-mess.patch @@ -0,0 +1,119 @@ +From c3725a13ef694c2c34813953153f33ebfbaf1c27 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +Reviewed-by: Justin Stephenson +(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 + diff --git a/SOURCES/0011-krb5-make-prompter-and-pre-auth-debug-message-less-i.patch b/SOURCES/0011-krb5-make-prompter-and-pre-auth-debug-message-less-i.patch new file mode 100644 index 0000000..5126106 --- /dev/null +++ b/SOURCES/0011-krb5-make-prompter-and-pre-auth-debug-message-less-i.patch @@ -0,0 +1,67 @@ +From 87b54bd8448760241e7071a585f95b3e2604355a Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +Reviewed-by: Justin Stephenson +(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 + diff --git a/SOURCES/0012-pam_sss-prefer-Smartcard-authentication.patch b/SOURCES/0012-pam_sss-prefer-Smartcard-authentication.patch new file mode 100644 index 0000000..90e27c9 --- /dev/null +++ b/SOURCES/0012-pam_sss-prefer-Smartcard-authentication.patch @@ -0,0 +1,70 @@ +From d06b4a3eda612d1a54b6bdb3c3b779543bc23b0f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 +Reviewed-by: Justin Stephenson +(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 + diff --git a/SOURCES/0013-pam-fix-storing-auth-types-for-offline-auth.patch b/SOURCES/0013-pam-fix-storing-auth-types-for-offline-auth.patch new file mode 100644 index 0000000..e9220d5 --- /dev/null +++ b/SOURCES/0013-pam-fix-storing-auth-types-for-offline-auth.patch @@ -0,0 +1,57 @@ +From 163db8465e815984abac0ba9af097589045791da Mon Sep 17 00:00:00 2001 +From: Sumit Bose +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 + diff --git a/SOURCES/0014-ad-gpo-use-hash-to-store-intermediate-results.patch b/SOURCES/0014-ad-gpo-use-hash-to-store-intermediate-results.patch new file mode 100644 index 0000000..5bb0332 --- /dev/null +++ b/SOURCES/0014-ad-gpo-use-hash-to-store-intermediate-results.patch @@ -0,0 +1,218 @@ +From e1bfbc2493c4194988acc3b2413df3dde0735ae3 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 8 Nov 2023 14:50:24 +0100 +Subject: [PATCH] ad-gpo: use hash to store intermediate results +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently after the evaluation of a single GPO file the intermediate +results are stored in the cache and this cache entry is updated until +all applicable GPO files are evaluated. Finally the data in the cache is +used to make the decision of access is granted or rejected. + +If there are two or more access-control request running in parallel one +request might overwrite the cache object with intermediate data while +another request reads the cached data for the access decision and as a +result will do this decision based on intermediate data. + +To avoid this the intermediate results are not stored in the cache +anymore but in hash tables which are specific to the request. Only the +final result is written to the cache to have it available for offline +authentication. + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Tomáš Halman +(cherry picked from commit d7db7971682da2dbf7642ac94940d6b0577ec35a) +--- + src/providers/ad/ad_gpo.c | 116 +++++++++++++++++++++++++++++++++----- + 1 file changed, 102 insertions(+), 14 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index 3d1ad39c7..b879b0a08 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -1431,6 +1431,33 @@ ad_gpo_extract_policy_setting(TALLOC_CTX *mem_ctx, + return ret; + } + ++static errno_t ++add_result_to_hash(hash_table_t *hash, const char *key, char *value) ++{ ++ int hret; ++ hash_key_t k; ++ hash_value_t v; ++ ++ if (hash == NULL || key == NULL || value == NULL) { ++ return EINVAL; ++ } ++ ++ k.type = HASH_KEY_CONST_STRING; ++ k.c_str = key; ++ ++ v.type = HASH_VALUE_PTR; ++ v.ptr = value; ++ ++ hret = hash_enter(hash, &k, &v); ++ if (hret != HASH_SUCCESS) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to add [%s][%s] to hash: [%s].\n", ++ key, value, hash_error_string(hret)); ++ return EIO; ++ } ++ ++ return EOK; ++} ++ + /* + * This function parses the cse-specific (GP_EXT_GUID_SECURITY) filename, + * and stores the allow_key and deny_key of all of the gpo_map_types present +@@ -1438,6 +1465,7 @@ ad_gpo_extract_policy_setting(TALLOC_CTX *mem_ctx, + */ + static errno_t + ad_gpo_store_policy_settings(struct sss_domain_info *domain, ++ hash_table_t *allow_maps, hash_table_t *deny_maps, + const char *filename) + { + struct ini_cfgfile *file_ctx = NULL; +@@ -1571,14 +1599,14 @@ ad_gpo_store_policy_settings(struct sss_domain_info *domain, + goto done; + } else if (ret != ENOENT) { + const char *value = allow_value ? allow_value : empty_val; +- ret = sysdb_gpo_store_gpo_result_setting(domain, +- allow_key, +- value); ++ ret = add_result_to_hash(allow_maps, allow_key, ++ talloc_strdup(allow_maps, value)); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "sysdb_gpo_store_gpo_result_setting failed for key:" +- "'%s' value:'%s' [%d][%s]\n", allow_key, allow_value, +- ret, sss_strerror(ret)); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add key: [%s] " ++ "value: [%s] to allow maps " ++ "[%d][%s].\n", ++ allow_key, value, ret, ++ sss_strerror(ret)); + goto done; + } + } +@@ -1598,14 +1626,14 @@ ad_gpo_store_policy_settings(struct sss_domain_info *domain, + goto done; + } else if (ret != ENOENT) { + const char *value = deny_value ? deny_value : empty_val; +- ret = sysdb_gpo_store_gpo_result_setting(domain, +- deny_key, +- value); ++ ret = add_result_to_hash(deny_maps, deny_key, ++ talloc_strdup(deny_maps, value)); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "sysdb_gpo_store_gpo_result_setting failed for key:" +- "'%s' value:'%s' [%d][%s]\n", deny_key, deny_value, +- ret, sss_strerror(ret)); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add key: [%s] " ++ "value: [%s] to deny maps " ++ "[%d][%s].\n", ++ deny_key, value, ret, ++ sss_strerror(ret)); + goto done; + } + } +@@ -1902,6 +1930,8 @@ struct ad_gpo_access_state { + int num_cse_filtered_gpos; + int cse_gpo_index; + const char *ad_domain; ++ hash_table_t *allow_maps; ++ hash_table_t *deny_maps; + }; + + static void ad_gpo_connect_done(struct tevent_req *subreq); +@@ -2023,6 +2053,19 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, + goto immediately; + } + ++ ret = sss_hash_create(state, 0, &state->allow_maps); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Could not create allow maps " ++ "hash table [%d]: %s\n", ret, sss_strerror(ret)); ++ goto immediately; ++ } ++ ++ ret = sss_hash_create(state, 0, &state->deny_maps); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Could not create deny maps " ++ "hash table [%d]: %s\n", ret, sss_strerror(ret)); ++ goto immediately; ++ } + + subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); + if (subreq == NULL) { +@@ -2713,6 +2756,43 @@ ad_gpo_cse_step(struct tevent_req *req) + return EAGAIN; + } + ++static errno_t ++store_hash_maps_in_cache(struct sss_domain_info *domain, ++ hash_table_t *allow_maps, hash_table_t *deny_maps) ++{ ++ int ret; ++ struct hash_iter_context_t *iter; ++ hash_entry_t *entry; ++ size_t c; ++ hash_table_t *hash_list[] = { allow_maps, deny_maps, NULL}; ++ ++ ++ for (c = 0; hash_list[c] != NULL; c++) { ++ iter = new_hash_iter_context(hash_list[c]); ++ if (iter == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to create hash iterator.\n"); ++ return EINVAL; ++ } ++ ++ while ((entry = iter->next(iter)) != NULL) { ++ ret = sysdb_gpo_store_gpo_result_setting(domain, ++ entry->key.c_str, ++ entry->value.ptr); ++ if (ret != EOK) { ++ free(iter); ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_gpo_store_gpo_result_setting failed for key:" ++ "[%s] value:[%s] [%d][%s]\n", entry->key.c_str, ++ (char *) entry->value.ptr, ret, sss_strerror(ret)); ++ return ret; ++ } ++ } ++ talloc_free(iter); ++ } ++ ++ return EOK; ++} ++ + /* + * This cse-specific function (GP_EXT_GUID_SECURITY) increments the + * cse_gpo_index until the policy settings for all applicable GPOs have been +@@ -2754,6 +2834,7 @@ ad_gpo_cse_done(struct tevent_req *subreq) + * (as part of the GPO Result object in the sysdb cache). + */ + ret = ad_gpo_store_policy_settings(state->host_domain, ++ state->allow_maps, state->deny_maps, + cse_filtered_gpo->policy_filename); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, +@@ -2767,6 +2848,13 @@ ad_gpo_cse_done(struct tevent_req *subreq) + + if (ret == EOK) { + /* ret is EOK only after all GPO policy files have been downloaded */ ++ ret = store_hash_maps_in_cache(state->host_domain, ++ state->allow_maps, state->deny_maps); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to store evaluated GPO maps " ++ "[%d][%s].\n", ret, sss_strerror(ret)); ++ goto done; ++ } + ret = ad_gpo_perform_hbac_processing(state, + state->gpo_mode, + state->gpo_map_type, +-- +2.44.0 + diff --git a/SOURCES/0015-tests-Drop-extensions-from-openssl-command-if-there-.patch b/SOURCES/0015-tests-Drop-extensions-from-openssl-command-if-there-.patch new file mode 100644 index 0000000..e7ddccc --- /dev/null +++ b/SOURCES/0015-tests-Drop-extensions-from-openssl-command-if-there-.patch @@ -0,0 +1,49 @@ +From a453f9625b40a0a1fbcf055ffa196121f2b248b5 Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +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 + +Reviewed-by: Sumit Bose +(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 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 372efda..bc684b2 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -26,16 +26,29 @@ %global samba_package_version %(rpm -q samba-devel --queryformat %{version}-%{release}) Name: sssd -Version: 2.9.1 -Release: 2%{?dist} +Version: 2.9.4 +Release: 6%{?dist} Summary: System Security Services Daemon License: GPLv3+ URL: https://github.com/SSSD/sssd/ Source0: https://github.com/SSSD/sssd/releases/download/%{version}/sssd-%{version}.tar.gz ### Patches ### -Patch0001: 0001-watchdog-add-arm_watchdog-and-disarm_watchdog-calls.patch -Patch0002: 0002-sbus-arm-watchdog-for-sbus_connect_init_send.patch +Patch0001: 0001-sssd-adding-mail-as-case-insensitive.patch +Patch0002: 0002-sdap-add-search_bases-option-to-groups_by_user_send.patch +Patch0003: 0003-sdap-add-naming_context-as-new-member-of-struct-sdap.patch +Patch0004: 0004-pam-fix-SC-auth-with-multiple-certs-and-missing-logi.patch +Patch0005: 0005-sss-client-handle-key-value-in-destructor.patch +Patch0006: 0006-krb5-Allow-fallback-between-responder-questions.patch +Patch0007: 0007-krb5-Add-fallback-password-change-support.patch +Patch0008: 0008-pam-fix-invalid-if-condition.patch +Patch0009: 0009-krb5-add-OTP-to-krb5-response-selection.patch +Patch0010: 0010-krb5-make-sure-answer_pkinit-use-matching-debug-mess.patch +Patch0011: 0011-krb5-make-prompter-and-pre-auth-debug-message-less-i.patch +Patch0012: 0012-pam_sss-prefer-Smartcard-authentication.patch +Patch0013: 0013-pam-fix-storing-auth-types-for-offline-auth.patch +Patch0014: 0014-ad-gpo-use-hash-to-store-intermediate-results.patch +Patch0015: 0015-tests-Drop-extensions-from-openssl-command-if-there-.patch ### Dependencies ### @@ -85,6 +98,7 @@ BuildRequires: krb5-devel BuildRequires: krb5-libs >= 1.18.2-11 BuildRequires: libcmocka-devel >= 1.0.0 BuildRequires: libdhash-devel >= 0.4.2 +BuildRequires: libfido2-devel BuildRequires: libini_config-devel >= 1.1 BuildRequires: libldb-devel >= %{ldb_version} BuildRequires: libnfsidmap-devel @@ -325,6 +339,7 @@ identity data from and authenticate against an Active Directory server. Summary: The proxy back end of the SSSD License: GPLv3+ Requires: sssd-common = %{version}-%{release} +Requires: libsss_certmap = %{version}-%{release} %description proxy Provides the proxy back end which can be used to wrap an existing NSS and/or @@ -493,6 +508,16 @@ This package provides Kerberos plugins that are required to enable authentication against external identity providers. Additionally a helper program to handle the OAuth 2.0 Device Authorization Grant is provided. +%package passkey +Summary: SSSD helpers and plugins needed for authentication with passkey token +License: GPLv3+ +Requires: sssd-common = %{version}-%{release} +Requires: libfido2 + +%description passkey +This package provides helper processes and Kerberos plugins that are required to +enable authentication with passkey token. + %prep %autosetup -p1 @@ -524,6 +549,7 @@ autoreconf -ivf --with-subid \ --with-files-provider \ --with-libsifp \ + --with-passkey \ %if 0%{?fedora} --disable-polkit-rules-path \ %endif @@ -568,6 +594,10 @@ cp $RPM_BUILD_ROOT/%{_datadir}/sssd-kcm/kcm_default_ccache \ cp $RPM_BUILD_ROOT/%{_datadir}/sssd/krb5-snippets/sssd_enable_idp \ $RPM_BUILD_ROOT/%{_sysconfdir}/krb5.conf.d/sssd_enable_idp +# Enable krb5 passkey plugins by default (when sssd-passkey package is installed) +cp $RPM_BUILD_ROOT/%{_datadir}/sssd/krb5-snippets/sssd_enable_passkey \ + $RPM_BUILD_ROOT/%{_sysconfdir}/krb5.conf.d/sssd_enable_passkey + # krb5 configuration snippet cp $RPM_BUILD_ROOT/%{_datadir}/sssd/krb5-snippets/enable_sssd_conf_dir \ $RPM_BUILD_ROOT/%{_sysconfdir}/krb5.conf.d/enable_sssd_conf_dir @@ -973,6 +1003,12 @@ done %{_datadir}/sssd/krb5-snippets/sssd_enable_idp %config(noreplace) %{_sysconfdir}/krb5.conf.d/sssd_enable_idp +%files passkey +%attr(755,%{sssd_user},%{sssd_user}) %{_libexecdir}/%{servicename}/passkey_child +%{_libdir}/%{name}/modules/sssd_krb5_passkey_plugin.so +%{_datadir}/sssd/krb5-snippets/sssd_enable_passkey +%config(noreplace) %{_sysconfdir}/krb5.conf.d/sssd_enable_passkey + %if 0%{?rhel} %pre common getent group sssd >/dev/null || groupadd -r sssd @@ -1062,6 +1098,53 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Thu Apr 18 2024 Alexey Tikhonov - 2.9.4-6 +- Resolves: RHEL-27209 - Race condition during authorization leads to GPO policies functioning inconsistently [rhel-9.4.0] + +* Mon Mar 25 2024 Alexey Tikhonov - 2.9.4-5 +- Resolves: RHEL-28161 - Passkey cannot fall back to password + +* Thu Mar 21 2024 Alexey Tikhonov - 2.9.4-4 +- Resolves: RHEL-28161 - Passkey cannot fall back to password + +* Wed Mar 13 2024 Alexey Tikhonov - 2.9.4-3 +- Resolves: RHEL-22340 - socket leak +- Resolves: RHEL-28161 - Passkey cannot fall back to password + +* Mon Feb 12 2024 Alexey Tikhonov - 2.9.4-2 +- Resolves: RHEL-12503 - AD users are unable to log in due to case sensitivity of user because the domain is found as an alias to the email address. +- Resolves: RHEL-22288 - ssh pubkey stored in ldap/AD no longer works to authenticate via sssd +- Resolves: RHEL-22194 - gdm smartcard login fails with sssd-2.9.3 in case of multiple identities + +* Fri Jan 12 2024 Alexey Tikhonov - 2.9.4-1 +- Resolves: RHEL-2632 - Rebase SSSD for RHEL 9.4 +- Resolves: RHEL-18395 - latest sssd breaks logging in via XDMCP for LDAP/Kerberos users +- Resolves: RHEL-17498 - New sssd.conf seems not to be backwards compatible (wrt SmartCard auth of local users using 'files provider') [rhel-9] +- Resolves: RHEL-21079 - SSSD GPO lacks group resolution on hosts [rhel-9] +- Resolves: RHEL-19211 - Excessive logging to sssd_nss and sssd_be in multi-domain AD forest [rhel-9] + +* Mon Nov 13 2023 Alexey Tikhonov - 2.9.3-2 +- Resolves: RHEL-2632 - Rebase SSSD for RHEL 9.4 + +* Mon Nov 13 2023 Alexey Tikhonov - 2.9.3-1 +- Resolves: RHEL-2632 - Rebase SSSD for RHEL 9.4 +- Resolves: RHEL-14427 - Expected cn in RDN, got uid +- Resolves: RHEL-12229 - HANA validation on RHEL 9.2 issue possibly related to libc/nss_sss behaviour +- Resolves: RHEL-3925 - SSSD goes offline when, while reading a single user, misses a required attribute (i.e. SID) +- Resolves: RHEL-2319 - Passkey authentication for centrally managed users +- Resolves: RHEL-4146 - Incorrect handling of reverse IPv6 update results in update failure +- Resolves: RHEL-4971 - sssd-kcm does not appear to expire Kerberos tickets (RFE: sssd_kcm should have the option to automatically delete the expired tickets) + +* Thu Oct 5 2023 Alexey Tikhonov - 2.9.2-2 +- Resolves: RHEL-2319 - Passkey authentication for centrally managed users + +* Fri Sep 8 2023 Alexey Tikhonov - 2.9.2-1 +- Resolves: RHEL-2632 - Rebase SSSD for RHEL 9.4 +- Resolves: RHEL-2319 - Passkey authentication for centrally managed users +- Resolves: rhbz#2234829 - SSSD runs multiples lookup search for each NFS request (SBUS req chaining stopped working) +- Resolves: rhbz#2236119 - dbus and crond getting terminated with SIGBUS in sss_client code + + * Mon Jul 10 2023 Alexey Tikhonov - 2.9.1-2 - Resolves: rhbz#2218858 - [sssd] SSSD enters failed state after heavy load in the system