389-ds-base/SOURCES/0044-Issue-6571-2nd-Nested-group-does-not-receive-memberO.patch

273 lines
10 KiB
Diff

From 17da0257b24749765777a4e64c3626cb39cca639 Mon Sep 17 00:00:00 2001
From: tbordaz <tbordaz@redhat.com>
Date: Mon, 31 Mar 2025 11:05:01 +0200
Subject: [PATCH] Issue 6571 - (2nd) Nested group does not receive memberOf
attribute (#6697)
Bug description:
erroneous debug change made in previous fix
where cache_ancestors is called with the wrong parameter
Fix description:
Restore the orginal param 'member_data'
Increase the set of tests around multipaths
fixes: #6571
review by: Simon Pichugin (Thanks !!)
---
.../suites/memberof_plugin/regression_test.py | 154 ++++++++++++++++++
ldap/servers/plugins/memberof/memberof.c | 50 +++++-
2 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/dirsrvtests/tests/suites/memberof_plugin/regression_test.py b/dirsrvtests/tests/suites/memberof_plugin/regression_test.py
index dba908975..9ba40a0c3 100644
--- a/dirsrvtests/tests/suites/memberof_plugin/regression_test.py
+++ b/dirsrvtests/tests/suites/memberof_plugin/regression_test.py
@@ -598,6 +598,8 @@ def test_multipaths(topology_st, request):
'homeDirectory': '/home/user1'
})
group = Groups(inst, SUFFIX, rdn=None)
+ g0 = group.create(properties={'cn': 'group0',
+ 'description': 'group0'})
g1 = group.create(properties={'cn': 'group1',
'member': user1.dn,
'description': 'group1'})
@@ -635,6 +637,158 @@ def test_multipaths(topology_st, request):
_check_membership(inst, g21, expected_members=[user1], expected_memberof=[g2, g1])
_check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1])
+ #inst.config.replace('nsslapd-errorlog-level', '65536')
+ #inst.config.set('nsslapd-accesslog-level','260')
+ #inst.config.set('nsslapd-plugin-logging', 'on')
+ #inst.config.set('nsslapd-auditlog-logging-enabled','on')
+ #inst.config.set('nsslapd-auditfaillog-logging-enabled','on')
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # ^
+ # /
+ # Grp2 --> Grp21 --
+ #
+ g1.remove_member(g2.dn)
+ time.sleep(delay)
+
+ #
+ # Check G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g1, expected_members=[user1], expected_memberof=[])
+ _check_membership(inst, g2, expected_members=[g21], expected_memberof=[])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g2])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1])
+
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # \__________ ^
+ # | /
+ # v /
+ # Grp2 --> Grp21 ----
+ #
+ g1.add_member(g21.dn)
+ time.sleep(delay)
+
+ #
+ # Check G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g1, expected_members=[user1, g21], expected_memberof=[])
+ _check_membership(inst, g2, expected_members=[g21], expected_memberof=[])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g2, g1])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1])
+
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # ^
+ # /
+ # Grp2 --> Grp21 --
+ #
+ g1.remove_member(g21.dn)
+ time.sleep(delay)
+
+ #
+ # Check G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g1, expected_members=[user1], expected_memberof=[])
+ _check_membership(inst, g2, expected_members=[g21], expected_memberof=[])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g2])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1])
+
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # ^
+ # /
+ # Grp0 ---> Grp2 ---> Grp21 ---
+ #
+ g0.add_member(g2.dn)
+ time.sleep(delay)
+
+ #
+ # Check G0,G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g0, expected_members=[g2], expected_memberof=[])
+ _check_membership(inst, g1, expected_members=[user1], expected_memberof=[])
+ _check_membership(inst, g2, expected_members=[g21], expected_memberof=[g0])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g0, g2])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1, g0])
+
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # ^ ^
+ # / /
+ # Grp0 ---> Grp2 ---> Grp21 ---
+ #
+ g0.add_member(g1.dn)
+ time.sleep(delay)
+
+ #
+ # Check G0,G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g0, expected_members=[g1,g2], expected_memberof=[])
+ _check_membership(inst, g1, expected_members=[user1], expected_memberof=[g0])
+ _check_membership(inst, g2, expected_members=[g21], expected_memberof=[g0])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g0, g2])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1, g0])
+
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # ^ \_____________ ^
+ # / | /
+ # / V /
+ # Grp0 ---> Grp2 ---> Grp21 ---
+ #
+ g1.add_member(g21.dn)
+ time.sleep(delay)
+
+ #
+ # Check G0,G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g0, expected_members=[g1, g2], expected_memberof=[])
+ _check_membership(inst, g1, expected_members=[user1, g21], expected_memberof=[g0])
+ _check_membership(inst, g2, expected_members=[g21], expected_memberof=[g0])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g0, g1, g2])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g2, g1, g0])
+
+ #
+ # Update the hierarchy
+ #
+ #
+ # Grp1 ----------------> User1
+ # ^ \_____________ ^
+ # / | /
+ # / V /
+ # Grp0 ---> Grp2 Grp21 ---
+ #
+ g2.remove_member(g21.dn)
+ time.sleep(delay)
+
+ #
+ # Check G0,G1, G2, G21 and User1 members and memberof
+ #
+ _check_membership(inst, g0, expected_members=[g1, g2], expected_memberof=[])
+ _check_membership(inst, g1, expected_members=[user1, g21], expected_memberof=[g0])
+ _check_membership(inst, g2, expected_members=[], expected_memberof=[g0])
+ _check_membership(inst, g21, expected_members=[user1], expected_memberof=[g0, g1])
+ _check_membership(inst, user1, expected_members=[], expected_memberof=[g21, g1, g0])
+
def fin():
try:
user1.delete()
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c
index 32bdcf3f1..f79b083a9 100644
--- a/ldap/servers/plugins/memberof/memberof.c
+++ b/ldap/servers/plugins/memberof/memberof.c
@@ -3258,6 +3258,35 @@ merge_ancestors(Slapi_Value **member_ndn_val, memberof_get_groups_data *v1, memb
Slapi_ValueSet *v2_group_norm_vals = *((memberof_get_groups_data *)v2)->group_norm_vals;
int merged_cnt = 0;
+#if MEMBEROF_CACHE_DEBUG
+ {
+ Slapi_Value *val = 0;
+ int hint = 0;
+ struct berval *bv;
+ hint = slapi_valueset_first_value(v2_groupvals, &val);
+ while (val) {
+ /* this makes a copy of the berval */
+ bv = slapi_value_get_berval(val);
+ if (bv && bv->bv_len) {
+ slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "merge_ancestors: V2 contains %s\n",
+ bv->bv_val);
+ }
+ hint = slapi_valueset_next_value(v2_groupvals, hint, &val);
+ }
+ hint = slapi_valueset_first_value(v1_groupvals, &val);
+ while (val) {
+ /* this makes a copy of the berval */
+ bv = slapi_value_get_berval(val);
+ if (bv && bv->bv_len) {
+ slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "merge_ancestors: add %s (from V1)\n",
+ bv->bv_val);
+ }
+ hint = slapi_valueset_next_value(v1_groupvals, hint, &val);
+ }
+ }
+#endif
hint = slapi_valueset_first_value(v1_groupvals, &sval);
while (sval) {
if (memberof_compare(config, member_ndn_val, &sval)) {
@@ -3319,7 +3348,7 @@ memberof_get_groups_r(MemberOfConfig *config, Slapi_DN *member_sdn, memberof_get
merge_ancestors(&member_ndn_val, &member_data, data);
if (!cached && member_data.use_cache)
- cache_ancestors(config, &member_ndn_val, data);
+ cache_ancestors(config, &member_ndn_val, &member_data);
slapi_value_free(&member_ndn_val);
slapi_valueset_free(groupvals);
@@ -4285,6 +4314,25 @@ memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
/* get a list of all of the groups this user belongs to */
groups = memberof_get_groups(config, sdn);
+#if MEMBEROF_CACHE_DEBUG
+ {
+ Slapi_Value *val = 0;
+ int hint = 0;
+ struct berval *bv;
+ hint = slapi_valueset_first_value(groups, &val);
+ while (val) {
+ /* this makes a copy of the berval */
+ bv = slapi_value_get_berval(val);
+ if (bv && bv->bv_len) {
+ slapi_log_err(SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "memberof_fix_memberof_callback: %s belongs to %s\n",
+ ndn,
+ bv->bv_val);
+ }
+ hint = slapi_valueset_next_value(groups, hint, &val);
+ }
+ }
+#endif
if (config->group_filter) {
if (slapi_filter_test_simple(e, config->group_filter)) {
--
2.49.0