ldap/servers/plugins/mep/mep.c | 176 +++++++++++++++++++++++++++--------------
1 file changed, 117 insertions(+), 59 deletions(-)
New commits:
commit 2e35351caf93e7338cd82b1c3eba46fc019f7121
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Fri Jan 7 10:19:59 2011 -0800
Bug 661102 - Rename of managed entries not handled correctly
When usign the managed entry plug-in, a modify operation against
an origin entry that should trigger a rename of a managed entry
does not trigger the rename. In addition, an error message is
logged since we try to do a modify of the RDN attribute of the
managed entry.
This patch makes the modify callback check if the changes require
a rename of the managed entry when an origin entry is updated. If
a rename is needed, we perform a MODRDN. We also need to skip the
RDN attribute when generating the mapped modifications that we use
to update a managed entry.
diff --git a/ldap/servers/plugins/mep/mep.c b/ldap/servers/plugins/mep/mep.c
index 63c2dd8..211a4cf 100644
--- a/ldap/servers/plugins/mep/mep.c
+++ b/ldap/servers/plugins/mep/mep.c
@@ -105,8 +105,10 @@ static Slapi_Entry *mep_create_managed_entry(struct configEntry
*config,
Slapi_Entry *origin);
static void mep_add_managed_entry(struct configEntry *config,
Slapi_Entry *origin);
+static void mep_rename_managed_entry(Slapi_Entry *origin,
+ char *new_dn, char *old_dn);
static Slapi_Mods *mep_get_mapped_mods(struct configEntry *config,
- Slapi_Entry *origin);
+ Slapi_Entry *origin, char **mapped_dn);
static int mep_parse_mapped_attr(char *mapping, Slapi_Entry *origin,
char **type, char **value);
static int mep_is_managed_entry(Slapi_Entry *e);
@@ -1193,6 +1195,77 @@ mep_add_managed_entry(struct configEntry *config,
slapi_pblock_destroy(mod_pb);
}
+/* mep_rename_managed_entry()
+ *
+ * Renames a managed entry and updates the pointer in the
+ * origin entry.
+ */
+static void mep_rename_managed_entry(Slapi_Entry *origin,
+ char *new_dn, char *old_dn)
+{
+ Slapi_RDN *srdn = slapi_rdn_new();
+ Slapi_PBlock *mep_pb = slapi_pblock_new();
+ LDAPMod mod;
+ LDAPMod *mods[2];
+ char *vals[2];
+ int result = LDAP_SUCCESS;
+
+ /* Just bail if any of our parameters are NULL. */
+ if (origin == NULL || new_dn == NULL || old_dn == NULL) {
+ goto bail;
+ }
+
+ /* Create new RDN */
+ slapi_rdn_set_dn(srdn, new_dn);
+
+ /* Rename the managed entry. */
+ slapi_rename_internal_set_pb(mep_pb, old_dn,
+ slapi_rdn_get_rdn(srdn),
+ NULL, 1, NULL, NULL, mep_get_plugin_id(), 0);
+ slapi_modrdn_internal_pb(mep_pb);
+ slapi_pblock_get(mep_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+
+ if (result != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+ "mep_rename_managed_entry: Unable to rename managed "
+ "entry \"%s\" to \"%s\" (%s).\n",
old_dn,
+ new_dn, ldap_err2string(result));
+ } else {
+ /* Clear out the pblock for reuse. */
+ slapi_pblock_init(mep_pb);
+
+ /* Update the link to the managed entry in the origin entry. */
+ vals[0] = new_dn;
+ vals[1] = 0;
+ mod.mod_op = LDAP_MOD_REPLACE;
+ mod.mod_type = MEP_MANAGED_ENTRY_TYPE;
+ mod.mod_values = vals;
+ mods[0] = &mod;
+ mods[1] = 0;
+
+ /* Perform the modify operation. */
+ slapi_log_error(SLAPI_LOG_PLUGIN, MEP_PLUGIN_SUBSYSTEM,
+ "mep_rename_managed_entry: Updating %s pointer to "
+ "\"%s\" in entry \"%s\"\n.",
MEP_MANAGED_ENTRY_TYPE,
+ vals[0], slapi_entry_get_dn(origin));
+ slapi_modify_internal_set_pb(mep_pb, slapi_entry_get_dn(origin), mods,
+ 0, 0, mep_get_plugin_id(), 0);
+ slapi_modify_internal_pb(mep_pb);
+ slapi_pblock_get(mep_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
+
+ if (result != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+ "mep_rename_managed_entry: Unable to update %s "
+ "pointer in entry \"%s\" (%s).\n",
MEP_MANAGED_ENTRY_TYPE,
+ slapi_entry_get_dn(origin), ldap_err2string(result));
+ }
+ }
+
+bail:
+ slapi_rdn_free(&srdn);
+ slapi_pblock_destroy(mep_pb);
+}
+
/*
* mep_get_mapped_mods()
*
@@ -1201,7 +1274,7 @@ mep_add_managed_entry(struct configEntry *config,
* returned mods when it is finished using them.
*/
static Slapi_Mods *mep_get_mapped_mods(struct configEntry *config,
- Slapi_Entry *origin)
+ Slapi_Entry *origin, char **mapped_dn)
{
Slapi_Mods *smods = NULL;
Slapi_Entry *template = NULL;
@@ -1209,6 +1282,7 @@ static Slapi_Mods *mep_get_mapped_mods(struct configEntry *config,
char **vals = NULL;
char *type = NULL;
char *value = NULL;
+ char *rdn_type = NULL;
int i = 0;
/* If no template was supplied, there's nothing we can do. */
@@ -1227,12 +1301,31 @@ static Slapi_Mods *mep_get_mapped_mods(struct configEntry
*config,
slapi_mods_init(smods, numvals);
}
+ /* Find the the RDN type for the managed entry. */
+ if ((rdn_type = slapi_entry_attr_get_charptr(template, MEP_RDN_ATTR_TYPE)) == NULL)
{
+ slapi_log_error( SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+ "mep_get_mapped_mods: Error getting RDN type from tempate "
+ "\"%s\".\n", config->template_dn);
+ slapi_mods_free(&smods);
+ goto bail;
+ }
+
/* Go through the template and find the mapped attrs. */
vals = slapi_entry_attr_get_charray(template, MEP_MAPPED_ATTR_TYPE);
for (i = 0; vals && vals[i]; ++i) {
if (mep_parse_mapped_attr(vals[i], origin, &type, &value) == 0) {
- /* Add a modify that replaces all values with the new value. */
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, type, value);
+ /* Don't attempt to modify the RDN type, but create
+ * the mapped DN if requested. It is up to the caller
+ * to free the returned DN. */
+ if (slapi_attr_type_cmp(type, rdn_type, SLAPI_TYPE_CMP_EXACT) == 0) {
+ if (mapped_dn) {
+ *mapped_dn = slapi_create_dn_string("%s=%s,%s", rdn_type,
+ value, config->managed_base);
+ }
+ } else {
+ /* Add a modify that replaces all values with the new value. */
+ slapi_mods_add_string(smods, LDAP_MOD_REPLACE, type, value);
+ }
slapi_ch_free_string(&type);
slapi_ch_free_string(&value);
} else {
@@ -1245,6 +1338,7 @@ static Slapi_Mods *mep_get_mapped_mods(struct configEntry *config,
}
bail:
+ slapi_ch_free_string(&rdn_type);
slapi_ch_array_free(vals);
return smods;
@@ -1881,6 +1975,9 @@ mep_mod_post_op(Slapi_PBlock *pb)
Slapi_Entry *e = NULL;
char *dn = NULL;
char *managed_dn = NULL;
+ Slapi_DN *managed_sdn = NULL;
+ char *mapped_dn = NULL;
+ Slapi_DN *mapped_sdn = NULL;
struct configEntry *config = NULL;
int result = 0;
@@ -1918,7 +2015,7 @@ mep_mod_post_op(Slapi_PBlock *pb)
mep_config_read_lock();
mep_find_config(e, &config);
if (config) {
- smods = mep_get_mapped_mods(config, e);
+ smods = mep_get_mapped_mods(config, e, &mapped_dn);
if (smods) {
/* Clear out the pblock for reuse. */
mep_pb = slapi_pblock_new();
@@ -1944,6 +2041,19 @@ mep_mod_post_op(Slapi_PBlock *pb)
slapi_mods_free(&smods);
slapi_pblock_destroy(mep_pb);
}
+
+ /* Check if we need to rename the managed entry. */
+ if (mapped_dn) {
+ mapped_sdn = slapi_sdn_new_dn_passin(mapped_dn);
+ managed_sdn = slapi_sdn_new_dn_byref(managed_dn);
+
+ if (slapi_sdn_compare(managed_sdn, mapped_sdn) != 0) {
+ mep_rename_managed_entry(e, mapped_dn, managed_dn);
+ }
+
+ slapi_sdn_free(&mapped_sdn);
+ slapi_sdn_free(&managed_sdn);
+ }
} else {
slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
"mep_mod_post_op: Unable to find config for origin "
@@ -2223,70 +2333,18 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
/* See if we need to rename the managed entry. */
managed_sdn = slapi_sdn_new_dn_byref(managed_dn);
if (slapi_sdn_compare(slapi_entry_get_sdn(new_managed_entry),
managed_sdn) != 0) {
- Slapi_RDN *srdn = slapi_rdn_new();
-
- /* Clear out the pblock for reuse. */
- slapi_pblock_init(mep_pb);
-
- /* Create new RDN */
- slapi_rdn_set_dn(srdn, slapi_entry_get_dn(new_managed_entry));
-
/* Rename the managed entry. */
slapi_log_error(SLAPI_LOG_PLUGIN, MEP_PLUGIN_SUBSYSTEM,
"mep_modrdn_post_op: Renaming managed entry
"
"\"%s\" to \"%s\" due to
rename of origin "
"entry \"%s\".\n ", managed_dn,
slapi_entry_get_dn(new_managed_entry), old_dn);
- slapi_rename_internal_set_pb(mep_pb, managed_dn,
- slapi_rdn_get_rdn(srdn),
- NULL, 1, NULL, NULL,
mep_get_plugin_id(), 0);
- slapi_modrdn_internal_pb(mep_pb);
- slapi_pblock_get(mep_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
-
- if (result != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
- "mep_modrdn_post_op: Unable to rename managed
"
- "entry \"%s\" to \"%s\"
(%s).\n", managed_dn,
- slapi_entry_get_dn(new_managed_entry),
- ldap_err2string(result));
- } else {
- /* Clear out the pblock for reuse. */
- slapi_pblock_init(mep_pb);
-
- /* Update the link to the managed entry in the origin
- * entry. We can just reuse the mod structure. */
- vals[0] = slapi_entry_get_dn(new_managed_entry);
- mod.mod_op = LDAP_MOD_REPLACE;
- mod.mod_type = MEP_MANAGED_ENTRY_TYPE;
- mod.mod_values = vals;
-
- /* Perform the modify operation. */
- slapi_log_error(SLAPI_LOG_PLUGIN, MEP_PLUGIN_SUBSYSTEM,
- "mep_modrdn_post_op: Updating %s pointer to "
- "\"%s\" in entry
\"%s\"\n.", MEP_MANAGED_ENTRY_TYPE,
- vals[0], new_dn);
- slapi_modify_internal_set_pb(mep_pb, new_dn, mods, 0, 0,
- mep_get_plugin_id(), 0);
- slapi_modify_internal_pb(mep_pb);
- slapi_pblock_get(mep_pb, SLAPI_PLUGIN_INTOP_RESULT,
&result);
-
- if (result != LDAP_SUCCESS) {
- slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
- "mep_modrdn_post_op: Unable to rename managed
"
- "entry \"%s\" to \"%s\"
(%s).\n", managed_dn,
- slapi_entry_get_dn(new_managed_entry),
- ldap_err2string(result));
- slapi_rdn_free(&srdn);
- goto bail;
- }
- }
-
- slapi_rdn_free(&srdn);
+ mep_rename_managed_entry(post_e,
slapi_entry_get_dn(new_managed_entry), managed_dn);
}
/* Update all of the mapped attributes
* to be sure they are up to date. */
- smods = mep_get_mapped_mods(config, post_e);
+ smods = mep_get_mapped_mods(config, post_e, NULL);
if (smods) {
/* Clear out the pblock for reuse. */
slapi_pblock_init(mep_pb);