import CS sssd-2.12.0-3.el10

This commit is contained in:
AlmaLinux RelEng Bot 2026-05-19 15:14:52 -04:00
parent e48834b608
commit 39e3882880
8 changed files with 526 additions and 295 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
sssd-2.11.1.tar.gz
sssd-2.12.0.tar.gz

View File

@ -1,222 +0,0 @@
From 98a91d170f7a6074ed1bd3b8ed9161c4a11b4074 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
Date: Thu, 14 Aug 2025 16:21:00 +0200
Subject: [PATCH] Revert "ipa: improve handling of external group memberships"
This reverts commit 63a6f51069a86765417f044a62705fe20572e0da.
---
src/providers/ipa/ipa_subdomains_ext_groups.c | 152 +++---------------
1 file changed, 22 insertions(+), 130 deletions(-)
diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c
index f86130d89..ba3fb3953 100644
--- a/src/providers/ipa/ipa_subdomains_ext_groups.c
+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c
@@ -312,19 +312,11 @@ static errno_t add_ad_user_to_cached_groups(struct ldb_dn *user_dn,
bool *missing_groups)
{
size_t c;
- size_t d = 0;
struct sysdb_attrs *user_attrs;
size_t msgs_count;
struct ldb_message **msgs;
TALLOC_CTX *tmp_ctx;
int ret;
- const struct ldb_val *val;
- char *user_name;
- char **sysdb_ipa_group_memberships;
- char **add_groups;
- char **del_groups;
- errno_t sret;
- bool in_transaction = false;
*missing_groups = false;
@@ -334,96 +326,18 @@ static errno_t add_ad_user_to_cached_groups(struct ldb_dn *user_dn,
return ENOMEM;
}
- val = ldb_dn_get_rdn_val(user_dn);
- if (val == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "user_dn has no RDN.\n");
- ret = EINVAL;
- goto done;
- }
- user_name = talloc_strndup(tmp_ctx, (char *) val->data, val->length);
- if (user_name == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to copy user name.\n");
- ret = ENOMEM;
- goto done;
- }
-
- ret = sysdb_transaction_start(user_dom->sysdb);
- if (ret != EOK) {
- DEBUG(SSSDBG_FATAL_FAILURE, "Failed to start update transaction\n");
- goto done;
- }
-
- in_transaction = true;
-
- ret = sysdb_get_direct_parents_ex(tmp_ctx, user_dom, group_dom,
- SYSDB_MEMBER_USER, user_name,
- SYSDB_ORIG_DN,
- &sysdb_ipa_group_memberships);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to get current IPA group memberships "
- "of user [%s].\n", user_name);
- goto done;
- }
-
- ret = diff_string_lists(tmp_ctx, groups, sysdb_ipa_group_memberships,
- &add_groups, &del_groups, NULL);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to get difference in group lists.\n");
- goto done;
- }
-
- user_attrs = sysdb_new_attrs(tmp_ctx);
- if (user_attrs == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
- ret = ENOMEM;
- goto done;
- }
-
- /* Add all new IPA groups to SYSDB_ORIG_MEMBEROF because they are most
- * probably removed by the previous user update and mark all new groups as
- * processed. */
for (c = 0; groups[c] != NULL; c++) {
- ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
- groups[c]);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
- goto done;
+ if (groups[c][0] == '\0') {
+ continue;
}
- groups[c][0] = '\0';
- }
-
- if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
- DEBUG(SSSDBG_TRACE_ALL, "New IPA groups [%zu].\n", c);
-
- for (c = 0; sysdb_ipa_group_memberships[c] != NULL; c++);
- DEBUG(SSSDBG_TRACE_ALL, "Cached IPA groups [%zu].\n", c);
-
- for (c = 0; add_groups[c] != NULL; c++);
- DEBUG(SSSDBG_TRACE_ALL, "Groups to add [%zu].\n", c);
-
- for (c = 0; del_groups[c] != NULL; c++);
- DEBUG(SSSDBG_TRACE_ALL, "Groups to delete [%zu].\n", c);
- }
-
- /* TODO: there is a similar functionality (adding and removing group
- * memberships in sysdb_update_members_ex(), but the missing group feature
- * is missing. It might be worth to evaluate if either the missing group
- * feature can be added there or if group which are missing in the cache
- * can bew handled differently here. */
-
- for (c = 0; add_groups[c] != NULL; c++) {
-
- ret = sysdb_search_groups_by_orig_dn(tmp_ctx, group_dom, add_groups[c],
+ ret = sysdb_search_groups_by_orig_dn(tmp_ctx, group_dom, groups[c],
NULL, &msgs_count, &msgs);
if (ret != EOK) {
if (ret == ENOENT) {
DEBUG(SSSDBG_TRACE_ALL, "Group [%s] not in the cache.\n",
- add_groups[c]);
+ groups[c]);
*missing_groups = true;
- talloc_free(groups[d]);
- /* add missing group back to the list */
- groups[d++] = talloc_steal(groups, add_groups[c]);
continue;
} else {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
@@ -431,6 +345,9 @@ static errno_t add_ad_user_to_cached_groups(struct ldb_dn *user_dn,
}
}
+/* TODO? Do we have to remove members as well? I think not because the AD
+ * query before removes all memberships. */
+
ret = sysdb_mod_group_member(group_dom, user_dn, msgs[0]->dn,
LDB_FLAG_MOD_ADD);
if (ret != EOK && ret != EEXIST) {
@@ -438,58 +355,33 @@ static errno_t add_ad_user_to_cached_groups(struct ldb_dn *user_dn,
goto done;
}
- }
- talloc_free(groups[d]);
- groups[d] = NULL;
+ user_attrs = sysdb_new_attrs(tmp_ctx);
+ if (user_attrs == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
- for (c = 0; del_groups[c] != NULL; c++) {
- ret = sysdb_search_groups_by_orig_dn(tmp_ctx, group_dom, del_groups[c],
- NULL, &msgs_count, &msgs);
+ ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
+ groups[c]);
if (ret != EOK) {
- if (ret == ENOENT) {
- DEBUG(SSSDBG_TRACE_ALL,
- "Group [%s] not in the cache, skipping.\n",
- del_groups[c]);
- continue;
- } else {
- DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
- goto done;
- }
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
+ goto done;
}
- ret = sysdb_mod_group_member(group_dom, user_dn, msgs[0]->dn,
- LDB_FLAG_MOD_DELETE);
+ ret = sysdb_set_entry_attr(user_dom->sysdb, user_dn, user_attrs,
+ LDB_FLAG_MOD_ADD);
if (ret != EOK && ret != EEXIST) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sysdb_mod_group_member failed to delete member.\n");
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n");
goto done;
}
- }
- /* Update SYSDB_ORIG_MEMBEROF with the IPA groups. */
- ret = sysdb_set_entry_attr(user_dom->sysdb, user_dn, user_attrs,
- LDB_FLAG_MOD_ADD);
- if (ret != EOK && ret != EEXIST) {
- DEBUG(SSSDBG_OP_FAILURE, "Failed to add original IPA group DNs, ignored.\n");
- }
-
- ret = sysdb_transaction_commit(user_dom->sysdb);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
- goto done;
+ /* mark group as already processed */
+ groups[c][0] = '\0';
}
- in_transaction = false;
-
ret = EOK;
done:
- if (in_transaction) {
- sret = sysdb_transaction_cancel(user_dom->sysdb);
- if (sret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
- }
- }
-
talloc_free(tmp_ctx);
return ret;
--
2.50.0

