273 lines
10 KiB
Diff
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
|
|
|