diff --git a/SOURCES/0007-failover-add-failover_primary_timeout-option.patch b/SOURCES/0007-failover-add-failover_primary_timeout-option.patch new file mode 100644 index 0000000..c24ca1c --- /dev/null +++ b/SOURCES/0007-failover-add-failover_primary_timeout-option.patch @@ -0,0 +1,306 @@ +From 14f32f681a25aac185d72bc6d22a9e3b59dd265a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 30 Apr 2024 12:28:53 +0200 +Subject: [PATCH] failover: add failover_primary_timeout option + +This was previously hardcoded to 31 seconds (hardcoded retry_timout + +1). This may be too short period under some circumstances. + +When we retry primary server we drop connection to the backup server and +if the primary server is not yet available (and there are many +unavailable primary servers) we may go through a long timeout cycle +every half minute. + +This patch makes the value configurable. + +:config: Added `failover_primary_timout` configuration option. This + can be used to configure how often SSSD tries to reconnect to a + primary server after a successful connection to a backup server. + This was previously hardcoded to 31 seconds which is kept as + the default value. + +Resolves: https://github.com/SSSD/sssd/issues/7375 + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Iker Pedrosa +(cherry picked from commit e9738e36937e78f80bb2772c48cffbddf39bd5fe) +--- + src/config/SSSDConfig/sssdoptions.py | 2 + + src/config/SSSDConfigTest.py | 2 + + src/config/cfg_rules.ini | 1 + + src/config/etc/sssd.api.conf | 1 + + src/man/sssd.conf.5.xml | 19 ++++++++ + src/providers/data_provider.h | 1 + + src/providers/data_provider_fo.c | 14 +++++- + src/providers/fail_over.c | 10 +++++ + src/providers/fail_over.h | 3 ++ + src/tests/system/tests/test_failover.py | 59 +++++++++++++++++++++++++ + 10 files changed, 110 insertions(+), 2 deletions(-) + create mode 100644 src/tests/system/tests/test_failover.py + +diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py +index 0d75e6d82..95b39aa59 100644 +--- a/src/config/SSSDConfig/sssdoptions.py ++++ b/src/config/SSSDConfig/sssdoptions.py +@@ -186,6 +186,8 @@ class SSSDOptions(object): + 'dns_resolver_op_timeout': _('How long should keep trying to resolve single DNS query (seconds)'), + 'dns_resolver_timeout': _('How long to wait for replies from DNS when resolving servers (seconds)'), + 'dns_discovery_domain': _('The domain part of service discovery DNS query'), ++ 'failover_primary_timeout': _('How often SSSD tries to reconnect to the primary server after a successful ' ++ 'connection to the backup server.'), + 'override_gid': _('Override GID value from the identity provider with this value'), + 'case_sensitive': _('Treat usernames as case sensitive'), + 'entry_cache_user_timeout': _('Entry cache timeout length (seconds)'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index b160be2b1..f333c35eb 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -579,6 +579,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'dns_resolver_op_timeout', + 'dns_resolver_timeout', + 'dns_discovery_domain', ++ 'failover_primary_timeout', + 'dyndns_update', + 'dyndns_ttl', + 'dyndns_iface', +@@ -939,6 +940,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'dns_resolver_op_timeout', + 'dns_resolver_timeout', + 'dns_discovery_domain', ++ 'failover_primary_timeout', + 'dyndns_update', + 'dyndns_ttl', + 'dyndns_iface', +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 92e87fb18..4c2ea0b87 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -405,6 +405,7 @@ option = dns_resolver_op_timeout + option = dns_resolver_timeout + option = dns_resolver_use_search_list + option = dns_discovery_domain ++option = failover_primary_timeout + option = override_gid + option = case_sensitive + option = override_homedir +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index 5ae6aab19..31787c23c 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -172,6 +172,7 @@ dns_resolver_server_timeout = int, None, false + dns_resolver_op_timeout = int, None, false + dns_resolver_timeout = int, None, false + dns_discovery_domain = str, None, false ++failover_primary_timeout = int, None, false + override_gid = int, None, false + case_sensitive = str, None, false + override_homedir = str, None, false +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index 339f21e25..fbb82e357 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -3773,6 +3773,25 @@ pam_gssapi_indicators_map = sudo:pkinit, sudo-i:pkinit + + + ++ ++ failover_primary_timeout (integer) ++ ++ ++ When no primary server is currently available, ++ SSSD fail overs to a backup server. This option ++ defines the amount of time (in seconds) to ++ wait before SSSD tries to reconnect to a primary ++ server again. ++ ++ ++ Note: The minimum value is 31. ++ ++ ++ Default: 31 ++ ++ ++ ++ + + override_gid (integer) + +diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h +index 36a82b84d..def35e491 100644 +--- a/src/providers/data_provider.h ++++ b/src/providers/data_provider.h +@@ -267,6 +267,7 @@ enum dp_res_opts { + DP_RES_OPT_RESOLVER_SERVER_TIMEOUT, + DP_RES_OPT_RESOLVER_USE_SEARCH_LIST, + DP_RES_OPT_DNS_DOMAIN, ++ DP_RES_OPT_FAILOVER_PRIMARY_TIMEOUT, + + DP_RES_OPTS /* attrs counter */ + }; +diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c +index b0aed54e9..c23f92e35 100644 +--- a/src/providers/data_provider_fo.c ++++ b/src/providers/data_provider_fo.c +@@ -48,10 +48,20 @@ static int be_fo_get_options(struct be_ctx *ctx, + DP_RES_OPT_RESOLVER_TIMEOUT); + opts->use_search_list = dp_opt_get_bool(ctx->be_res->opts, + DP_RES_OPT_RESOLVER_USE_SEARCH_LIST); ++ opts->primary_timeout = dp_opt_get_int(ctx->be_res->opts, ++ DP_RES_OPT_FAILOVER_PRIMARY_TIMEOUT); ++ + opts->retry_timeout = 30; + opts->srv_retry_neg_timeout = 15; + opts->family_order = ctx->be_res->family_order; + ++ if (opts->primary_timeout <= opts->retry_timeout) { ++ opts->primary_timeout = opts->retry_timeout + 1; ++ DEBUG(SSSDBG_CONF_SETTINGS, ++ "Warning: failover_primary_timeout is too low, using %lu " ++ "seconds instead\n", opts->primary_timeout); ++ } ++ + return EOK; + } + +@@ -551,7 +561,7 @@ static void be_resolve_server_done(struct tevent_req *subreq) + struct tevent_req); + struct be_resolve_server_state *state = tevent_req_data(req, + struct be_resolve_server_state); +- time_t timeout = fo_get_service_retry_timeout(state->svc->fo_service) + 1; ++ time_t timeout = fo_get_primary_retry_timeout(state->svc->fo_service); + int ret; + + ret = be_resolve_server_process(subreq, state, &new_subreq); +@@ -564,7 +574,6 @@ static void be_resolve_server_done(struct tevent_req *subreq) + } + + if (!fo_is_server_primary(state->srv)) { +- /* FIXME: make the timeout configurable */ + ret = be_primary_server_timeout_activate(state->ctx, state->ev, + state->ctx, state->svc, + timeout); +@@ -871,6 +880,7 @@ static struct dp_option dp_res_default_opts[] = { + { "dns_resolver_server_timeout", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER }, + { "dns_resolver_use_search_list", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "dns_discovery_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, ++ { "failover_primary_timeout", DP_OPT_NUMBER, { .number = 31 }, NULL_NUMBER }, + DP_OPTION_TERMINATOR + }; + +diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c +index 7cb642448..7f94407c5 100644 +--- a/src/providers/fail_over.c ++++ b/src/providers/fail_over.c +@@ -158,6 +158,7 @@ fo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts) + + ctx->opts->srv_retry_neg_timeout = opts->srv_retry_neg_timeout; + ctx->opts->retry_timeout = opts->retry_timeout; ++ ctx->opts->primary_timeout = opts->primary_timeout; + ctx->opts->family_order = opts->family_order; + ctx->opts->service_resolv_timeout = opts->service_resolv_timeout; + ctx->opts->use_search_list = opts->use_search_list; +@@ -1740,6 +1741,15 @@ time_t fo_get_service_retry_timeout(struct fo_service *svc) + return svc->ctx->opts->retry_timeout; + } + ++time_t fo_get_primary_retry_timeout(struct fo_service *svc) ++{ ++ if (svc == NULL || svc->ctx == NULL || svc->ctx->opts == NULL) { ++ return 0; ++ } ++ ++ return svc->ctx->opts->primary_timeout; ++} ++ + bool fo_get_use_search_list(struct fo_server *server) + { + if ( +diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h +index 36021ad6f..924a09970 100644 +--- a/src/providers/fail_over.h ++++ b/src/providers/fail_over.h +@@ -83,6 +83,7 @@ struct fo_server; + struct fo_options { + time_t srv_retry_neg_timeout; + time_t retry_timeout; ++ time_t primary_timeout; + int service_resolv_timeout; + bool use_search_list; + enum restrict_family family_order; +@@ -211,6 +212,8 @@ int fo_is_srv_lookup(struct fo_server *s); + + time_t fo_get_service_retry_timeout(struct fo_service *svc); + ++time_t fo_get_primary_retry_timeout(struct fo_service *svc); ++ + bool fo_get_use_search_list(struct fo_server *server); + + void fo_reset_services(struct fo_ctx *fo_ctx); +diff --git a/src/tests/system/tests/test_failover.py b/src/tests/system/tests/test_failover.py +new file mode 100644 +index 000000000..565cec9bc +--- /dev/null ++++ b/src/tests/system/tests/test_failover.py +@@ -0,0 +1,59 @@ ++""" ++SSSD Failover tests. ++ ++:requirement: Failover ++""" ++ ++from __future__ import annotations ++ ++import pytest ++from sssd_test_framework.roles.client import Client ++from sssd_test_framework.roles.ldap import LDAP ++from sssd_test_framework.topology import KnownTopology ++ ++ ++@pytest.mark.parametrize("value, expected", [(None, 31), (15, 31), (60, 60)]) ++@pytest.mark.importance("low") ++@pytest.mark.ticket(gh=7375, jira="RHEL-17659") ++@pytest.mark.topology(KnownTopology.LDAP) ++def test_failover__retry_primary(client: Client, ldap: LDAP, value: int | None, expected: int): ++ """ ++ :title: Primary server reactivation timeout is respected ++ :setup: ++ 1. Create LDAP user "user-1" ++ 2. Set failover_primary_timeout to @value ++ 3. Set ldap_uri to invalid, not working server ++ 4. Set ldap_backup_uri to working server ++ 5. Start SSSD ++ :steps: ++ 1. Lookup user-1 ++ 2. Check that SSSD is connected to backup server ++ 3. Find "Primary server reactivation timeout set to @expected seconds" in domain logs ++ :expectedresults: ++ 1. SSSD failover to backup server ++ 2. SSSD is indeed connected to the backup server ++ 3. String is found ++ :customerscenario: True ++ """ ++ ldap.user("user-1").add() ++ ++ if value is not None: ++ client.sssd.domain["failover_primary_timeout"] = str(value) ++ ++ client.sssd.enable_responder("ifp") ++ client.sssd.domain["ldap_uri"] = "ldap://ldap.invalid" ++ client.sssd.domain["ldap_backup_uri"] = f"ldap://{ldap.host.hostname}" ++ client.sssd.start() ++ ++ # Lookup user to make sure SSSD did correctly failover to backup server ++ result = client.tools.id("user-1") ++ assert result is not None ++ ++ # Check that SSSD is indeed connected to backup server ++ assert client.sssd.default_domain is not None ++ status = client.sssctl.domain_status(client.sssd.default_domain, active=True) ++ assert ldap.host.hostname in status.stdout ++ ++ # Check that primary server reactivation timeout was correctly created ++ log = client.fs.read(client.sssd.logs.domain()) ++ assert f"Primary server reactivation timeout set to {expected} seconds" in log +-- +2.46.0 + diff --git a/SOURCES/0008-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch b/SOURCES/0008-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch new file mode 100644 index 0000000..2375fc1 --- /dev/null +++ b/SOURCES/0008-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch @@ -0,0 +1,35 @@ +From 5fc4540e97625a23f2573b0804a1509cf46931c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20L=C3=B3pez?= +Date: Thu, 14 Nov 2024 17:27:49 +0100 +Subject: [PATCH 08/15] OPTS: Add the option for DP_OPT_DYNDNS_REFRESH_OFFSET + +The label `DP_OPT_DYNDNS_REFRESH_OFFSET` was introduced in +https://github.com/SSSD/sssd/blob/fb91349cfeba653942b32141f890e3de78b3fb13/src/providers/be_dyndns.h#L55 +but the corresponding option is missing in +https://github.com/SSSD/sssd/blob/fb91349cfeba653942b32141f890e3de78b3fb13/src/providers/be_dyndns.c#L1200 + +This error was introduced by +https://github.com/SSSD/sssd/commit/35c35de42012481a6bd2690d12d5d11a4ae23ea5 + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Sumit Bose +(cherry picked from commit 9ee10f98e0070774e0e7f0794bc296ef06a671e4) +--- + src/providers/be_dyndns.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/providers/be_dyndns.c b/src/providers/be_dyndns.c +index 2c655ef1e..5d0f51119 100644 +--- a/src/providers/be_dyndns.c ++++ b/src/providers/be_dyndns.c +@@ -1201,6 +1201,7 @@ static struct dp_option default_dyndns_opts[] = { + { "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_update_per_family", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "dyndns_refresh_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, ++ { "dyndns_refresh_interval_offset", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, + { "dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER }, + { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE }, +-- +2.46.1 + diff --git a/SOURCES/0009-TESTS-Also-test-default_dyndns_opts.patch b/SOURCES/0009-TESTS-Also-test-default_dyndns_opts.patch new file mode 100644 index 0000000..2f7cb8f --- /dev/null +++ b/SOURCES/0009-TESTS-Also-test-default_dyndns_opts.patch @@ -0,0 +1,69 @@ +From b34aa979919ec6f3d73e3229c5ad3ab88bc5028a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20L=C3=B3pez?= +Date: Thu, 14 Nov 2024 18:46:44 +0100 +Subject: [PATCH 09/15] TESTS: Also test default_dyndns_opts + +Compare this structure to ipa_dyndns_opts, which is already compared +to ad_dyndns_opts. + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Sumit Bose +(cherry picked from commit 2c72834e657197012b3a32207ffe307e8ba5f9e2) +--- + src/providers/be_dyndns.c | 2 +- + src/providers/be_dyndns.h | 1 + + src/tests/ipa_ldap_opt-tests.c | 6 ++++++ + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/providers/be_dyndns.c b/src/providers/be_dyndns.c +index 5d0f51119..e6fa7dfd6 100644 +--- a/src/providers/be_dyndns.c ++++ b/src/providers/be_dyndns.c +@@ -1197,7 +1197,7 @@ be_nsupdate_check(void) + return ret; + } + +-static struct dp_option default_dyndns_opts[] = { ++struct dp_option default_dyndns_opts[] = { + { "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_update_per_family", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "dyndns_refresh_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, +diff --git a/src/providers/be_dyndns.h b/src/providers/be_dyndns.h +index 2185fee95..719c13942 100644 +--- a/src/providers/be_dyndns.h ++++ b/src/providers/be_dyndns.h +@@ -63,6 +63,7 @@ enum dp_dyndns_opts { + + DP_OPT_DYNDNS /* attrs counter */ + }; ++extern struct dp_option default_dyndns_opts[DP_OPT_DYNDNS + 1]; + + #define DYNDNS_REMOVE_A 0x1 + #define DYNDNS_REMOVE_AAAA 0x2 +diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c +index a1a0e9cc6..da990acaf 100644 +--- a/src/tests/ipa_ldap_opt-tests.c ++++ b/src/tests/ipa_ldap_opt-tests.c +@@ -103,6 +103,10 @@ START_TEST(test_compare_opts) + ret = compare_dp_options(ipa_dyndns_opts, DP_OPT_DYNDNS, + ad_dyndns_opts); + ck_assert_msg(ret == EOK, "[%s]", strerror(ret)); ++ ++ ret = compare_dp_options(ipa_dyndns_opts, DP_OPT_DYNDNS, ++ default_dyndns_opts); ++ ck_assert_msg(ret == EOK, "[%s]", strerror(ret)); + } + END_TEST + +@@ -200,6 +204,8 @@ START_TEST(test_dp_opt_sentinel) + + fail_unless_dp_opt_is_terminator(&default_krb5_opts[KRB5_OPTS]); + ++ fail_unless_dp_opt_is_terminator(&default_dyndns_opts[DP_OPT_DYNDNS]); ++ + fail_unless_dp_opt_is_terminator(&ad_basic_opts[AD_OPTS_BASIC]); + fail_unless_dp_opt_is_terminator(&ad_def_ldap_opts[SDAP_OPTS_BASIC]); + fail_unless_dp_opt_is_terminator(&ad_def_krb5_opts[KRB5_OPTS]); +-- +2.46.1 + diff --git a/SOURCES/0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch b/SOURCES/0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch new file mode 100644 index 0000000..c304253 --- /dev/null +++ b/SOURCES/0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch @@ -0,0 +1,310 @@ +From ebbde00722489c51cfcc70aa6550ed6ea4b97ff8 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 6 Sep 2024 14:27:19 +0200 +Subject: [PATCH 10/15] sdap: allow to provide user_map when looking up group + memberships +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To allow to lookup group memberships of other objects similar to user +objects but with different attribute mappings, e.g. host objects in AD, +a new option to provide an alternative attribute map is added. + +Resolves: https://github.com/SSSD/sssd/issues/7590 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +(cherry picked from commit 69f63f1fa64bd9cc7c2ee1f8e8d736727b13b3be) +(cherry picked from commit 321ca19ae09609ac4195f323b696bdcd7ee573e4) + +Reviewed-by: Justin Stephenson +--- + src/providers/ad/ad_gpo.c | 2 +- + src/providers/ldap/ldap_common.h | 2 + + src/providers/ldap/ldap_id.c | 9 ++++ + src/providers/ldap/sdap_async.h | 2 + + src/providers/ldap/sdap_async_initgroups.c | 51 ++++++++++++++-------- + 5 files changed, 48 insertions(+), 18 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index b879b0a08..69dd54f5b 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -2244,7 +2244,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) + search_bases, + state->host_fqdn, + BE_FILTER_NAME, +- NULL, ++ NULL, NULL, 0, + true, + true); + tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req); +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index 2c984ef50..61a35553b 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -308,6 +308,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + bool noexist_delete, + bool set_non_posix); + +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index b3ea2333f..0596ad4cf 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -1144,6 +1144,8 @@ struct groups_by_user_state { + const char *filter_value; + int filter_type; + const char *extra_value; ++ struct sdap_attr_map *user_map; ++ size_t user_map_cnt; + const char **attrs; + bool non_posix; + +@@ -1165,6 +1167,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + bool noexist_delete, + bool set_non_posix) + { +@@ -1192,6 +1196,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + state->filter_value = filter_value; + state->filter_type = filter_type; + state->extra_value = extra_value; ++ state->user_map = user_map; ++ state->user_map_cnt = user_map_cnt; + state->domain = sdom->dom; + state->sysdb = sdom->dom->sysdb; + state->search_bases = search_bases; +@@ -1256,6 +1262,8 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) + state->sdom, + sdap_id_op_handle(state->op), + state->ctx, ++ state->user_map, ++ state->user_map_cnt, + state->conn, + state->search_bases, + state->filter_value, +@@ -1457,6 +1465,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + ar->filter_value, + ar->filter_type, + ar->extra_value, ++ NULL, 0, + noexist_delete, false); + break; + +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index 89245f41f..a45e057d0 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -157,6 +157,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct sdap_domain *sdom, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, + const char *name, +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index fb3d8fe24..8ce1f6cd4 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -785,6 +785,8 @@ struct sdap_initgr_nested_state { + struct tevent_context *ev; + struct sysdb_ctx *sysdb; + struct sdap_options *opts; ++ struct sdap_attr_map *user_map; ++ size_t user_map_cnt; + struct sss_domain_info *dom; + struct sdap_handle *sh; + +@@ -812,6 +814,8 @@ static void sdap_initgr_nested_store(struct tevent_req *req); + static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_options *opts, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_handle *sh, +@@ -828,6 +832,8 @@ static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx, + + state->ev = ev; + state->opts = opts; ++ state->user_map = user_map; ++ state->user_map_cnt = user_map_cnt; + state->sysdb = sysdb; + state->dom = dom; + state->sh = sh; +@@ -968,7 +974,7 @@ static errno_t sdap_initgr_nested_deref_search(struct tevent_req *req) + + subreq = sdap_deref_search_send(state, state->ev, state->opts, + state->sh, state->orig_dn, +- state->opts->user_map[SDAP_AT_USER_MEMBEROF].name, ++ state->user_map[SDAP_AT_USER_MEMBEROF].name, + sdap_attrs, num_maps, maps, timeout); + if (!subreq) { + ret = EIO; +@@ -2697,6 +2703,8 @@ struct sdap_get_initgr_state { + struct tevent_context *ev; + struct sysdb_ctx *sysdb; + struct sdap_options *opts; ++ struct sdap_attr_map *user_map; ++ size_t user_map_cnt; + struct sss_domain_info *dom; + struct sdap_domain *sdom; + struct sdap_handle *sh; +@@ -2731,6 +2739,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + struct sdap_domain *sdom, + struct sdap_handle *sh, + struct sdap_id_ctx *id_ctx, ++ struct sdap_attr_map *user_map, ++ size_t user_map_cnt, + struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, + const char *filter_value, +@@ -2754,6 +2764,12 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + + state->ev = ev; + state->opts = id_ctx->opts; ++ state->user_map = user_map; ++ state->user_map_cnt = user_map_cnt; ++ if (state->user_map == NULL) { ++ state->user_map = id_ctx->opts->user_map; ++ state->user_map_cnt = id_ctx->opts->user_map_cnt; ++ } + state->dom = sdom->dom; + state->sysdb = sdom->dom->sysdb; + state->sdom = sdom; +@@ -2785,7 +2801,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + + switch (filter_type) { + case BE_FILTER_SECID: +- search_attr = state->opts->user_map[SDAP_AT_USER_OBJECTSID].name; ++ search_attr = state->user_map[SDAP_AT_USER_OBJECTSID].name; + + ret = sss_filter_sanitize(state, state->filter_value, &clean_name); + if (ret != EOK) { +@@ -2794,7 +2810,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + } + break; + case BE_FILTER_UUID: +- search_attr = state->opts->user_map[SDAP_AT_USER_UUID].name; ++ search_attr = state->user_map[SDAP_AT_USER_UUID].name; + + ret = sss_filter_sanitize(state, state->filter_value, &clean_name); + if (ret != EOK) { +@@ -2812,23 +2828,23 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + } + + ep_filter = get_enterprise_principal_string_filter(state, +- state->opts->user_map[SDAP_AT_USER_PRINC].name, ++ state->user_map[SDAP_AT_USER_PRINC].name, + clean_name, state->opts->basic); + state->user_base_filter = + talloc_asprintf(state, + "(&(|(%s=%s)(%s=%s)%s)(objectclass=%s)", +- state->opts->user_map[SDAP_AT_USER_PRINC].name, ++ state->user_map[SDAP_AT_USER_PRINC].name, + clean_name, +- state->opts->user_map[SDAP_AT_USER_EMAIL].name, ++ state->user_map[SDAP_AT_USER_EMAIL].name, + clean_name, + ep_filter == NULL ? "" : ep_filter, +- state->opts->user_map[SDAP_OC_USER].name); ++ state->user_map[SDAP_OC_USER].name); + if (state->user_base_filter == NULL) { + talloc_zfree(req); + return NULL; + } + } else { +- search_attr = state->opts->user_map[SDAP_AT_USER_NAME].name; ++ search_attr = state->user_map[SDAP_AT_USER_NAME].name; + + ret = sss_parse_internal_fqname(state, filter_value, + &state->shortname, NULL); +@@ -2860,7 +2876,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + state->user_base_filter = + talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)", + search_attr, clean_name, +- state->opts->user_map[SDAP_OC_USER].name); ++ state->user_map[SDAP_OC_USER].name); + if (!state->user_base_filter) { + talloc_zfree(req); + return NULL; +@@ -2877,14 +2893,14 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + */ + state->user_base_filter = talloc_asprintf_append(state->user_base_filter, + "(%s=*))", +- id_ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name); ++ state->user_map[SDAP_AT_USER_OBJECTSID].name); + } else { + /* When not ID-mapping or looking up app users, make sure there + * is a non-NULL UID */ + state->user_base_filter = talloc_asprintf_append(state->user_base_filter, + "(&(%s=*)(!(%s=0))))", +- id_ctx->opts->user_map[SDAP_AT_USER_UID].name, +- id_ctx->opts->user_map[SDAP_AT_USER_UID].name); ++ state->user_map[SDAP_AT_USER_UID].name, ++ state->user_map[SDAP_AT_USER_UID].name); + } + if (!state->user_base_filter) { + talloc_zfree(req); +@@ -2892,8 +2908,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + } + + ret = build_attrs_from_map(state, +- state->opts->user_map, +- state->opts->user_map_cnt, ++ state->user_map, ++ state->user_map_cnt, + NULL, &state->user_attrs, NULL); + if (ret) { + talloc_zfree(req); +@@ -2990,7 +3006,7 @@ static errno_t sdap_get_initgr_next_base(struct tevent_req *req) + state->user_search_bases[state->user_base_iter]->basedn, + state->user_search_bases[state->user_base_iter]->scope, + state->filter, state->user_attrs, +- state->opts->user_map, state->opts->user_map_cnt, ++ state->user_map, state->user_map_cnt, + state->timeout, + false); + if (!subreq) { +@@ -3179,6 +3195,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) + + case SDAP_SCHEMA_IPA_V1: + subreq = sdap_initgr_nested_send(state, state->ev, state->opts, ++ state->user_map, state->user_map_cnt, + state->sysdb, state->dom, state->sh, + state->orig_user, state->grp_attrs); + if (!subreq) { +@@ -3377,7 +3394,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + */ + ret = sdap_attrs_get_sid_str( + tmp_ctx, opts->idmap_ctx, state->orig_user, +- opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, ++ state->user_map[SDAP_AT_USER_OBJECTSID].sys_name, + &sid_str); + if (ret != EOK) goto done; + +@@ -3392,7 +3409,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + + ret = sysdb_attrs_get_uint32_t( + state->orig_user, +- opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name, ++ state->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name, + &primary_gid); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, +-- +2.46.1 + diff --git a/SOURCES/0011-ad-use-default-user_map-when-looking-of-host-groups-.patch b/SOURCES/0011-ad-use-default-user_map-when-looking-of-host-groups-.patch new file mode 100644 index 0000000..20605e3 --- /dev/null +++ b/SOURCES/0011-ad-use-default-user_map-when-looking-of-host-groups-.patch @@ -0,0 +1,80 @@ +From 9ff2e55000d146381db5f66575e40ada5ecaf0cf Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 6 Sep 2024 14:37:05 +0200 +Subject: [PATCH 11/15] ad: use default user_map when looking of host groups + for GPO +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the default AD user attribute map to lookup the group membership of +the AD host object. This should help to avoid issues if user attributes +are overwritten in the user attribute map. + +Resolves: https://github.com/SSSD/sssd/issues/7590 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +(cherry picked from commit 5f5077ac1158deff6fbb51722d37b9c5f8b05cf7) +(cherry picked from commit 2c233636c093708d5cdd7ddb69af9b0ecde633bd) + +Reviewed-by: Justin Stephenson +--- + src/providers/ad/ad_access.h | 1 + + src/providers/ad/ad_gpo.c | 15 ++++++++++++++- + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ad/ad_access.h b/src/providers/ad/ad_access.h +index 34d5597da..c54b53eed 100644 +--- a/src/providers/ad/ad_access.h ++++ b/src/providers/ad/ad_access.h +@@ -49,6 +49,7 @@ struct ad_access_ctx { + } gpo_map_type; + hash_table_t *gpo_map_options_table; + enum gpo_map_type gpo_default_right; ++ struct sdap_attr_map *host_attr_map; + }; + + struct tevent_req * +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index 69dd54f5b..4e2f06b0d 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -45,6 +45,7 @@ + #include "providers/ad/ad_common.h" + #include "providers/ad/ad_domain_info.h" + #include "providers/ad/ad_gpo.h" ++#include "providers/ad/ad_opts.h" + #include "providers/ldap/sdap_access.h" + #include "providers/ldap/sdap_async.h" + #include "providers/ldap/sdap.h" +@@ -2238,13 +2239,25 @@ ad_gpo_connect_done(struct tevent_req *subreq) + "trying with user search base."); + } + ++ if (state->access_ctx->host_attr_map == NULL) { ++ ret = sdap_copy_map(state->access_ctx, ++ ad_2008r2_user_map, SDAP_OPTS_USER, ++ &state->access_ctx->host_attr_map); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to copy user map.\n"); ++ goto done; ++ } ++ } ++ + 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, NULL, 0, ++ NULL, ++ state->access_ctx->host_attr_map, ++ SDAP_OPTS_USER, + true, + true); + tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req); +-- +2.46.1 + diff --git a/SOURCES/0012-sysdb-do-not-fail-to-add-non-posix-user-to-MPG-domai.patch b/SOURCES/0012-sysdb-do-not-fail-to-add-non-posix-user-to-MPG-domai.patch new file mode 100644 index 0000000..2e8a31c --- /dev/null +++ b/SOURCES/0012-sysdb-do-not-fail-to-add-non-posix-user-to-MPG-domai.patch @@ -0,0 +1,61 @@ +From 0e86f1a53b893a296488d96a432b98458403bcb9 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 14 Jun 2024 16:10:34 +0200 +Subject: [PATCH 12/15] sysdb: do not fail to add non-posix user to MPG domain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SSSD does not handle the root user (UID==0) and treats all accounts with +UID 0 as non-Posix accounts. The primary GID of those accounts is 0 as +well and as a result for those accounts in MPG domains the check for a +collisions of the primary GID should be skipped. The current code might +e.g. cause issues during GPO evaluation when adding a host account into +the cache which does not have any UID or GID set in AD and SSSD is +configured to read UID and GID from AD. + +Resolves: https://github.com/SSSD/sssd/issues/7451 + +Reviewed-by: Alejandro López +Reviewed-by: Tomáš Halman +(cherry picked from commit 986bb726202e69b05f861c14c3a220379baf9bd1) +(cherry picked from commit d234cf5d6e793daf2c96856887acb641c4dff407) + +Reviewed-by: Justin Stephenson +--- + src/db/sysdb_ops.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 3331d4687..fa2d81217 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -1914,15 +1914,17 @@ int sysdb_add_user(struct sss_domain_info *domain, + goto done; + } + +- ret = sysdb_search_group_by_gid(tmp_ctx, domain, uid, NULL, &msg); +- if (ret != ENOENT) { +- if (ret == EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Group with GID [%"SPRIgid"] already exists in an " +- "MPG domain\n", gid); +- ret = EEXIST; ++ if (uid != 0) { /* uid == 0 means non-POSIX object */ ++ ret = sysdb_search_group_by_gid(tmp_ctx, domain, uid, NULL, &msg); ++ if (ret != ENOENT) { ++ if (ret == EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Group with GID [%"SPRIgid"] already exists in an " ++ "MPG domain\n", uid); ++ ret = EEXIST; ++ } ++ goto done; + } +- goto done; + } + } + +-- +2.46.1 + diff --git a/SOURCES/0013-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch b/SOURCES/0013-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch new file mode 100644 index 0000000..67159db --- /dev/null +++ b/SOURCES/0013-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch @@ -0,0 +1,230 @@ +From acd5da528789734411b12fa8b19007b00eea9f2c Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 13 Sep 2024 15:45:59 +0200 +Subject: [PATCH 13/15] ldap: add 'exop_force' value for ldap_pwmodify_mode + +In case the LDAP server allows to run the extended operation to change a +password even if an authenticated bind fails due to missing grace logins +the new option 'exop_force' can be used to run the extended operation to +change the password anyways. + +:config: Added `exop_force` value for configuration option + `ldap_pwmodify_mode`. This can be used to force a password change even + if no grace logins are left. Depending on the configuration of the + LDAP server it might be expected that the password change will fail. + +(cherry picked from commit 72a7fd0ded236a16b00bb4e26221f7e23b702a53) + +Reviewed-by: Justin Stephenson +(cherry picked from commit e3a3f44c4cdcb936b59941636ff576de613366d1) + +Reviewed-by: Justin Stephenson +--- + src/man/sssd-ldap.5.xml | 11 +++++++++ + src/providers/ipa/ipa_auth.c | 3 ++- + src/providers/ldap/ldap_auth.c | 5 +++- + src/providers/ldap/ldap_options.c | 2 ++ + src/providers/ldap/sdap.h | 5 ++-- + src/providers/ldap/sdap_async.h | 3 ++- + src/providers/ldap/sdap_async_connection.c | 27 +++++++++++++++++----- + 7 files changed, 45 insertions(+), 11 deletions(-) + +diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml +index 0a814ec35..a9994aade 100644 +--- a/src/man/sssd-ldap.5.xml ++++ b/src/man/sssd-ldap.5.xml +@@ -234,6 +234,17 @@ + userPassword (not recommended). + + ++ ++ ++ exop_force - Try Password Modify ++ Extended Operation (RFC 3062) even if ++ there are no grace logins left. ++ Depending on the type and configuration ++ of the LDAP server the password change ++ might fail because an authenticated bind ++ is not possible. ++ ++ + + + +diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c +index 1d61a1052..b2e5b6f35 100644 +--- a/src/providers/ipa/ipa_auth.c ++++ b/src/providers/ipa/ipa_auth.c +@@ -381,7 +381,8 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq) + SDAP_OPT_TIMEOUT); + + subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn, +- state->pd->authtok, timeout); ++ state->pd->authtok, timeout, ++ state->auth_ctx->sdap_auth_ctx->opts->pwmodify_mode); + if (subreq == NULL) { + goto done; + } +diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c +index 8ec4d3af5..023ed2277 100644 +--- a/src/providers/ldap/ldap_auth.c ++++ b/src/providers/ldap/ldap_auth.c +@@ -896,7 +896,8 @@ static void auth_do_bind(struct tevent_req *req) + NULL, NULL, state->dn, + state->authtok, + dp_opt_get_int(state->ctx->opts->basic, +- SDAP_OPT_TIMEOUT)); ++ SDAP_OPT_TIMEOUT), ++ state->ctx->opts->pwmodify_mode); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; +@@ -1186,6 +1187,7 @@ sdap_pam_change_password_send(TALLOC_CTX *mem_ctx, + + switch (opts->pwmodify_mode) { + case SDAP_PWMODIFY_EXOP: ++ case SDAP_PWMODIFY_EXOP_FORCE: + subreq = sdap_exop_modify_passwd_send(state, ev, sh, user_dn, + password, new_password, + timeout); +@@ -1229,6 +1231,7 @@ static void sdap_pam_change_password_done(struct tevent_req *subreq) + + switch (state->mode) { + case SDAP_PWMODIFY_EXOP: ++ case SDAP_PWMODIFY_EXOP_FORCE: + ret = sdap_exop_modify_passwd_recv(subreq, state, + &state->user_error_message); + break; +diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c +index 277bcb529..72a95300d 100644 +--- a/src/providers/ldap/ldap_options.c ++++ b/src/providers/ldap/ldap_options.c +@@ -294,6 +294,8 @@ int ldap_get_options(TALLOC_CTX *memctx, + opts->pwmodify_mode = SDAP_PWMODIFY_EXOP; + } else if (strcasecmp(pwmodify, "ldap_modify") == 0) { + opts->pwmodify_mode = SDAP_PWMODIFY_LDAP; ++ } else if (strcasecmp(pwmodify, "exop_force") == 0) { ++ opts->pwmodify_mode = SDAP_PWMODIFY_EXOP_FORCE; + } else { + DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized pwmodify mode: %s\n", pwmodify); + ret = EINVAL; +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index 103d50ed4..cc34c8198 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -546,8 +546,9 @@ struct sdap_options { + + /* password modify mode */ + enum pwmodify_mode { +- SDAP_PWMODIFY_EXOP = 1, /* pwmodify extended operation */ +- SDAP_PWMODIFY_LDAP = 2 /* ldap_modify of userPassword */ ++ SDAP_PWMODIFY_EXOP = 1, /* pwmodify extended operation */ ++ SDAP_PWMODIFY_LDAP = 2, /* ldap_modify of userPassword */ ++ SDAP_PWMODIFY_EXOP_FORCE = 3 /* forced pwmodify extended operation */ + } pwmodify_mode; + + /* The search bases for the domain or its subdomain */ +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index a45e057d0..80b403bc3 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -146,7 +146,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, + const char *sasl_user, + const char *user_dn, + struct sss_auth_token *authtok, +- int simple_bind_timeout); ++ int simple_bind_timeout, ++ enum pwmodify_mode pwmodify_mode); + + errno_t sdap_auth_recv(struct tevent_req *req, + TALLOC_CTX *memctx, +diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c +index e8638725c..992a5798c 100644 +--- a/src/providers/ldap/sdap_async_connection.c ++++ b/src/providers/ldap/sdap_async_connection.c +@@ -643,6 +643,7 @@ struct simple_bind_state { + struct tevent_context *ev; + struct sdap_handle *sh; + const char *user_dn; ++ enum pwmodify_mode pwmodify_mode; + + struct sdap_op *op; + +@@ -659,7 +660,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, + struct sdap_handle *sh, + int timeout, + const char *user_dn, +- struct berval *pw) ++ struct berval *pw, ++ enum pwmodify_mode pwmodify_mode) + { + struct tevent_req *req; + struct simple_bind_state *state; +@@ -682,6 +684,7 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, + state->ev = ev; + state->sh = sh; + state->user_dn = user_dn; ++ state->pwmodify_mode = pwmodify_mode; + + ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST, + 0, NULL, 0, &ctrls[0]); +@@ -866,7 +869,12 @@ static void simple_bind_done(struct sdap_op *op, + * Grace Authentications". */ + DEBUG(SSSDBG_TRACE_LIBS, + "Password expired, grace logins exhausted.\n"); +- ret = ERR_AUTH_FAILED; ++ if (state->pwmodify_mode == SDAP_PWMODIFY_EXOP_FORCE) { ++ DEBUG(SSSDBG_TRACE_LIBS, "Password change forced.\n"); ++ ret = ERR_PASSWORD_EXPIRED; ++ } else { ++ ret = ERR_AUTH_FAILED; ++ } + } + } else if (strcmp(response_controls[c]->ldctl_oid, + LDAP_CONTROL_PWEXPIRED) == 0) { +@@ -879,7 +887,12 @@ static void simple_bind_done(struct sdap_op *op, + if (result == LDAP_INVALID_CREDENTIALS) { + DEBUG(SSSDBG_TRACE_LIBS, + "Password expired, grace logins exhausted.\n"); +- ret = ERR_AUTH_FAILED; ++ if (state->pwmodify_mode == SDAP_PWMODIFY_EXOP_FORCE) { ++ DEBUG(SSSDBG_TRACE_LIBS, "Password change forced.\n"); ++ ret = ERR_PASSWORD_EXPIRED; ++ } else { ++ ret = ERR_AUTH_FAILED; ++ } + } else { + DEBUG(SSSDBG_TRACE_LIBS, + "Password expired, user must set a new password.\n"); +@@ -1358,7 +1371,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, + const char *sasl_user, + const char *user_dn, + struct sss_auth_token *authtok, +- int simple_bind_timeout) ++ int simple_bind_timeout, ++ enum pwmodify_mode pwmodify_mode) + { + struct tevent_req *req, *subreq; + struct sdap_auth_state *state; +@@ -1397,7 +1411,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, + pw.bv_len = pwlen; + + state->is_sasl = false; +- subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw); ++ subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw, pwmodify_mode); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return tevent_req_post(req, ev); +@@ -1972,7 +1986,8 @@ static void sdap_cli_auth_step(struct tevent_req *req) + SDAP_SASL_AUTHID), + user_dn, authtok, + dp_opt_get_int(state->opts->basic, +- SDAP_OPT_TIMEOUT)); ++ SDAP_OPT_TIMEOUT), ++ state->opts->pwmodify_mode); + talloc_free(authtok); + if (!subreq) { + tevent_req_error(req, ENOMEM); +-- +2.46.1 + diff --git a/SOURCES/0014-DEBUG-reduce-log-level-in-case-a-responder-asks-for-.patch b/SOURCES/0014-DEBUG-reduce-log-level-in-case-a-responder-asks-for-.patch new file mode 100644 index 0000000..9b4dd50 --- /dev/null +++ b/SOURCES/0014-DEBUG-reduce-log-level-in-case-a-responder-asks-for-.patch @@ -0,0 +1,54 @@ +From aa81ab093966c1717ebfafbeef9f9f78944b9c23 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Mon, 15 Apr 2024 16:29:33 +0200 +Subject: [PATCH 14/15] DEBUG: reduce log level in case a responder asks for + unknown domain +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Addition to 718fed9c53807b8502d6547bc0253b979d35e677 + +Reviewed-by: Alejandro López +Reviewed-by: Iker Pedrosa +(cherry picked from commit ab2671c00866d917f3e737a007ae64753f8440aa) +(cherry picked from commit 8dcf23f215fe2a7fadf13598ce7f04523caa5eb0) + +Reviewed-by: Justin Stephenson +--- + src/responder/common/cache_req/plugins/cache_req_common.c | 5 ++++- + src/sbus/router/sbus_router_handler.c | 2 ++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/responder/common/cache_req/plugins/cache_req_common.c b/src/responder/common/cache_req/plugins/cache_req_common.c +index 7eb09215a..00b9383ee 100644 +--- a/src/responder/common/cache_req/plugins/cache_req_common.c ++++ b/src/responder/common/cache_req/plugins/cache_req_common.c +@@ -129,7 +129,10 @@ cache_req_common_process_dp_reply(struct cache_req *cr, + bool bret; + + if (ret != EOK) { +- CACHE_REQ_DEBUG(SSSDBG_IMPORTANT_INFO, cr, ++ int msg_level = SSSDBG_IMPORTANT_INFO; ++ /* ERR_DOMAIN_NOT_FOUND: 'ad_enabled_domains' option can exclude domain */ ++ if (ret == ERR_DOMAIN_NOT_FOUND) msg_level = SSSDBG_CONF_SETTINGS; ++ CACHE_REQ_DEBUG(msg_level, cr, + "Could not get account info [%d]: %s\n", + ret, sss_strerror(ret)); + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, +diff --git a/src/sbus/router/sbus_router_handler.c b/src/sbus/router/sbus_router_handler.c +index 7b6c2441f..732716046 100644 +--- a/src/sbus/router/sbus_router_handler.c ++++ b/src/sbus/router/sbus_router_handler.c +@@ -150,6 +150,8 @@ static void sbus_issue_request_done(struct tevent_req *subreq) + } else { + int msg_level = SSSDBG_OP_FAILURE; + if (ret == ERR_MISSING_DP_TARGET) msg_level = SSSDBG_FUNC_DATA; ++ /* ERR_DOMAIN_NOT_FOUND: 'ad_enabled_domains' option can exclude domain */ ++ if (ret == ERR_DOMAIN_NOT_FOUND) msg_level = SSSDBG_CONF_SETTINGS; + DEBUG(msg_level, "%s.%s: Error [%d]: %s\n", + meta.interface, meta.member, ret, sss_strerror(ret)); + } +-- +2.46.1 + diff --git a/SOURCES/0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch b/SOURCES/0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch new file mode 100644 index 0000000..779ffd8 --- /dev/null +++ b/SOURCES/0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch @@ -0,0 +1,55 @@ +From 3e7e0cc7038c89132c9f4b8a48b6b1e0c0febff4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 21 Nov 2024 09:16:09 +0100 +Subject: [PATCH 15/15] ldap_child: make sure invalid krb5 context is not used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://github.com/SSSD/sssd/issues/7715 + +Reviewed-by: Alejandro López +Reviewed-by: Alexey Tikhonov +(cherry picked from commit fce94aec3f335cbe33c509b14e389b9df0748744) +--- + src/util/sss_krb5.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c +index 3f57e5b26..f44df2b5f 100644 +--- a/src/util/sss_krb5.c ++++ b/src/util/sss_krb5.c +@@ -83,6 +83,10 @@ const char *sss_printable_keytab_name(krb5_context ctx, const char *keytab_name) + return keytab_name; + } + ++ if (ctx == NULL) { ++ return "-unknown-"; ++ } ++ + if (krb5_kt_default_name(ctx, buff, sizeof(buff)) != 0) { + return "-default keytab-"; + } +@@ -1355,8 +1359,9 @@ krb5_error_code sss_krb5_init_context(krb5_context *context) + { + krb5_error_code kerr; + const char *msg; ++ krb5_context ctx; + +- kerr = krb5_init_context(context); ++ kerr = krb5_init_context(&ctx); + if (kerr != 0) { + /* It is safe to call (sss_)krb5_get_error_message() with NULL as first + * argument. */ +@@ -1365,6 +1370,8 @@ krb5_error_code sss_krb5_init_context(krb5_context *context) + "Failed to init Kerberos context [%s]\n", msg); + sss_log(SSS_LOG_CRIT, "Failed to init Kerberos context [%s]\n", msg); + sss_krb5_free_error_message(NULL, msg); ++ } else { ++ *context = ctx; + } + + return kerr; +-- +2.46.1 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 3963821..36d493d 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -19,7 +19,7 @@ Name: sssd Version: 2.9.4 -Release: 4%{?dist} +Release: 5%{?dist}.1 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -33,6 +33,15 @@ 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-ad-gpo-use-hash-to-store-intermediate-results.patch Patch0006: 0006-ad-refresh-root-domain-when-read-directly.patch +Patch0007: 0007-failover-add-failover_primary_timeout-option.patch +Patch0008: 0008-OPTS-Add-the-option-for-DP_OPT_DYNDNS_REFRESH_OFFSET.patch +Patch0009: 0009-TESTS-Also-test-default_dyndns_opts.patch +Patch0010: 0010-sdap-allow-to-provide-user_map-when-looking-up-group.patch +Patch0011: 0011-ad-use-default-user_map-when-looking-of-host-groups-.patch +Patch0012: 0012-sysdb-do-not-fail-to-add-non-posix-user-to-MPG-domai.patch +Patch0013: 0013-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch +Patch0014: 0014-DEBUG-reduce-log-level-in-case-a-responder-asks-for-.patch +Patch0015: 0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch ### Downstream Patches ### @@ -1217,6 +1226,17 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Fri Nov 22 2024 Alexey Tikhonov - 2.9.4-5.1 +- Resolves: RHEL-67671 - Label DP_OPT_DYNDNS_REFRESH_OFFSET has no corresponding option [rhel-8.10.z] +- Resolves: RHEL-68507 - sssd backend process segfaults when krb5.conf is invalid [rhel-8.10.z] +- Resolves: RHEL-66267 - SSSD needs an option to indicate if the LDAP server can run the exop with an anonymous bind or not [rhel-8.10.z] +- Resolves: RHEL-67128 - Excessive "Domain not found' messages logged to sssd_nss & sssd_be in multidomain AD forest [rhel-8.10.z] +- Resolves: RHEL-66272 - sssd is skipping GPO evaluation with auto_private_groups [rhel-8.10.z] +- Resolves: RHEL-66277 - possible regression of rhbz#2196521 [rhel-8.10.z] + +* Mon Sep 09 2024 Anuar Beisembayev - 2.9.4-5 +- Resolves: RHEL-39085 - [RfE] SSSD Failover Enhancements + * Fri May 17 2024 Arun Bansal - 2.9.4-4 - Resolves: RHEL-33957 - ad: refresh root domain when read directly