| |
@@ -73,7 +73,8 @@
|
| |
static void automember_free_regex_rule(struct automemberRegexRule *rule);
|
| |
static int automember_parse_grouping_attr(char *value, char **grouping_attr, char **grouping_value);
|
| |
static int automember_update_membership(struct configEntry *config, Slapi_Entry *e, PRFileDesc *ldif_fd);
|
| |
- static int automember_add_member_value(Slapi_Entry *member_e, const char *group_dn, char *grouping_attr, char *grouping_value, PRFileDesc *ldif_fd);
|
| |
+ static int automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char *grouping_attr,
|
| |
+ char *grouping_value, PRFileDesc *ldif_fd, int add);
|
| |
|
| |
/*
|
| |
* task functions
|
| |
@@ -89,6 +90,8 @@
|
| |
static void automember_task_map_destructor(Slapi_Task *task);
|
| |
|
| |
#define DEFAULT_FILE_MODE PR_IRUSR | PR_IWUSR
|
| |
+ static uint64_t plugin_do_modify = 1;
|
| |
+ static uint64_t plugin_is_betxn = 0;
|
| |
|
| |
/*
|
| |
* Config cache locking functions
|
| |
@@ -139,8 +142,6 @@
|
| |
return _PluginDN;
|
| |
}
|
| |
|
| |
- static int plugin_is_betxn = 0;
|
| |
-
|
| |
/*
|
| |
* Plug-in initialization functions
|
| |
*/
|
| |
@@ -158,8 +159,7 @@
|
| |
"--> automember_init\n");
|
| |
|
| |
/* get args */
|
| |
- if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
|
| |
- plugin_entry &&
|
| |
+ if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) && plugin_entry &&
|
| |
(plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) &&
|
| |
plugin_type && strstr(plugin_type, "betxn")) {
|
| |
plugin_is_betxn = 1;
|
| |
@@ -297,7 +297,9 @@
|
| |
automember_start(Slapi_PBlock *pb)
|
| |
{
|
| |
Slapi_DN *plugindn = NULL;
|
| |
+ Slapi_Entry *plugin_entry = NULL;
|
| |
char *config_area = NULL;
|
| |
+ const char *do_modify = NULL;
|
| |
|
| |
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
"--> automember_start\n");
|
| |
@@ -342,8 +344,22 @@
|
| |
return -1;
|
| |
}
|
| |
|
| |
+ /* Check and set if we should process modify operations */
|
| |
+ plugin_do_modify = 1; /* default is "on" */
|
| |
+ if ((slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry) == 0) && plugin_entry){
|
| |
+ if ((do_modify = slapi_fetch_attr(plugin_entry, AUTOMEMBER_DO_MODIFY, NULL)) ) {
|
| |
+ if (strcasecmp(do_modify, "on") && strcasecmp(do_modify, "off")) {
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_start - %s: invalid value \"%s\". Valid values are \"on\" or \"off\". Using default of \"on\"\n",
|
| |
+ AUTOMEMBER_DO_MODIFY, do_modify);
|
| |
+ } else if (strcasecmp(do_modify, "off") == 0 ){
|
| |
+ plugin_do_modify = 0;
|
| |
+ }
|
| |
+ }
|
| |
+ }
|
| |
+
|
| |
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "auto membership plug-in: ready for service\n");
|
| |
+ "automember_start - ready for service\n");
|
| |
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
"<-- automember_start\n");
|
| |
|
| |
@@ -1365,37 +1381,49 @@
|
| |
}
|
| |
|
| |
/*
|
| |
- * automember_update_membership()
|
| |
- *
|
| |
- * Determines which target groups need to be updated according to
|
| |
- * the rules in config, then performs the updates.
|
| |
+ * Free the exclusion and inclusion group dn's created by
|
| |
+ * automember_get_membership_lists()
|
| |
*/
|
| |
- static int
|
| |
- automember_update_membership(struct configEntry *config, Slapi_Entry *e, PRFileDesc *ldif_fd)
|
| |
+ static void
|
| |
+ automember_free_membership_lists(PRCList *exclusions, PRCList *targets)
|
| |
+ {
|
| |
+ struct automemberDNListItem *dnitem = NULL;
|
| |
+
|
| |
+ /*
|
| |
+ * Free the exclusions and targets lists. Remember that the DN's
|
| |
+ * are not ours, so don't free them!
|
| |
+ */
|
| |
+ while (!PR_CLIST_IS_EMPTY(exclusions)) {
|
| |
+ dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(exclusions);
|
| |
+ PR_REMOVE_LINK((PRCList *)dnitem);
|
| |
+ slapi_ch_free((void **)&dnitem);
|
| |
+ }
|
| |
+
|
| |
+ while (!PR_CLIST_IS_EMPTY(targets)) {
|
| |
+ dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(targets);
|
| |
+ PR_REMOVE_LINK((PRCList *)dnitem);
|
| |
+ slapi_ch_free((void **)&dnitem);
|
| |
+ }
|
| |
+ }
|
| |
+
|
| |
+ /*
|
| |
+ * Populate the exclusion and inclusion(target) PRCLists based on the
|
| |
+ * slapi entry and configEntry provided. The PRCLists should be freed
|
| |
+ * using automember_free_membership_lists()
|
| |
+ */
|
| |
+ static void
|
| |
+ automember_get_membership_lists(struct configEntry *config, PRCList *exclusions, PRCList *targets, Slapi_Entry *e)
|
| |
{
|
| |
PRCList *rule = NULL;
|
| |
struct automemberRegexRule *curr_rule = NULL;
|
| |
- PRCList exclusions;
|
| |
- PRCList targets;
|
| |
struct automemberDNListItem *dnitem = NULL;
|
| |
Slapi_DN *last = NULL;
|
| |
PRCList *curr_exclusion = NULL;
|
| |
char **vals = NULL;
|
| |
- int rc = 0;
|
| |
int i = 0;
|
| |
|
| |
- if (!config || !e) {
|
| |
- return -1;
|
| |
- }
|
| |
-
|
| |
- slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "automember_update_membership - Processing \"%s\" "
|
| |
- "definition entry for candidate entry \"%s\".\n",
|
| |
- config->dn, slapi_entry_get_dn(e));
|
| |
-
|
| |
- /* Initialize our lists that keep track of targets. */
|
| |
- PR_INIT_CLIST(&exclusions);
|
| |
- PR_INIT_CLIST(&targets);
|
| |
+ PR_INIT_CLIST(exclusions);
|
| |
+ PR_INIT_CLIST(targets);
|
| |
|
| |
/* Go through exclusive rules and build an exclusion list. */
|
| |
if (config->exclusive_rules) {
|
| |
@@ -1416,20 +1444,19 @@
|
| |
/* Found a match. Add to end of the exclusion list
|
| |
* and set last as a hint to ourselves. */
|
| |
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "automember_update_membership - Adding \"%s\" "
|
| |
+ "automember_get_membership_lists - Adding \"%s\" "
|
| |
"to list of excluded groups for \"%s\" "
|
| |
"(matched: \"%s=%s\").\n",
|
| |
slapi_sdn_get_dn(curr_rule->target_group_dn),
|
| |
slapi_entry_get_dn(e), curr_rule->attr,
|
| |
curr_rule->regex_str);
|
| |
- dnitem = (struct automemberDNListItem *)slapi_ch_calloc(1,
|
| |
- sizeof(struct automemberDNListItem));
|
| |
+ dnitem = (struct automemberDNListItem *)slapi_ch_calloc(1, sizeof(struct automemberDNListItem));
|
| |
/* We are just referencing the dn from the regex rule. We
|
| |
* will not free it when we clean up this list. This list
|
| |
* is more short-lived than the regex rule list, so we can
|
| |
* get away with this optimization. */
|
| |
dnitem->dn = curr_rule->target_group_dn;
|
| |
- PR_APPEND_LINK(&(dnitem->list), &exclusions);
|
| |
+ PR_APPEND_LINK(&(dnitem->list), exclusions);
|
| |
last = curr_rule->target_group_dn;
|
| |
}
|
| |
}
|
| |
@@ -1450,8 +1477,8 @@
|
| |
last = NULL;
|
| |
|
| |
/* Get the first excluded target for exclusion checking. */
|
| |
- if (!PR_CLIST_IS_EMPTY(&exclusions)) {
|
| |
- curr_exclusion = PR_LIST_HEAD(&exclusions);
|
| |
+ if (!PR_CLIST_IS_EMPTY(exclusions)) {
|
| |
+ curr_exclusion = PR_LIST_HEAD(exclusions);
|
| |
}
|
| |
|
| |
rule = PR_LIST_HEAD((PRCList *)config->inclusive_rules);
|
| |
@@ -1468,7 +1495,7 @@
|
| |
* until we find a target that is the same or comes after the
|
| |
* current rule. */
|
| |
if (curr_exclusion) {
|
| |
- while ((curr_exclusion != &exclusions) && (slapi_sdn_compare(
|
| |
+ while ((curr_exclusion != exclusions) && (slapi_sdn_compare(
|
| |
((struct automemberDNListItem *)curr_exclusion)->dn,
|
| |
curr_rule->target_group_dn) < 0)) {
|
| |
curr_exclusion = PR_NEXT_LINK(curr_exclusion);
|
| |
@@ -1479,7 +1506,7 @@
|
| |
* we can skip all rules for the last target group DN that we
|
| |
* added to the targets list. We also skip any rules for
|
| |
* target groups that have been excluded by an exclusion rule. */
|
| |
- if (((curr_exclusion == NULL) || (curr_exclusion == &exclusions) ||
|
| |
+ if (((curr_exclusion == NULL) || (curr_exclusion == exclusions) ||
|
| |
slapi_sdn_compare(((struct automemberDNListItem *)curr_exclusion)->dn,
|
| |
curr_rule->target_group_dn) != 0) &&
|
| |
((last == NULL) ||
|
| |
@@ -1492,7 +1519,7 @@
|
| |
/* Found a match. Add to the end of the targets list
|
| |
* and set last as a hint to ourselves. */
|
| |
slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "automember_update_membership - Adding \"%s\" "
|
| |
+ "automember_get_membership_lists - Adding \"%s\" "
|
| |
"to list of target groups for \"%s\" "
|
| |
"(matched: \"%s=%s\").\n",
|
| |
slapi_sdn_get_dn(curr_rule->target_group_dn),
|
| |
@@ -1505,7 +1532,7 @@
|
| |
* is more short-lived than the regex rule list, so we can
|
| |
* get away with this optimization. */
|
| |
dnitem->dn = curr_rule->target_group_dn;
|
| |
- PR_APPEND_LINK(&(dnitem->list), &targets);
|
| |
+ PR_APPEND_LINK(&(dnitem->list), targets);
|
| |
last = curr_rule->target_group_dn;
|
| |
}
|
| |
}
|
| |
@@ -1518,6 +1545,42 @@
|
| |
}
|
| |
}
|
| |
}
|
| |
+ }
|
| |
+
|
| |
+ /*
|
| |
+ * automember_update_membership()
|
| |
+ *
|
| |
+ * Determines which target groups need to be updated according to
|
| |
+ * the rules in config, then performs the updates.
|
| |
+ *
|
| |
+ * Return SLAPI_PLUGIN_FAILURE for failures, or
|
| |
+ * SLAPI_PLUGIN_SUCCESS for success (no memberships updated), or
|
| |
+ * MEMBERSHIP_UPDATED for success (memberships updated)
|
| |
+ */
|
| |
+ static int
|
| |
+ automember_update_membership(struct configEntry *config, Slapi_Entry *e, PRFileDesc *ldif_fd)
|
| |
+ {
|
| |
+ PRCList exclusions;
|
| |
+ PRCList targets;
|
| |
+ struct automemberDNListItem *dnitem = NULL;
|
| |
+ int rc = SLAPI_PLUGIN_SUCCESS;
|
| |
+ int i = 0;
|
| |
+
|
| |
+ if (!config || !e) {
|
| |
+ return SLAPI_PLUGIN_FAILURE;
|
| |
+ }
|
| |
+
|
| |
+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_update_membership - Processing \"%s\" "
|
| |
+ "definition entry for candidate entry \"%s\".\n",
|
| |
+ config->dn, slapi_entry_get_dn(e));
|
| |
+
|
| |
+ /* Initialize our lists that keep track of targets. */
|
| |
+ PR_INIT_CLIST(&exclusions);
|
| |
+ PR_INIT_CLIST(&targets);
|
| |
+
|
| |
+ /* get the membership lists */
|
| |
+ automember_get_membership_lists(config, &exclusions, &targets, e);
|
| |
|
| |
/* If no targets, update default groups if set. Otherwise, update
|
| |
* targets. Use a helper to do the actual updates. We can just pass an
|
| |
@@ -1526,51 +1589,45 @@
|
| |
if (PR_CLIST_IS_EMPTY(&targets)) {
|
| |
/* Add to each default group. */
|
| |
for (i = 0; config->default_groups && config->default_groups[i]; i++) {
|
| |
- if (automember_add_member_value(e, config->default_groups[i], config->grouping_attr,
|
| |
- config->grouping_value, ldif_fd)) {
|
| |
+ if (automember_update_member_value(e, config->default_groups[i], config->grouping_attr,
|
| |
+ config->grouping_value, ldif_fd, ADD_MEMBER))
|
| |
+ {
|
| |
rc = SLAPI_PLUGIN_FAILURE;
|
| |
goto out;
|
| |
}
|
| |
+ rc = MEMBERSHIP_UPDATED;
|
| |
}
|
| |
} else {
|
| |
/* Update the target groups. */
|
| |
dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&targets);
|
| |
while ((PRCList *)dnitem != &targets) {
|
| |
- if (automember_add_member_value(e, slapi_sdn_get_dn(dnitem->dn), config->grouping_attr,
|
| |
- config->grouping_value, ldif_fd)) {
|
| |
+ if (automember_update_member_value(e, slapi_sdn_get_dn(dnitem->dn), config->grouping_attr,
|
| |
+ config->grouping_value, ldif_fd, ADD_MEMBER))
|
| |
+ {
|
| |
rc = SLAPI_PLUGIN_FAILURE;
|
| |
goto out;
|
| |
}
|
| |
dnitem = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dnitem);
|
| |
+ rc = MEMBERSHIP_UPDATED;
|
| |
}
|
| |
}
|
| |
|
| |
- /* Free the exclusions and targets lists. Remember that the DN's
|
| |
- * are not ours, so don't free them! */
|
| |
- while (!PR_CLIST_IS_EMPTY(&exclusions)) {
|
| |
- dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&exclusions);
|
| |
- PR_REMOVE_LINK((PRCList *)dnitem);
|
| |
- slapi_ch_free((void **)&dnitem);
|
| |
- }
|
| |
-
|
| |
- while (!PR_CLIST_IS_EMPTY(&targets)) {
|
| |
- dnitem = (struct automemberDNListItem *)PR_LIST_HEAD(&targets);
|
| |
- PR_REMOVE_LINK((PRCList *)dnitem);
|
| |
- slapi_ch_free((void **)&dnitem);
|
| |
- }
|
| |
+ /* Free the exclusions and targets lists */
|
| |
+ automember_free_membership_lists(&exclusions, &targets);
|
| |
|
| |
out:
|
| |
|
| |
return rc;
|
| |
}
|
| |
|
| |
+
|
| |
/*
|
| |
- * automember_add_member_value()
|
| |
+ * automember_update_member_value()
|
| |
*
|
| |
* Adds a member entry to a group.
|
| |
*/
|
| |
static int
|
| |
- automember_add_member_value(Slapi_Entry *member_e, const char *group_dn, char *grouping_attr, char *grouping_value, PRFileDesc *ldif_fd)
|
| |
+ automember_update_member_value(Slapi_Entry *member_e, const char *group_dn, char *grouping_attr, char *grouping_value, PRFileDesc *ldif_fd, int add)
|
| |
{
|
| |
Slapi_PBlock *mod_pb = slapi_pblock_new();
|
| |
int result = LDAP_SUCCESS;
|
| |
@@ -1606,34 +1663,57 @@
|
| |
/* Set up the operation. */
|
| |
vals[0] = member_value;
|
| |
vals[1] = 0;
|
| |
- mod.mod_op = LDAP_MOD_ADD;
|
| |
+ if (add) {
|
| |
+ mod.mod_op = LDAP_MOD_ADD;
|
| |
+ } else {
|
| |
+ mod.mod_op = LDAP_MOD_DELETE;
|
| |
+ }
|
| |
mod.mod_type = grouping_attr;
|
| |
mod.mod_values = vals;
|
| |
mods[0] = &mod;
|
| |
mods[1] = 0;
|
| |
|
| |
/* Perform the modify operation. */
|
| |
- slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "automember_add_member_value - Adding \"%s\" as "
|
| |
- "a \"%s\" value to group \"%s\".\n",
|
| |
- member_value, grouping_attr, group_dn);
|
| |
+ if (add){
|
| |
+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_update_member_value - Adding \"%s\" as "
|
| |
+ "a \"%s\" value to group \"%s\".\n",
|
| |
+ member_value, grouping_attr, group_dn);
|
| |
+ } else {
|
| |
+ slapi_log_err(SLAPI_LOG_PLUGIN, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_update_member_value - Deleting \"%s\" as "
|
| |
+ "a \"%s\" value from group \"%s\".\n",
|
| |
+ member_value, grouping_attr, group_dn);
|
| |
+ }
|
| |
|
| |
slapi_modify_internal_set_pb(mod_pb, group_dn,
|
| |
mods, 0, 0, automember_get_plugin_id(), 0);
|
| |
slapi_modify_internal_pb(mod_pb);
|
| |
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
|
| |
|
| |
- if ((result != LDAP_SUCCESS) && (result != LDAP_TYPE_OR_VALUE_EXISTS)) {
|
| |
- slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "automember_add_member_value - Unable to add \"%s\" as "
|
| |
- "a \"%s\" value to group \"%s\" (%s).\n",
|
| |
- member_value, grouping_attr, group_dn,
|
| |
- ldap_err2string(result));
|
| |
- rc = result;
|
| |
+ if(add){
|
| |
+ if ((result != LDAP_SUCCESS) && (result != LDAP_TYPE_OR_VALUE_EXISTS)) {
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_update_member_value - Unable to add \"%s\" as "
|
| |
+ "a \"%s\" value to group \"%s\" (%s).\n",
|
| |
+ member_value, grouping_attr, group_dn,
|
| |
+ ldap_err2string(result));
|
| |
+ rc = result;
|
| |
+ }
|
| |
+ } else {
|
| |
+ /* delete value */
|
| |
+ if ((result != LDAP_SUCCESS) && (result != LDAP_NO_SUCH_ATTRIBUTE)) {
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_update_member_value - Unable to delete \"%s\" as "
|
| |
+ "a \"%s\" value from group \"%s\" (%s).\n",
|
| |
+ member_value, grouping_attr, group_dn,
|
| |
+ ldap_err2string(result));
|
| |
+ rc = result;
|
| |
+ }
|
| |
}
|
| |
} else {
|
| |
slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "automember_add_member_value - Unable to find grouping "
|
| |
+ "automember_update_member_value - Unable to find grouping "
|
| |
"value attribute \"%s\" in entry \"%s\".\n",
|
| |
grouping_value, slapi_entry_get_dn(member_e));
|
| |
}
|
| |
@@ -1780,22 +1860,144 @@
|
| |
static int
|
| |
automember_mod_post_op(Slapi_PBlock *pb)
|
| |
{
|
| |
+ Slapi_Entry *post_e = NULL;
|
| |
+ Slapi_Entry *pre_e = NULL;
|
| |
Slapi_DN *sdn = NULL;
|
| |
+ struct configEntry *config = NULL;
|
| |
+ PRCList *list = NULL;
|
| |
+ int rc = SLAPI_PLUGIN_SUCCESS;
|
| |
|
| |
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
"--> automember_mod_post_op\n");
|
| |
|
| |
if (automember_oktodo(pb) && (sdn = automember_get_sdn(pb))) {
|
| |
- /* Check if the config is being modified and reload if so. */
|
| |
if (automember_dn_is_config(sdn)) {
|
| |
+ /*
|
| |
+ * The config is being modified, reload it
|
| |
+ */
|
| |
automember_load_config();
|
| |
+ } else if ( !automember_isrepl(pb) && plugin_do_modify) {
|
| |
+ /*
|
| |
+ * We might be applying an update that will invoke automembership changes...
|
| |
+ */
|
| |
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &post_e);
|
| |
+ slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &pre_e);
|
| |
+
|
| |
+ if (post_e) {
|
| |
+ /*
|
| |
+ * Check if a config entry applies to the entry being modified
|
| |
+ */
|
| |
+ automember_config_read_lock();
|
| |
+
|
| |
+ if (!PR_CLIST_IS_EMPTY(g_automember_config)) {
|
| |
+ list = PR_LIST_HEAD(g_automember_config);
|
| |
+ while (list != g_automember_config) {
|
| |
+ config = (struct configEntry *)list;
|
| |
+
|
| |
+ /* Does the entry meet scope and filter requirements? */
|
| |
+ if (slapi_dn_issuffix(slapi_sdn_get_dn(sdn), config->scope) &&
|
| |
+ slapi_filter_test_simple(post_e, config->filter) == 0)
|
| |
+ {
|
| |
+ /* Find out what membership changes are needed and make them. */
|
| |
+ if ((rc = automember_update_membership(config, post_e, NULL)) == SLAPI_PLUGIN_FAILURE) {
|
| |
+ /* Failed to update our groups, break out */
|
| |
+ break;
|
| |
+ } else if (rc == MEMBERSHIP_UPDATED) {
|
| |
+ /*
|
| |
+ * We updated one of our groups, but we might need to do some cleanup in other groups
|
| |
+ */
|
| |
+ PRCList exclusions_post, targets_post;
|
| |
+ PRCList exclusions_pre, targets_pre;
|
| |
+ struct automemberDNListItem *dn_pre = NULL;
|
| |
+ struct automemberDNListItem *dn_post = NULL;
|
| |
+ int i;
|
| |
+
|
| |
+ /* reset rc */
|
| |
+ rc = SLAPI_PLUGIN_SUCCESS;
|
| |
+
|
| |
+ /* Get the group lists */
|
| |
+ automember_get_membership_lists(config, &exclusions_post, &targets_post, post_e);
|
| |
+ automember_get_membership_lists(config, &exclusions_pre, &targets_pre, pre_e);
|
| |
+
|
| |
+ /* Process the before and after lists */
|
| |
+ if (PR_CLIST_IS_EMPTY(&targets_pre) && !PR_CLIST_IS_EMPTY(&targets_post)) {
|
| |
+ /*
|
| |
+ * We were in the default groups, but not anymore
|
| |
+ */
|
| |
+ for (i = 0; config->default_groups && config->default_groups[i]; i++) {
|
| |
+ if (automember_update_member_value(post_e, config->default_groups[i], config->grouping_attr,
|
| |
+ config->grouping_value, NULL, DEL_MEMBER))
|
| |
+ {
|
| |
+ rc = SLAPI_PLUGIN_FAILURE;
|
| |
+ break;
|
| |
+ }
|
| |
+ }
|
| |
+ } else if (!PR_CLIST_IS_EMPTY(&targets_pre) && PR_CLIST_IS_EMPTY(&targets_post)) {
|
| |
+ /*
|
| |
+ * We were in non-default groups, but not anymore
|
| |
+ */
|
| |
+ dn_pre = (struct automemberDNListItem *)PR_LIST_HEAD(&targets_pre);
|
| |
+ while ((PRCList *)dn_pre != &targets_pre) {
|
| |
+ if (automember_update_member_value(post_e, slapi_sdn_get_dn(dn_pre->dn), config->grouping_attr,
|
| |
+ config->grouping_value, NULL, DEL_MEMBER))
|
| |
+ {
|
| |
+ rc = SLAPI_PLUGIN_FAILURE;
|
| |
+ break;
|
| |
+ }
|
| |
+ dn_pre = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dn_pre);
|
| |
+ }
|
| |
+ } else {
|
| |
+ /*
|
| |
+ * We were previously in non-default groups, and still in non-default groups.
|
| |
+ * Compare before and after memberships and cleanup the orphaned memberships
|
| |
+ */
|
| |
+ dn_pre = (struct automemberDNListItem *)PR_LIST_HEAD(&targets_pre);
|
| |
+ while ((PRCList *)dn_pre != &targets_pre) {
|
| |
+ int found = 0;
|
| |
+ dn_post = (struct automemberDNListItem *)PR_LIST_HEAD(&targets_post);
|
| |
+ while ((PRCList *)dn_post != &targets_post) {
|
| |
+ if (slapi_sdn_compare(dn_pre->dn, dn_post->dn) == 0) {
|
| |
+ /* found */
|
| |
+ found = 1;
|
| |
+ break;
|
| |
+ }
|
| |
+ /* Next dn */
|
| |
+ dn_post = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dn_post);
|
| |
+ }
|
| |
+ if (!found){
|
| |
+ /* Remove user from dn_pre->dn */
|
| |
+ if (automember_update_member_value(post_e, slapi_sdn_get_dn(dn_pre->dn), config->grouping_attr,
|
| |
+ config->grouping_value, NULL, DEL_MEMBER))
|
| |
+ {
|
| |
+ rc = SLAPI_PLUGIN_FAILURE;
|
| |
+ break;
|
| |
+ }
|
| |
+ }
|
| |
+ /* Next dn */
|
| |
+ dn_pre = (struct automemberDNListItem *)PR_NEXT_LINK((PRCList *)dn_pre);
|
| |
+ }
|
| |
+ }
|
| |
+
|
| |
+ /* All done with this config entry, free the lists */
|
| |
+ automember_free_membership_lists(&exclusions_post, &targets_post);
|
| |
+ automember_free_membership_lists(&exclusions_pre, &targets_pre);
|
| |
+ if (rc == SLAPI_PLUGIN_FAILURE) {
|
| |
+ break;
|
| |
+ }
|
| |
+ }
|
| |
+ }
|
| |
+ list = PR_NEXT_LINK(list);
|
| |
+ }
|
| |
+ }
|
| |
+ automember_config_unlock();
|
| |
+ }
|
| |
}
|
| |
}
|
| |
|
| |
slapi_log_err(SLAPI_LOG_TRACE, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
- "<-- automember_mod_post_op\n");
|
| |
+ "<-- automember_mod_post_op (%d)\n", rc);
|
| |
|
| |
- return SLAPI_PLUGIN_SUCCESS;
|
| |
+ return rc;
|
| |
}
|
| |
|
| |
static int
|
| |
@@ -1854,7 +2056,7 @@
|
| |
if (slapi_dn_issuffix(slapi_sdn_get_dn(sdn), config->scope) &&
|
| |
(slapi_filter_test_simple(e, config->filter) == 0)) {
|
| |
/* Find out what membership changes are needed and make them. */
|
| |
- if (automember_update_membership(config, e, NULL)) {
|
| |
+ if (automember_update_membership(config, e, NULL) == SLAPI_PLUGIN_FAILURE) {
|
| |
rc = SLAPI_PLUGIN_FAILURE;
|
| |
break;
|
| |
}
|
| |
@@ -2098,8 +2300,9 @@
|
| |
Slapi_Entry **entries = NULL;
|
| |
task_data *td = NULL;
|
| |
PRCList *list = NULL;
|
| |
+ PRCList *include_list = NULL;
|
| |
int result = 0;
|
| |
- int i = 0;
|
| |
+ size_t i = 0, ii = 0;
|
| |
|
| |
if (!task) {
|
| |
return; /* no task */
|
| |
@@ -2175,9 +2378,55 @@
|
| |
config = (struct configEntry *)list;
|
| |
/* Does the entry meet scope and filter requirements? */
|
| |
if (slapi_dn_issuffix(slapi_entry_get_dn(entries[i]), config->scope) &&
|
| |
- (slapi_filter_test_simple(entries[i], config->filter) == 0)) {
|
| |
+ (slapi_filter_test_simple(entries[i], config->filter) == 0))
|
| |
+ {
|
| |
+ /* First clear out all the defaults groups */
|
| |
+ for (ii = 0; config->default_groups && config->default_groups[ii]; ii++) {
|
| |
+ if ((result = automember_update_member_value(entries[i], config->default_groups[ii],
|
| |
+ config->grouping_attr, config->grouping_value, NULL, DEL_MEMBER)))
|
| |
+ {
|
| |
+ slapi_task_log_notice(task, "Automember rebuild membership task unable to delete "
|
| |
+ "member from default group (%s) error (%d)\n",
|
| |
+ config->default_groups[ii], result);
|
| |
+ slapi_task_log_status(task, "Automember rebuild membership task unable to delete "
|
| |
+ "member from default group (%s) error (%d)\n",
|
| |
+ config->default_groups[ii], result);
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n",
|
| |
+ config->default_groups[ii], result);
|
| |
+ automember_config_unlock();
|
| |
+ goto out;
|
| |
+ }
|
| |
+ }
|
| |
+
|
| |
+ /* Then clear out the non-default group */
|
| |
+ if (config->inclusive_rules && !PR_CLIST_IS_EMPTY((PRCList *)config->inclusive_rules)) {
|
| |
+ include_list = PR_LIST_HEAD((PRCList *)config->inclusive_rules);
|
| |
+ while (include_list != (PRCList *)config->inclusive_rules) {
|
| |
+ struct automemberRegexRule *curr_rule = (struct automemberRegexRule *)include_list;
|
| |
+ if ((result = automember_update_member_value(entries[i], slapi_sdn_get_dn(curr_rule->target_group_dn),
|
| |
+ config->grouping_attr, config->grouping_value, NULL, DEL_MEMBER)))
|
| |
+ {
|
| |
+ slapi_task_log_notice(task, "Automember rebuild membership task unable to delete "
|
| |
+ "member from group (%s) error (%d)\n",
|
| |
+ slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
| |
+ slapi_task_log_status(task, "Automember rebuild membership task unable to delete "
|
| |
+ "member from group (%s) error (%d)\n",
|
| |
+ slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
| |
+ slapi_log_err(SLAPI_LOG_ERR, AUTOMEMBER_PLUGIN_SUBSYSTEM,
|
| |
+ "automember_rebuild_task_thread - Unable to unable to delete from (%s) error (%d)\n",
|
| |
+ slapi_sdn_get_dn(curr_rule->target_group_dn), result);
|
| |
+ automember_config_unlock();
|
| |
+ goto out;
|
| |
+ }
|
| |
+ include_list = PR_NEXT_LINK(include_list);
|
| |
+ }
|
| |
+ }
|
| |
+
|
| |
+ /* Update the memberships for this entries */
|
| |
if (slapi_is_shutting_down() ||
|
| |
- automember_update_membership(config, entries[i], NULL)) {
|
| |
+ automember_update_membership(config, entries[i], NULL) == SLAPI_PLUGIN_FAILURE)
|
| |
+ {
|
| |
result = SLAPI_PLUGIN_FAILURE;
|
| |
automember_config_unlock();
|
| |
goto out;
|
| |
@@ -2390,7 +2639,7 @@
|
| |
if (slapi_dn_issuffix(slapi_sdn_get_dn(td->base_dn), config->scope) &&
|
| |
(slapi_filter_test_simple(entries[i], config->filter) == 0)) {
|
| |
if (slapi_is_shutting_down() ||
|
| |
- automember_update_membership(config, entries[i], ldif_fd)) {
|
| |
+ automember_update_membership(config, entries[i], ldif_fd) == SLAPI_PLUGIN_FAILURE) {
|
| |
result = SLAPI_DSE_CALLBACK_ERROR;
|
| |
automember_config_unlock();
|
| |
goto out;
|
| |
@@ -2594,7 +2843,7 @@
|
| |
if (slapi_dn_issuffix(slapi_entry_get_dn_const(e), config->scope) &&
|
| |
(slapi_filter_test_simple(e, config->filter) == 0)) {
|
| |
if (slapi_is_shutting_down() ||
|
| |
- automember_update_membership(config, e, ldif_fd_out)) {
|
| |
+ automember_update_membership(config, e, ldif_fd_out) == SLAPI_PLUGIN_FAILURE) {
|
| |
result = SLAPI_DSE_CALLBACK_ERROR;
|
| |
slapi_entry_free(e);
|
| |
slapi_ch_free_string(&entrystr);
|
| |
@@ -2702,7 +2951,7 @@
|
| |
if (slapi_dn_issuffix(slapi_sdn_get_dn(new_sdn), config->scope) &&
|
| |
(slapi_filter_test_simple(post_e, config->filter) == 0)) {
|
| |
/* Find out what membership changes are needed and make them. */
|
| |
- if (automember_update_membership(config, post_e, NULL)) {
|
| |
+ if (automember_update_membership(config, post_e, NULL) == SLAPI_PLUGIN_FAILURE) {
|
| |
rc = SLAPI_PLUGIN_FAILURE;
|
| |
break;
|
| |
}
|
| |
modrdn case is already defined I guess? What about if deleting an attribute would now cause the entry to be part of the group?