View File

@ -0,0 +1,79 @@
Based on 7aa7344a20b3b31ae53ea790801254af42d525ed
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 9 Feb 2026 14:10:29 +0100
Subject: [PATCH] sdap: do not require GID for non-POSIX group
diff -up sssd-2.12.0/src/providers/ldap/sdap_async_groups.c.orig sssd-2.12.0/src/providers/ldap/sdap_async_groups.c
--- sssd-2.12.0/src/providers/ldap/sdap_async_groups.c.orig 2026-01-14 15:59:45.560996918 +0100
+++ sssd-2.12.0/src/providers/ldap/sdap_async_groups.c 2026-04-02 10:34:30.367027491 +0200
@@ -620,15 +620,17 @@ static int sdap_save_group(TALLOC_CTX *m
goto done;
}
- ret = sysdb_attrs_get_uint32_t(attrs,
- opts->group_map[SDAP_AT_GROUP_GID].sys_name,
- &gid);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "no gid provided for [%s] in domain [%s].\n",
- group_name, dom->name);
- ret = EINVAL;
- goto done;
+ if (posix_group) {
+ ret = sysdb_attrs_get_uint32_t(attrs,
+ opts->group_map[SDAP_AT_GROUP_GID].sys_name,
+ &gid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "no gid provided for [%s] in domain [%s].\n",
+ group_name, dom->name);
+ ret = EINVAL;
+ goto done;
+ }
}
}
}
diff -up sssd-2.12.0/src/tests/tests/system/tests/test_identity.py.orig sssd-2.12.0/src/tests/tests/system/tests/test_identity.py
--- sssd-2.12.0/src/tests/tests/system/tests/test_identity.py.orig 2026-01-14 15:59:45.611996896 +0100
+++ sssd-2.12.0/src/tests/tests/system/tests/test_identity.py 2026-04-02 10:34:30.368219151 +0200
@@ -761,3 +761,40 @@ def test_identity__filter_groups_by_name
result = client.tools.getent.group(20001)
assert result is None, "Filtered group was found"
+
+
+@pytest.mark.importance("critical")
+@pytest.mark.topology(KnownTopologyGroup.AnyAD)
+def test_identity__nested_non_posix_group(client: Client, provider: GenericADProvider):
+ """
+ :title: Lookup indirect group-members of a nested non-POSIX group
+ :setup:
+ 1. Add a new POSIX user and two new groups, one POSIX the other non-POSIX
+ 2. Add the user to the non-POSIX group and the non-POSIX group to the POSIX group
+ 3. Set 'ldap_id_mapping = false' to allow non-POSIX groups, because
+ with POSIX id-mapping enabled all groups will get POSIX ID and hence
+ there are no non-POSIX groups, and start SSSD
+ :steps:
+ 1. Lookup the POSIX group with getent
+ :expectedresults:
+ 1. Group is present and the new user is a member
+ :customerscenario: False
+ """
+ user = provider.user("nesteduser").add(
+ uid=10001, gid=20001, password="Secret123", gecos="User for tests", shell="/bin/bash"
+ )
+ nested_group = provider.group("nested_nonposix_group").add().add_member(user)
+ base_group = provider.group("posix_group").add(gid=30001).add_member(nested_group)
+
+ client.sssd.domain["ldap_id_mapping"] = "false"
+ client.sssd.start()
+
+ result = client.tools.getent.group(base_group.name)
+ assert result is not None, f"Group '{base_group.name}' not found!"
+ assert (
+ len(result.members) == 1
+ ), f"Group '{base_group.name}' has unexpected number of members [{len(result.members)}]!"
+ assert f"{user.name}" in result.members, f"Member '{user.name}' of group '{base_group.name}' not found!"
+
+ result = client.tools.getent.group(nested_group.name)
+ assert result is None, f"Non-POSIX Group '{nested_group.name}' was found with 'getent group'!"

