From 17da0257b24749765777a4e64c3626cb39cca639 Mon Sep 17 00:00:00 2001 From: tbordaz 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