diff options
author | Nathan Kinder <nkinder@redhat.com> | 2008-07-01 22:30:07 +0000 |
---|---|---|
committer | Nathan Kinder <nkinder@redhat.com> | 2008-07-01 22:30:07 +0000 |
commit | 8bf8f52b94bdf7df248eaca6f6feb58a0b835c8f (patch) | |
tree | 3754cf1d14069a68e951455ee1e3f2fafd77851d /ldap/servers | |
parent | ab2d605d10f34442cb561bf0d88d1e497f0eb0f4 (diff) | |
download | ds-8bf8f52b94bdf7df248eaca6f6feb58a0b835c8f.tar.gz ds-8bf8f52b94bdf7df248eaca6f6feb58a0b835c8f.tar.xz ds-8bf8f52b94bdf7df248eaca6f6feb58a0b835c8f.zip |
Resolves: 453011
Summary: Redesigned algorithm used to update memberOf attribute.
Diffstat (limited to 'ldap/servers')
-rw-r--r-- | ldap/servers/plugins/memberof/memberof.c | 547 | ||||
-rw-r--r-- | ldap/servers/plugins/memberof/memberof.h | 1 | ||||
-rw-r--r-- | ldap/servers/plugins/memberof/memberof_config.c | 17 |
3 files changed, 178 insertions, 387 deletions
diff --git a/ldap/servers/plugins/memberof/memberof.c b/ldap/servers/plugins/memberof/memberof.c index a8bb98f4..9583a6d0 100644 --- a/ldap/servers/plugins/memberof/memberof.c +++ b/ldap/servers/plugins/memberof/memberof.c @@ -87,6 +87,13 @@ typedef struct _memberofstringll void *next; } memberofstringll; +typedef struct _memberof_get_groups_data +{ + MemberOfConfig *config; + Slapi_Value *memberdn_val; + Slapi_ValueSet **groupvals; +} memberof_get_groups_data; + /*** function prototypes ***/ /* exported functions */ @@ -133,17 +140,15 @@ static void *memberof_get_plugin_id(); static int memberof_compare(MemberOfConfig *config, const void *a, const void *b); static int memberof_qsort_compare(const void *a, const void *b); static void memberof_load_array(Slapi_Value **array, Slapi_Attr *attr); -static int memberof_is_legit_member(Slapi_PBlock *pb, MemberOfConfig *config, - char *group_dn, char *op_this, char *op_to, memberofstringll *stack); static int memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn); static int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn, char *type, plugin_search_entry_callback callback, void *callback_data); static int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn, Slapi_Value *memberdn); -static int memberof_is_member(MemberOfConfig *config, Slapi_Value *groupdn, - Slapi_Value *memberdn); -static int memberof_is_member_r(MemberOfConfig *config, Slapi_Value *groupdn, - Slapi_Value *memberdn, memberofstringll *stack); +static Slapi_ValueSet *memberof_get_groups(MemberOfConfig *config, char *memberdn); +static int memberof_get_groups_r(MemberOfConfig *config, char *memberdn, + memberof_get_groups_data *data); +static int memberof_get_groups_callback(Slapi_Entry *e, void *callback_data); static int memberof_test_membership(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn); static int memberof_test_membership_callback(Slapi_Entry *e, void *callback_data); @@ -154,9 +159,6 @@ static int memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *con static int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op, char *group_dn, char *op_this, char *replace_with, char *op_to, memberofstringll *stack); -static int memberof_add_groups_search_callback(Slapi_Entry *e, void *callback_data); -static int memberof_add_membership(Slapi_PBlock *pb, MemberOfConfig *config, - char *op_this, char *op_to); static int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg); @@ -352,6 +354,8 @@ int memberof_postop_del(Slapi_PBlock *pb) } memberof_unlock(); + + memberof_free_config(&configCopy); } slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM, @@ -359,15 +363,15 @@ int memberof_postop_del(Slapi_PBlock *pb) return ret; } -typedef struct _del_dn_data +typedef struct _memberof_del_dn_data { char *dn; char *type; -} del_dn_data; +} memberof_del_dn_data; int memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn) { - del_dn_data data = {dn, config->groupattr}; + memberof_del_dn_data data = {dn, config->groupattr}; return memberof_call_foreach_dn(pb, dn, config->groupattr, memberof_del_dn_type_callback, &data); @@ -386,11 +390,11 @@ int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data) mods[0] = &mod; mods[1] = 0; - val[0] = ((del_dn_data *)callback_data)->dn; + val[0] = ((memberof_del_dn_data *)callback_data)->dn; val[1] = 0; mod.mod_op = LDAP_MOD_DELETE; - mod.mod_type = ((del_dn_data *)callback_data)->type; + mod.mod_type = ((memberof_del_dn_data *)callback_data)->type; mod.mod_values = val; slapi_modify_internal_set_pb( @@ -524,6 +528,8 @@ int memberof_postop_modrdn(Slapi_PBlock *pb) memberof_replace_dn_from_groups(pb, &configCopy, pre_dn, post_dn); memberof_unlock(); + + memberof_free_config(&configCopy); } } @@ -726,6 +732,11 @@ int memberof_postop_modify(Slapi_PBlock *pb) smod = slapi_mods_get_next_smod(smods, next_mod); } + if (config_copied) + { + memberof_free_config(&configCopy); + } + slapi_mod_free(&next_mod); slapi_mods_free(&smods); } @@ -783,6 +794,8 @@ int memberof_postop_add(Slapi_PBlock *pb) } memberof_unlock(); + + memberof_free_config(&configCopy); } } @@ -1012,7 +1025,7 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, /* someone set up infinitely recursive groups - bail out */ - slapi_log_error( SLAPI_LOG_FATAL, + slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_modop_one_replace_r: group recursion" " detected in %s\n" @@ -1065,38 +1078,13 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, goto bail; } - /* We need to deal with delete cases separately. We may not - * want to remove a memberof attribute from an entry since - * it could still be a member in some other indirect manner. */ - if(stack && LDAP_MOD_DELETE == mod_op) + /* For add and del modify operations, we just regenerate the + * memberOf attribute. */ + if(LDAP_MOD_DELETE == mod_op || LDAP_MOD_ADD == mod_op) { - if(memberof_is_legit_member(pb, config, group_dn, - op_this, op_to, stack)) - { - /* entry is member some other way too */ - slapi_log_error( SLAPI_LOG_PLUGIN, - MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_modop_one_replace_r: not deleting %s\n" - ,op_to); - goto bail; - } - } - - /* Check if the entry is still an indirect member. If it is, we - * don't want to remove the memberOf value. */ - if((LDAP_MOD_DELETE != mod_op) || - (0 == memberof_is_member(config, this_dn_val, to_dn_val))) { - /* If we're about to add a memberOf value to an entry, we should first check - * if the value already exists. */ - if((LDAP_MOD_ADD == mod_op) && (slapi_entry_attr_has_syntax_value(e, - config->memberof_attr, this_dn_val))) - { - slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_modop_one_replace_r: memberOf value %s already exists in " - "entry %s\n", op_this, op_to); - goto bail; - } - + /* find parent groups and replace our member attr */ + memberof_fix_memberof_callback(e, config); + } else { /* single entry - do mod */ mod_pb = slapi_pblock_new(); @@ -1113,7 +1101,6 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, val[0] = op_this; val[1] = 0; - mod.mod_op = LDAP_MOD_REPLACE == mod_op?LDAP_MOD_DELETE:mod_op; mod.mod_type = config->memberof_attr; mod.mod_values = val; @@ -1141,22 +1128,6 @@ int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config, slapi_pblock_destroy(mod_pb); } - - if(LDAP_MOD_DELETE == mod_op) - { - /* fix up membership for groups that have been orphaned */ - memberof_test_membership_callback(e, config); - } - - if(LDAP_MOD_ADD == mod_op) - { - /* If we failed to update memberOf for op_to, we shouldn't - * try to fix up membership for parent groups. */ - if (rc == 0) { - /* fix up membership for groups that are now in scope */ - memberof_add_membership(pb, config, op_this, op_to); - } - } } bail: @@ -1435,26 +1406,88 @@ int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, return rc; } -typedef struct _memberof_add_groups +/* memberof_get_groups() + * + * Gets a list of all groups that an entry is a member of. + * This is done by looking only at member attribute values. + * A Slapi_ValueSet* is returned. It is up to the caller to + * free it. + */ +Slapi_ValueSet *memberof_get_groups(MemberOfConfig *config, char *memberdn) { - MemberOfConfig *config; - char *target_dn; - char *group_dn; -} memberof_add_groups; + Slapi_Value *memberdn_val = slapi_value_new_string(memberdn); + Slapi_ValueSet *groupvals = slapi_valueset_new(); + memberof_get_groups_data data = {config, memberdn_val, &groupvals}; -int memberof_add_membership(Slapi_PBlock *pb, MemberOfConfig *config, - char *op_this, char *op_to) -{ - memberof_add_groups data = {config, op_to, op_this}; + memberof_get_groups_r(config, memberdn, &data); - return memberof_call_foreach_dn(pb, op_this, config->groupattr, - memberof_add_groups_search_callback, &data); + slapi_value_free(&memberdn_val); + + return groupvals; } -int memberof_add_groups_search_callback(Slapi_Entry *e, void *callback_data) +int memberof_get_groups_r(MemberOfConfig *config, char *memberdn, memberof_get_groups_data *data) { - return memberof_add_one(0, ((memberof_add_groups*)callback_data)->config, slapi_entry_get_dn(e), - ((memberof_add_groups*)callback_data)->target_dn); + /* Search for member=<memberdn> + * For each match, add it to the list, recurse and do same search */ + memberof_call_foreach_dn(0, memberdn, config->groupattr, + memberof_get_groups_callback, data); +} + +/* memberof_get_groups_callback() + * + * Callback to perform work of memberof_get_groups() + */ +int memberof_get_groups_callback(Slapi_Entry *e, void *callback_data) +{ + char *group_dn = slapi_entry_get_dn(e); + Slapi_Value *group_dn_val = 0; + Slapi_ValueSet *groupvals = *((memberof_get_groups_data*)callback_data)->groupvals; + + /* get the DN of the group */ + group_dn_val = slapi_value_new_string(group_dn); + + /* check if e is the same as our original member entry */ + if (0 == memberof_compare(((memberof_get_groups_data*)callback_data)->config, + &((memberof_get_groups_data*)callback_data)->memberdn_val, &group_dn_val)) + { + /* A recursive group caused us to find our original + * entry we passed to memberof_get_groups(). We just + * skip processing this entry. */ + slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, + "memberof_get_groups_callback: group recursion" + " detected in %s\n" ,group_dn); + slapi_value_free(&group_dn_val); + goto bail; + + } + + /* have we been here before? */ + if (groupvals && + slapi_valueset_find(((memberof_get_groups_data*)callback_data)->config->group_slapiattr, + groupvals, group_dn_val)) + { + /* we either hit a recursive grouping, or an entry is + * a member of a group through multiple paths. Either + * way, we can just skip processing this entry since we've + * already gone through this part of the grouping hierarchy. */ + slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, + "memberof_get_groups_callback: possible group recursion" + " detected in %s\n" ,group_dn); + slapi_value_free(&group_dn_val); + goto bail; + } + + /* Push group_dn_val into the valueset. This memory is now owned + * by the valueset. */ + slapi_valueset_add_value_ext(groupvals, group_dn_val, SLAPI_VALUE_FLAG_PASSIN); + + /* now recurse to find parent groups of e */ + memberof_get_groups_r(((memberof_get_groups_data*)callback_data)->config, + group_dn, callback_data); + + bail: + return 0; } /* memberof_is_direct_member() @@ -1491,160 +1524,6 @@ int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn, return rc; } -/* memberof_is_member() - * - * tests for membership of memberdn in group groupdn. This - * will check for both direct and indirect membership. - * returns non-zero when true, zero otherwise - */ -int memberof_is_member(MemberOfConfig *config, Slapi_Value *groupdn, - Slapi_Value *memberdn) -{ - memberofstringll *stack = 0; - - /* Do a quick check to see if the entry is a direct - * member before tracing through nested groups. */ - if(memberof_is_direct_member(config, groupdn, memberdn)) - { - /* entry is a direct member */ - return 1; - } - - return memberof_is_member_r(config, groupdn, memberdn, stack); -} - -/* memberof_is_member_r() - * - * Recursive function to do the work for the memberof_is_member() - * function. This will basically check if "memberdn" is a member - * of the group represented by "groupdn". Only "member" attribute - * values will be used to make this determination, not "memberOf" - * attribute values. - * - * returns non-zero when true, zero otherwise - */ -int memberof_is_member_r(MemberOfConfig *config, Slapi_Value *groupdn, - Slapi_Value *memberdn, memberofstringll *stack) -{ - Slapi_DN *member_sdn = 0; - Slapi_DN *base_sdn = 0; - Slapi_PBlock *search_pb = slapi_pblock_new(); - Slapi_Backend *be = 0; - Slapi_Value *ll_dn_val = 0; - memberofstringll *ll = stack; - char *filter_str = 0; - int rc = 0; - - /* Check if we've processed memberdn already to detect looped - * groupings. We want to do this right away to avoid any - * unecessary processing. */ - while(ll) - { - ll_dn_val = slapi_value_new_string(ll->dn); - - if(0 == memberof_compare(config, &ll_dn_val, &memberdn)) - { - slapi_value_free(&ll_dn_val); - - /* someone set up infinitely - * recursive groups - bail out */ - slapi_log_error( SLAPI_LOG_FATAL, - MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_is_member_r: group recursion" - " detected in %s\n" - ,slapi_value_get_string(memberdn)); - /* We set this to null to avoid freeing it twice. - * If we don't do this, we'd free ll in the bail section - * and the caller (ourselves since we're using recursion) - * would free it as well. */ - ll = 0; - goto bail; - } - - slapi_value_free(&ll_dn_val); - ll = ll->next; - } - - /* push memberdn onto the stack to detect loops */ - ll = (memberofstringll*)slapi_ch_malloc(sizeof(memberofstringll)); - ll->dn = slapi_value_get_string(memberdn); - ll->next = stack; - - /* Find the backend suffix that memberdn is in so we can - * use it as a search base. */ - member_sdn = slapi_sdn_new_dn_byref(slapi_value_get_string(memberdn)); - be = slapi_be_select(member_sdn); - if(be) - { - base_sdn = (Slapi_DN*)slapi_be_getsuffix(be,0); - } - - /* Do a search for "member=<memberdn>". Go through matches to - * see if it is our group. If not, search for "member=<matchdn>" - * and keep looping until we've exhausted it. */ - if(base_sdn) - { - filter_str = slapi_ch_smprintf("(%s=%s)", config->groupattr, - slapi_value_get_string(memberdn)); - } - - if(filter_str) - { - slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn), - LDAP_SCOPE_SUBTREE, filter_str, 0, 0, - 0, 0, - memberof_get_plugin_id(), - 0); - - if(slapi_search_internal_pb(search_pb)) - { - /* get result and log an error */ - int res = 0; - slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res); - slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_is_member_r: error searching for groups: %d", - res); - goto bail; - } else { - Slapi_Entry **entries = NULL; - slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); - if ( NULL != entries && NULL != entries[0]) - { - int i; - - for(i = 0; entries[i] != NULL; i++) - { - /* Iterate through the matches checking if the dn is our groupdn. */ - if(strcasecmp(slapi_entry_get_ndn(entries[i]), slapi_value_get_string(groupdn)) == 0) - { - /* This is the group we've been searching for, so - * set rc and bail. */ - rc = 1; - break; - } else { - /* This is not the group you're looking for... - * Find all of the groups that this group is a member of to - * see if any of them are the group we are trying to find. - * We do this by doing a recursive call on this function. */ - Slapi_Value *entrydn = slapi_value_new_string(slapi_entry_get_ndn(entries[i])); - rc = memberof_is_member_r(config, groupdn, entrydn, ll); - slapi_value_free(&entrydn); - } - } - } - } - } - - bail: - slapi_ch_free((void **)&ll); - slapi_ch_free_string(&filter_str); - slapi_sdn_free(&member_sdn); - slapi_free_search_results_internal(search_pb); - slapi_pblock_destroy(search_pb); - - return rc; -} - /* memberof_test_membership() * * Finds all entries who are a "memberOf" the group @@ -2038,156 +1917,6 @@ int memberof_qsort_compare(const void *a, const void *b) slapi_value_get_berval(val2)); } -/* memberof_is_legit_member() - * - * before we rush to remove this group from the entry - * we need to be sure that the entry is not a member - * of the group for another legitimate reason i.e. - * that it is not itself a direct member of the group, - * and that all groups in its memberof attribute except - * the second from bottom one of our stack do not appear - * in the membership attribute of the group -*/ -int memberof_is_legit_member(Slapi_PBlock *pb, MemberOfConfig *config, - char *group_dn, char *op_this, char *op_to, memberofstringll *stack) -{ - int rc = 0; - Slapi_DN *group_sdn = 0; - Slapi_Entry *group_e = 0; - Slapi_DN *opto_sdn = 0; - Slapi_Entry *opto_e = 0; - char *filter_str = 0; - Slapi_Filter *filter = 0; - memberofstringll *ll = 0; - char *attrlist[2] = {config->groupattr,0}; - char *optolist[2] = {config->memberof_attr,0}; - Slapi_Attr *memberof = 0; - Slapi_Value *memberdn = 0; - int hint = 0; - const char *delete_group_dn = 0; - - slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM, - "--> memberof_is_legit_member\n" ); - - /* first test entry */ - group_sdn = slapi_sdn_new_dn_byref(op_this); - slapi_search_internal_get_entry( group_sdn, attrlist, - &group_e, memberof_get_plugin_id()); - slapi_sdn_free(&group_sdn); - - if(!group_e) - { - goto bail; - } - - filter_str = slapi_ch_smprintf("(%s=%s)", config->groupattr, op_to); - filter = slapi_str2filter(filter_str); - - if(!slapi_filter_test_simple(group_e, filter)) - { - /* entry is direct member */ - slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_is_legit_member: %s direct member of %s\n" - ,op_to,op_this); - slapi_filter_free(filter,0); - rc = 1; - goto bail; - } - - slapi_filter_free(filter,0); - - /* test all group dns in stack - the top dn is the group we remove the entry from - second from bottom dn is being removed from the - bottom group, we ignore those two - */ - ll = stack; - - /* need to be 2 items left on the stack */ - while( ll && - ll->next && - ((memberofstringll*)ll->next)->next) - { - ll = ll->next; - } - - if(!ll || !ll->next) - { - /* tight recursion, bail */ - goto bail; - } - - delete_group_dn = ((memberofstringll*)ll->next)->dn; - - /* get the target entry memberof attribute */ - opto_sdn = slapi_sdn_new_dn_byref(op_to); - slapi_search_internal_get_entry( opto_sdn, optolist, - &opto_e, memberof_get_plugin_id()); - slapi_sdn_free(&opto_sdn); - - if(opto_e) - { - slapi_entry_attr_find(opto_e, config->memberof_attr, &memberof); - } - - if(0 == memberof) - { - goto bail; - } - - /* iterate through memberof values and test against group membership */ - hint = slapi_attr_first_value(memberof, &memberdn); - - while(memberdn) - { - char *dn = (char*)slapi_value_get_string(memberdn); - int current_size = - (strlen(config->groupattr) + - strlen(dn) + 4); /* 4 for (=) + null */ - - /* disregard the group being removed */ - if(0 == strcmp(dn, delete_group_dn)) - { - hint = slapi_attr_next_value(memberof, hint, &memberdn); - continue; - } - - if (current_size > strlen(filter_str)) - { - int filter_size = 2 * current_size; - filter_str = slapi_ch_realloc(filter_str, filter_size); - } - - sprintf(filter_str, "(%s=%s)", config->groupattr, dn); - filter = slapi_str2filter(filter_str); - - if(!slapi_filter_test_simple(group_e, filter)) - { - /* another group allows entry */ - slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM, - "memberof_is_legit_member: %s is group member of %s\n" - ,op_to,dn); - slapi_filter_free(filter,0); - - rc = 1; - goto bail; - } - - slapi_filter_free(filter,0); - - hint = slapi_attr_next_value(memberof, hint, &memberdn); - } - -bail: - slapi_entry_free(group_e); - slapi_entry_free(opto_e); - slapi_ch_free_string(&filter_str); - - slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM, - "<-- memberof_is_legit_member\n" ); - return rc; -} - void memberof_lock() { slapi_lock_mutex(memberof_operation_lock); @@ -2235,6 +1964,8 @@ void memberof_fixup_task_thread(void *arg) /* release the memberOf operation lock */ memberof_unlock(); + memberof_free_config(&configCopy); + slapi_task_log_notice(task, "Memberof task finished."); slapi_task_log_status(task, "Memberof task finished."); slapi_task_inc_progress(task); @@ -2372,15 +2103,57 @@ int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data) int rc = 0; char *dn = slapi_entry_get_dn(e); MemberOfConfig *config = (MemberOfConfig *)callback_data; - memberof_add_groups data = {config, dn, dn}; + memberof_del_dn_data del_data = {0, config->memberof_attr}; + Slapi_ValueSet *groups = 0; + + /* get a list of all of the groups this user belongs to */ + groups = memberof_get_groups(config, dn); + + /* If we found some groups, replace the existing memberOf attribute + * with the found values. */ + if (groups && slapi_valueset_count(groups)) + { + Slapi_PBlock *mod_pb = slapi_pblock_new(); + Slapi_Value *val = 0; + Slapi_Mod smod; + LDAPMod **mods = (LDAPMod **) slapi_ch_malloc(2 * sizeof(LDAPMod *)); + int hint = 0; + + slapi_mod_init(&smod, 0); + slapi_mod_set_operation(&smod, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES); + slapi_mod_set_type(&smod, config->memberof_attr); + + /* Loop through all of our values and add them to smod */ + hint = slapi_valueset_first_value(groups, &val); + while (val) + { + /* this makes a copy of the berval */ + slapi_mod_add_value(&smod, slapi_value_get_berval(val)); + hint = slapi_valueset_next_value(groups, hint, &val); + } + + mods[0] = slapi_mod_get_ldapmod_passout(&smod); + mods[1] = 0; + + slapi_modify_internal_set_pb( + mod_pb, dn, mods, 0, 0, + memberof_get_plugin_id(), 0); - /* step 1 */ - slapi_entry_attr_delete(e, config->memberof_attr); + slapi_modify_internal_pb(mod_pb); - /* step 2 and 3 */ - rc = memberof_call_foreach_dn(0, dn, config->groupattr, - memberof_add_groups_search_callback, &data); + slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc); + ldap_mods_free(mods, 1); + slapi_mod_done(&smod); + slapi_pblock_destroy(mod_pb); + } else { + /* No groups were found, so remove the memberOf attribute + * from this entry. */ + memberof_del_dn_type_callback(e, &del_data); + } + + slapi_valueset_free(groups); + return rc; } diff --git a/ldap/servers/plugins/memberof/memberof.h b/ldap/servers/plugins/memberof/memberof.h index 139be784..268f16c7 100644 --- a/ldap/servers/plugins/memberof/memberof.h +++ b/ldap/servers/plugins/memberof/memberof.h @@ -84,6 +84,7 @@ typedef struct memberofconfig { */ int memberof_config(Slapi_Entry *config_e); void memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src); +void memberof_free_config(MemberOfConfig *config); MemberOfConfig *memberof_get_config(); void memberof_lock(); void memberof_unlock(); diff --git a/ldap/servers/plugins/memberof/memberof_config.c b/ldap/servers/plugins/memberof/memberof_config.c index 63f3f7a8..60679b69 100644 --- a/ldap/servers/plugins/memberof/memberof_config.c +++ b/ldap/servers/plugins/memberof/memberof_config.c @@ -291,6 +291,23 @@ memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src) } /* + * memberof_free_config() + * + * Free's the contents of a config structure. + */ +void +memberof_free_config(MemberOfConfig *config) +{ + if (config) + { + slapi_ch_free_string(&config->groupattr); + slapi_filter_free(config->group_filter, 1); + slapi_attr_free(&config->group_slapiattr); + slapi_ch_free_string(&config->memberof_attr); + } +} + +/* * memberof_get_config() * * Returns a pointer to the main config. You should call |