View File

@ -0,0 +1,16 @@
KCM: fix use-after-free in `kcm_read_options()`
Based on commit c5a2b48f13af893ae6c7c9fe63e41f64eb77cade
diff --git a/src/responder/kcm/kcm_renew.c b/src/responder/kcm/kcm_renew.c
index 39e9470fa22..32eccf4b48a 100644
--- a/src/responder/kcm/kcm_renew.c
+++ b/src/responder/kcm/kcm_renew.c
@@ -228,7 +228,7 @@ static errno_t kcm_read_options(TALLOC_CTX *mem_ctx,
*_validate = validate;
*_canonicalize = canonicalize;
*_timeout = timeout;
- *_renew_intv = renew_intv;
+ *_renew_intv = talloc_steal(mem_ctx, renew_intv);
ret = EOK;

View File

@ -1,49 +0,0 @@
From a08e5862693ed1191ba464351ae43c779b509096 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 10 Oct 2025 12:57:40 +0200
Subject: [PATCH] krb5: disable Kerberos localauth an2ln plugin for AD/IPA
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If a client is joined to AD or IPA SSSD's localauth plugin can handle
the mapping of Kerberos principals to local accounts. In case it cannot
map the Kerberos principals libkrb5 is currently configured to fall back
to the default localauth plugins 'default', 'rule', 'names',
'auth_to_local', 'k5login' and 'an2ln' (see man krb5.conf for details).
All plugins except 'an2ln' require some explicit configuration by either
the administrator or the local user. To avoid some unexpected mapping is
done by the 'an2ln' plugin this patch disables it in the configuration
snippets for SSSD's localauth plugin.
Resolves: https://github.com/SSSD/sssd/issues/8021
:relnote: After startup SSSD already creates a Kerberos configuration
snippet typically in /var/lib/sss/pubconf/krb5.include.d/localauth_plugin
if the AD or IPA providers are used. This enables SSSD's localauth plugin.
Starting with this release the an2ln plugin is disabled in the
configuration snippet as well. If this file or its content are included in
the Kerberos configuration it will fix CVE-2025-11561.
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit 9939c39d1949fad48af2f0b43c788bad0809e310)
---
src/util/domain_info_utils.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 677b76ff352198b8b6049213ae32c80f2f59026e..00f22b19d29fb24a8c49219e857a02cc24886a7d 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -747,6 +747,7 @@ done:
#define LOCALAUTH_PLUGIN_CONFIG \
"[plugins]\n" \
" localauth = {\n" \
+" disable = an2ln\n" \
" module = sssd:"APP_MODULES_PATH"/sssd_krb5_localauth_plugin.so\n" \
" }\n"
--
2.51.0

View File

@ -0,0 +1,385 @@
Based on https://github.com/SSSD/sssd/pull/8595
idp: do not update cache timeout if member is added
diff -up sssd-2.12.0/src/confdb/confdb.c.orig sssd-2.12.0/src/confdb/confdb.c
--- sssd-2.12.0/src/confdb/confdb.c.orig 2026-01-14 15:59:45.496996946 +0100
+++ sssd-2.12.0/src/confdb/confdb.c 2026-04-14 11:31:11.752143448 +0200
@@ -1091,6 +1091,7 @@ static errno_t confdb_init_domain(struct
{
errno_t ret;
const char *tmp;
+ bool default_avoid_by_id_lookups = false;
tmp = ldb_msg_find_attr_as_string(res->msgs[0], "cn", NULL);
if (!tmp) {
@@ -1214,6 +1215,19 @@ static errno_t confdb_init_domain(struct
}
}
+ if (strcasecmp(domain->provider, "idp") == 0) {
+ default_avoid_by_id_lookups = true;
+ }
+ ret = get_entry_as_bool(res->msgs[0], &domain->avoid_by_id_lookups,
+ CONFDB_DOMAIN_AVOID_BY_ID_LOOKUPS,
+ default_avoid_by_id_lookups);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Invalid value for %s\n",
+ CONFDB_DOMAIN_AVOID_BY_ID_LOOKUPS);
+ goto done;
+ }
+
domain->has_views = false;
domain->view_name = NULL;
diff -up sssd-2.12.0/src/confdb/confdb.h.orig sssd-2.12.0/src/confdb/confdb.h
--- sssd-2.12.0/src/confdb/confdb.h.orig 2026-01-14 15:59:45.496996946 +0100
+++ sssd-2.12.0/src/confdb/confdb.h 2026-04-14 11:31:11.752647894 +0200
@@ -226,6 +226,7 @@
#define CONFDB_DOMAIN_ACCOUNT_CACHE_EXPIRATION "account_cache_expiration"
#define CONFDB_DOMAIN_OVERRIDE_GID "override_gid"
#define CONFDB_DOMAIN_CASE_SENSITIVE "case_sensitive"
+#define CONFDB_DOMAIN_AVOID_BY_ID_LOOKUPS "avoid_by_id_lookups"
#define CONFDB_DOMAIN_SUBDOMAIN_HOMEDIR "subdomain_homedir"
#define CONFDB_DOMAIN_DEFAULT_SUBDOMAIN_HOMEDIR "/home/%d/%u"
#define CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS "ignore_group_members"
@@ -366,6 +367,7 @@ struct sss_domain_info {
uint32_t cache_credentials_min_ff_length;
bool case_sensitive;
bool case_preserve;
+ bool avoid_by_id_lookups;
gid_t override_gid;
const char *override_homedir;
diff -up sssd-2.12.0/src/config/cfg_rules.ini.orig sssd-2.12.0/src/config/cfg_rules.ini
--- sssd-2.12.0/src/config/cfg_rules.ini.orig 2026-01-14 15:59:45.496996946 +0100
+++ sssd-2.12.0/src/config/cfg_rules.ini 2026-04-14 11:31:11.753537516 +0200
@@ -393,6 +393,7 @@ option = dns_discovery_domain
option = failover_primary_timeout
option = override_gid
option = case_sensitive
+option = avoid_by_id_lookups
option = override_homedir
option = fallback_homedir
option = homedir_substring
diff -up sssd-2.12.0/src/config/etc/sssd.api.conf.orig sssd-2.12.0/src/config/etc/sssd.api.conf
--- sssd-2.12.0/src/config/etc/sssd.api.conf.orig 2026-01-14 15:59:45.497996946 +0100
+++ sssd-2.12.0/src/config/etc/sssd.api.conf 2026-04-14 11:31:11.753715790 +0200
@@ -172,6 +172,7 @@ dns_discovery_domain = str, None, false
failover_primary_timeout = int, None, false
override_gid = int, None, false
case_sensitive = str, None, false
+avoid_by_id_lookups = bool, None, false
override_homedir = str, None, false
fallback_homedir = str, None, false
homedir_substring = str, None, false
diff -up sssd-2.12.0/src/config/SSSDConfig/sssdoptions.py.orig sssd-2.12.0/src/config/SSSDConfig/sssdoptions.py
--- sssd-2.12.0/src/config/SSSDConfig/sssdoptions.py.orig 2026-01-14 15:59:45.496996946 +0100
+++ sssd-2.12.0/src/config/SSSDConfig/sssdoptions.py 2026-04-14 11:31:11.752888576 +0200
@@ -187,6 +187,7 @@ class SSSDOptions(object):
'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'),
+ 'avoid_by_id_lookups': _('Lookups by ID are expensive or do not work at all'),
'entry_cache_user_timeout': _('Entry cache timeout length (seconds)'),
'entry_cache_group_timeout': _('Entry cache timeout length (seconds)'),
'entry_cache_netgroup_timeout': _('Entry cache timeout length (seconds)'),
diff -up sssd-2.12.0/src/config/SSSDConfigTest.py.orig sssd-2.12.0/src/config/SSSDConfigTest.py
--- sssd-2.12.0/src/config/SSSDConfigTest.py.orig 2026-01-14 15:59:45.496996946 +0100
+++ sssd-2.12.0/src/config/SSSDConfigTest.py 2026-04-14 11:31:11.753215468 +0200
@@ -573,6 +573,7 @@ class SSSDConfigTestSSSDDomain(unittest.
'dyndns_dot_key',
'override_gid',
'case_sensitive',
+ 'avoid_by_id_lookups',
'override_homedir',
'fallback_homedir',
'homedir_substring',
@@ -937,6 +938,7 @@ class SSSDConfigTestSSSDDomain(unittest.
'dyndns_dot_key',
'override_gid',
'case_sensitive',
+ 'avoid_by_id_lookups',
'override_homedir',
'fallback_homedir',
'homedir_substring',
diff -up sssd-2.12.0/src/db/sysdb_subdomains.c.orig sssd-2.12.0/src/db/sysdb_subdomains.c
--- sssd-2.12.0/src/db/sysdb_subdomains.c.orig 2026-01-14 15:59:45.499996945 +0100
+++ sssd-2.12.0/src/db/sysdb_subdomains.c 2026-04-14 11:31:11.753963557 +0200
@@ -199,6 +199,7 @@ struct sss_domain_info *new_subdomain(TA
dom->default_shell = parent->default_shell;
dom->homedir_substr = parent->homedir_substr;
dom->override_gid = parent->override_gid;
+ dom->avoid_by_id_lookups = parent->avoid_by_id_lookups;
dom->gssapi_services = parent->gssapi_services;
dom->gssapi_indicators_map = parent->gssapi_indicators_map;
diff -up sssd-2.12.0/src/man/sssd.conf.5.xml.orig sssd-2.12.0/src/man/sssd.conf.5.xml
--- sssd-2.12.0/src/man/sssd.conf.5.xml.orig 2026-01-14 15:59:45.543996926 +0100
+++ sssd-2.12.0/src/man/sssd.conf.5.xml 2026-04-14 11:31:11.754747046 +0200
@@ -3775,6 +3775,28 @@ pam_json_services = gdm-switchable-auth
</varlistentry>
<varlistentry>
+ <term>avoid_by_id_lookups (boolean)</term>
+ <listitem>
+ <para>
+ If this option is set to 'true' SSSD will try to
+ avoid sending lookups by ID to the backend and
+ will switch to a lookup by name if a cached
+ object with a matching ID can be found.
+ </para>
+ <para>
+ This option can e.g. be used in cases where
+ searches by ID are expensive on the server side
+ because of missing indexes or are not even
+ possible, e.g. due to non-reversible POSIX
+ id-mapping.
+ </para>
+ <para>
+ Default: False (True for IdP provider)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>subdomain_inherit (string)</term>
<listitem>
<para>
diff -up sssd-2.12.0/src/providers/idp/idp_id_eval.c.orig sssd-2.12.0/src/providers/idp/idp_id_eval.c
--- sssd-2.12.0/src/providers/idp/idp_id_eval.c.orig 2026-01-14 15:59:45.551996922 +0100
+++ sssd-2.12.0/src/providers/idp/idp_id_eval.c 2026-04-14 11:31:11.756401469 +0200
@@ -137,7 +137,6 @@ static errno_t store_json_group(struct i
errno_t ret;
json_t *group_name = NULL;
json_t *uuid = NULL;
- int cache_timeout;
struct sss_domain_info *dom;
gid_t gid;
char *fqdn = NULL;
@@ -195,18 +194,35 @@ static errno_t store_json_group(struct i
goto done;
}
- cache_timeout = dom->group_timeout;
- ret = sysdb_store_group(dom, fqdn, gid, attrs, cache_timeout, 0);
+ /* If we just add a single member to a group (user_name != NULL) we do not
+ * want to change the cache timeout. Calling `sysdb_add_incomplete_group()
+ * will check if the group already exists (ret == ERR_GID_DUPLICATED) or
+ * create an expired group object (ret == EOK). In both cases there will
+ * be a cached group object where the user can be added as a member. */
+ if (user_name == NULL) {
+ ret = sysdb_store_group(dom, fqdn, gid, attrs, dom->group_timeout, 0);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to store group [%s].\n", fqdn);
+ goto done;
+ }
+ } else {
+ ret = sysdb_add_incomplete_group(dom, fqdn, gid, NULL, NULL,
+ json_string_value(uuid),
+ gid != 0, 0);
+ if (ret != EOK && ret != ERR_GID_DUPLICATED) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to create incomplete group [%s].\n", fqdn);
+ goto done;
+ }
- if (user_name != NULL) {
ret = sysdb_add_group_member(dom, fqdn, user_name, SYSDB_MEMBER_USER,
false);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- "Failed to store user [%s] as member of group [%s].\n",
- user_name, fqdn);
- goto done;
- }
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to store user [%s] as member of group [%s].\n",
+ user_name, fqdn);
+ goto done;
+ }
}
done:
diff -up sssd-2.12.0/src/responder/common/cache_req/cache_req.c.orig sssd-2.12.0/src/responder/common/cache_req/cache_req.c
--- sssd-2.12.0/src/responder/common/cache_req/cache_req.c.orig 2026-01-14 15:59:45.565996916 +0100
+++ sssd-2.12.0/src/responder/common/cache_req/cache_req.c 2026-04-14 11:31:11.755687660 +0200
@@ -23,6 +23,7 @@
#include <tevent.h>
#include <errno.h>
+#include "db/sysdb.h"
#include "util/util.h"
#include "util/sss_chain_id.h"
#include "responder/common/responder.h"
@@ -1613,3 +1614,56 @@ cache_req_steal_data_and_send(TALLOC_CTX
return req;
}
+
+errno_t cache_req_fallback_to_name_search(struct cache_req *cr,
+ enum cache_req_type fallback_type,
+ struct ldb_result *result)
+{
+ int ret;
+ const char *name = NULL;
+ char *shortname = NULL;
+
+ name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL);
+ if (name != NULL) {
+ ret = cache_req_set_plugin(cr, fallback_type);
+ if (ret != EOK) {
+ CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, cr, "cache_req_set_plugin failed.\n");
+ goto done;
+ }
+
+ ret = sss_parse_internal_fqname(cr, name, &shortname, NULL);
+ if (ret != EOK) {
+ CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr, "sss_parse_internal_fqname() failed\n");
+ goto done;
+ }
+
+ ret = cache_req_set_name(cr, shortname);
+ if (ret != EOK) {
+ CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr, "cache_req_set_name() failed\n");
+ goto done;
+ }
+
+ ret = cr->plugin->prepare_domain_data_fn(cr, cr->data, cr->domain);
+ if (ret != EOK) {
+ CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, cr, "prepare_domain_data_fn() failed.\n");
+ goto done;
+ }
+
+ ret = cache_req_create_debug_name(cr, cr->domain);
+ if (ret != EOK) {
+ CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, cr, "cache_req_create_debug_name() failed.\n");
+ goto done;
+ }
+
+ CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Switching to name [%s]\n",
+ name);
+ } else {
+ CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, cr, "Name not available, switching not possible.\n");
+ }
+
+ ret = EOK;
+
+done:
+
+ return ret;
+}
diff -up sssd-2.12.0/src/responder/common/cache_req/cache_req_private.h.orig sssd-2.12.0/src/responder/common/cache_req/cache_req_private.h
--- sssd-2.12.0/src/responder/common/cache_req/cache_req_private.h.orig 2026-01-14 15:59:45.565996916 +0100
+++ sssd-2.12.0/src/responder/common/cache_req/cache_req_private.h 2026-04-14 11:31:11.755989311 +0200
@@ -224,4 +224,8 @@ cache_req_common_get_acct_domain_recv(TA
errno_t cache_req_idminmax_check(struct cache_req_data *data,
struct sss_domain_info *domain);
+
+errno_t cache_req_fallback_to_name_search(struct cache_req *cr,
+ enum cache_req_type fallback_type,
+ struct ldb_result *result);
#endif /* _CACHE_REQ_PRIVATE_H_ */
diff -up sssd-2.12.0/src/responder/common/cache_req/cache_req_search.c.orig sssd-2.12.0/src/responder/common/cache_req/cache_req_search.c
--- sssd-2.12.0/src/responder/common/cache_req/cache_req_search.c.orig 2026-01-14 15:59:45.566996916 +0100
+++ sssd-2.12.0/src/responder/common/cache_req/cache_req_search.c 2026-04-14 11:31:11.756157616 +0200
@@ -311,6 +311,7 @@ cache_req_search_send(TALLOC_CTX *mem_ct
bool bypass_dp = false;
bool skip_refresh = false;
errno_t ret;
+ enum cache_req_type fallback_type = CACHE_REQ_SENTINEL;
req = tevent_req_create(mem_ctx, &state, struct cache_req_search_state);
if (req == NULL) {
@@ -381,6 +382,26 @@ cache_req_search_send(TALLOC_CTX *mem_ct
CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr,
"Object found, but needs to be refreshed.\n");
bypass_dp = false;
+
+ if (cr->domain->avoid_by_id_lookups) {
+ if (cache_req_data_get_type(cr->data)
+ == CACHE_REQ_GROUP_BY_ID) {
+ fallback_type = CACHE_REQ_GROUP_BY_NAME;
+ } else if (cache_req_data_get_type(cr->data)
+ == CACHE_REQ_USER_BY_ID) {
+ fallback_type = CACHE_REQ_USER_BY_NAME;
+ }
+
+ if (fallback_type != CACHE_REQ_SENTINEL) {
+ ret = cache_req_fallback_to_name_search(cr, fallback_type,
+ state->result);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to switch to name search.\n");
+ goto done;
+ }
+ }
+ }
} else {
ret = ENOENT;
}
diff -up sssd-2.12.0/src/tests/tests/system/tests/test_idp.py.orig sssd-2.12.0/src/tests/tests/system/tests/test_idp.py
--- sssd-2.12.0/src/tests/tests/system/tests/test_idp.py.orig 2026-01-14 15:59:45.611996896 +0100
+++ sssd-2.12.0/src/tests/tests/system/tests/test_idp.py 2026-04-14 11:31:49.961013653 +0200
@@ -159,3 +159,59 @@ def test_idp__group_ignore_group_members
out = client.host.conn.run(f"getent group group1{domain}")
assert out.stdout.startswith(f"group1{domain}:*:")
assert out.stdout.endswith(":")
+
+
+@pytest.mark.parametrize("use_fully_qualified_names", ["true", "false"])
+@pytest.mark.topology(KnownTopology.Keycloak)
+@pytest.mark.builtwith(client="idp-provider")
+def test_idp__id_before_group(client: Client, keycloak: Keycloak, use_fully_qualified_names: str):
+ """
+ :title: Call id before getent group
+ :setup:
+ 1. Create two user
+ 2. Create group with both users as members
+ :steps:
+ 1. Lookup one user with 'id'
+ 2. Lookup group with 'getent group'
+ :expectedresults:
+ 1. User is member of added group and the auto-private group
+ 2. Both users are members of the group
+ :customerscenario: False
+ """
+
+ user1 = keycloak.user("user1").add(password="Secret123")
+ user2 = keycloak.user("user2").add(password="Secret123")
+ group1 = keycloak.group("group1").add().add_members([user1, user2])
+
+ client.sssd.dom("test")["use_fully_qualified_names"] = use_fully_qualified_names
+
+ domain = f"@{client.sssd.default_domain}" if use_fully_qualified_names == "true" else ""
+
+ client.sssd.start(check_config=False)
+
+ user_out = client.tools.id(user1.name + domain)
+ assert user_out is not None, f"User {user1.name} was not found using getent!"
+ assert (
+ user_out.user.name == user1.name + domain
+ ), f"Username {user_out.user.name} is incorrect, {user1.name}{domain} expected!"
+ assert user_out.memberof(
+ group1.name + domain
+ ), f"User {user_out.user.name} is not a member of group {group1.name}{domain}!"
+ assert user_out.memberof(
+ user1.name + domain
+ ), f"User {user_out.user.name} is not a member of group {user1.name}{domain}!"
+
+ group_out = client.tools.getent.group(f"{group1.name}{domain}")
+ assert group_out is not None, f"Group {group1.name}{domain} was not found using getent!"
+ assert (
+ group_out.name == group1.name + domain
+ ), f"Groupname {group_out.name} is incorrect, {group1.name}{domain} expected!"
+ assert (
+ len(group_out.members) == 2
+ ), f"Group {group_out.name} has unexpected number of members [{len(group_out.members)}]!"
+ assert (
+ user1.name + domain in group_out.members
+ ), f"Member {user1.name}{domain} of group {group_out.name} not found!"
+ assert (
+ user2.name + domain in group_out.members
+ ), f"Member {user2.name}{domain} of group {group_out.name} not found!"

View File

@ -1 +1 @@
SHA512 (sssd-2.11.1.tar.gz) = e65897bcb9ddd64f6c01787ad7b7eab3c9916e10f9ead02a6e92de503a4ea71c091e998ccf0344576b520bea75abfe5fd2880e8401237a26274d764d291f6fa4
SHA512 (sssd-2.12.0.tar.gz) = 3bd90a88a43019b00d3f0a674ef4d2473bf6895e749a54bec8ac1661e7d289083e0cbd64846dacc8bdd4b2447f171dddb2d0ba108962dbd862bce86c2247b038

View File

@ -7,7 +7,6 @@
%global build_kcm_renewals 1
%global krb5_version 1.18.2
%global build_passkey 1
%global build_idp 0
%global build_ssh_known_hosts_proxy 0
# we don't want to provide private python extension libs
@ -17,22 +16,22 @@
# Determine the location of the LDB modules directory
%global ldb_modulesdir %(pkg-config --variable=modulesdir ldb)
%global ldb_version 1.2.0
%global samba_package_version %(rpm -q samba-devel --queryformat %{version})
Name: sssd
Version: 2.11.1
Release: 2%{?dist}.1
Version: 2.12.0
Release: 3%{?dist}
Summary: System Security Services Daemon
License: GPL-3.0-or-later
URL: https://github.com/SSSD/sssd/
Source0: https://github.com/SSSD/sssd/releases/download/2.11.1/sssd-2.11.1.tar.gz
Source0: https://github.com/SSSD/sssd/releases/download/2.12.0/sssd-2.12.0.tar.gz
Source1: sssd.sysusers
### Patches ###
Patch0001: 0001-Revert-ipa-improve-handling-of-external-group-member.patch
Patch0002: 0002-krb5-disable-Kerberos-localauth-an2ln-plugin-for-AD-.patch
Patch1: 0001-do-not-require-GID-for-non-POSIX-group.patch
Patch2: 0002-fix-use-after-free-in-kcm_read_options.patch
Patch3: 0003-do-not-update-cache-timeout-if-member-is-added.patch
### Dependencies ###
@ -87,7 +86,7 @@ BuildRequires: libdhash-devel >= 0.4.2
BuildRequires: libfido2-devel
%endif
BuildRequires: libini_config-devel >= 1.3
BuildRequires: libldb-devel >= %{ldb_version}
BuildRequires: libldb-devel
BuildRequires: libnfsidmap-devel
BuildRequires: libnl3-devel
BuildRequires: libselinux-devel
@ -163,7 +162,7 @@ Obsoletes: libsss_simpleifp-debuginfo < 2.9.2
Obsoletes: sssd-polkit-rules < 2.10.0
# Requires
# due to ABI changes in 1.1.30/1.2.0
Requires: libldb >= %{ldb_version}
Requires: libldb >= %{samba_package_version}
Requires: libtevent >= 0.11.0
Requires: sssd-client%{?_isa} = %{version}-%{release}
Requires: (libsss_sudo = %{version}-%{release} if sudo)
@ -474,14 +473,17 @@ An implementation of a Kerberos KCM server. Use this package if you want to
use the KCM: Kerberos credentials cache.
%package idp
Summary: Kerberos plugins and OIDC helper for external identity providers.
Summary: The IdP back end of the SSSD, Kerberos plugins and OIDC helper
License: GPL-3.0-or-later
Requires: sssd-common = %{version}-%{release}
Requires: libsss_idmap = %{version}-%{release}
%description idp
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.
Provides the Identity Provider (IdP) back end that the SSSD can utilize to fetch
identity data from and authenticate against an IdP like Keycloak or Entra ID
server. Additionally this package provides Kerberos plugins that are required to
enable authentication against external identity providers, if the KDC supports
it, and a helper program to handle the OAuth 2.0 Device Authorization Grant.
%if %{build_passkey}
%package passkey
@ -499,7 +501,7 @@ enable authentication with passkey token.
%endif
%prep
%autosetup -n sssd-2.11.1 -p1
%autosetup -n %{name}-%{version_no_tilde} -p1
%build
@ -534,9 +536,6 @@ autoreconf -ivf
%endif
%if %{build_ssh_known_hosts_proxy}
--with-ssh-known-hosts-proxy \
%endif
%if ! %{build_idp}
--with-id-provider-idp=no
%endif
%{nil}
@ -982,10 +981,8 @@ install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/sssd.conf
%{_mandir}/man8/sssd-kcm.8*
%files idp
%if %{build_idp}
%{_libdir}/%{name}/libsss_idp.so
%{_mandir}/man5/sssd-idp.5*
%endif
%{_libexecdir}/%{servicename}/oidc_child
%{_libdir}/%{name}/modules/sssd_krb5_idp_plugin.so
%{_datadir}/sssd/krb5-snippets/sssd_enable_idp
@ -1093,9 +1090,34 @@ fi
%systemd_postun_with_restart sssd.service
%changelog
* Tue Oct 21 2025 Sumit Bose <sbose@redhat.com> - 2.11.1-2.1
- Resovles: RHEL-120288 - CVE-2025-11561 sssd: SSSD default Kerberos configuration allows
privilege escalation on AD-joined Linux systems [rhel-10.1.z]
* Tue Apr 14 2026 Tomas Halman <thalman@redhat.com> - 2.12.0-3
- Resolves: RHEL-167749 - SSSD IdP (Entra ID): listing group members does not work
- Resolves: RHEL-167757 - sssd-kcm fails to start if krb5_renew_interval is specified
* Thu Apr 2 2026 Tomas Halman <thalman@redhat.com> - 2.12.0-2
- Resolves: RHEL-148232 - Failed to resolve indirect group-members of nested non-POSIX group
* Thu Jan 15 2026 Sumit Bose <sbose@redhat.com> - 2.12.0-1
- Resolves: RHEL-139110 - Rebase SSSD for RHEL 10.2
- Resolves: RHEL-132552 - sssd_be: segfault at 8 ip 00007f6fd25b2b90 sp 00007ffc02dfbae0 error 4 in libsss_ipa.so[7f6fd25ae000+4d000]
- Resolves: RHEL-132505 - RFE: package LDAP provider support for subid ranges
- Resolves: RHEL-130571 - SSSD: change a default value of 'session_provider' sssd.conf option to 'none'
- Resolves: RHEL-129636 - sssd service fails to start after updating to 2.9.6-4 or 2.9.7-4
- Resolves: RHEL-128594 - 'sssd_nss' hangs when looking up an object by ID that has expired cache entry and filtered out by name
- Resolves: RHEL-127792 - Remove SSSD option ipa_enable_dns_sites
- Resolves: RHEL-120501 - Crash in 'sss_client/autofs/sss_autofs.c'
- Resolves: RHEL-120287 - CVE-2025-11561 sssd: SSSD default Kerberos configuration allows privilege escalation on AD-joined Linux systems [rhel-10.2]
- Resolves: RHEL-114468 - Spam in 'sssd_kcm.log' during normal operations
- Resolves: RHEL-113111 - Including innapropriate IPv6 addresses in dyndns_update
- Resolves: RHEL-104221 - The SSSD cache is filled with groups having GID=0, causing the cache index to grow excessively large. This, in turn, leads to timeouts
- Resolves: RHEL-94545 - When the user name of an AD user in an IPA-AD trust environment overwritten, the user private group, the users primary group, cannot be lookup up by the overwritten name.
- Resolves: RHEL-77184 - AD user in external group is not cleared when expiring the cache
- Resolves: RHEL-72935 - sss_override does not work on AD UPN
- Resolves: RHEL-11913 - GDM Support for IdM IdP feature and MFA [SSSD]
- Resolves: RHEL-4990 - [RFE] SSSD support for Azure AD / Microsoft Entra ID (or general direct support of OIDC authentication)
* Mon Sep 22 2025 Pavel Filipenský <pfilipen@redhat.com> - 2.11.1-3
- Related: RHEL-114545 - Rebase Samba to the latest 4.23.x release
* Thu Aug 14 2025 Alexey Tikhonov <atikhono@redhat.com> - 2.11.1-2
- Related: RHEL-77184 - AD user in external group is not cleared when expiring the cache