ldap/servers/plugins/mep/mep.c | 40 +++++++++++++++++++++++++-------
ldap/servers/slapd/plugin_internal_op.c | 17 +++++++++----
2 files changed, 44 insertions(+), 13 deletions(-)
New commits:
commit 379c164d5321549a249dc0a2f2ed7d79989801a0
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Sep 6 11:08:40 2011 -0700
Bug 735114 - renaming a managed entry does not update mepmanagedby
When a number of different plug-ins are being used that perform
internal operations to update entries, it is possible for the
managed entry plug-in to fail to update the managed entry. In
particular, it has been found that renaming an origin entry can
trigger a plug-in other than the managed entry plug-in to rename
the managed entry. This causes the managed entry plug-in to fail
when it attempts to update the managed entry.
This patch makes the managed entry plug-in check if the managed
entry has already been renamed when processing a MODRDN operation.
If it detects that the managed entry has already been renamed, it
will use the new DN to perform the managed entry updates.
diff --git a/ldap/servers/plugins/mep/mep.c b/ldap/servers/plugins/mep/mep.c
index 5e3aa17..0241cd3 100644
--- a/ldap/servers/plugins/mep/mep.c
+++ b/ldap/servers/plugins/mep/mep.c
@@ -2378,6 +2378,7 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
Slapi_Entry *new_managed_entry = NULL;
Slapi_DN *managed_sdn = NULL;
Slapi_Mods *smods = NULL;
+ int free_managed_dn = 1;
mep_config_read_lock();
@@ -2450,6 +2451,31 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
mods[0] = &mod;
mods[1] = 0;
+ /* Create a new managed entry to determine what changes
+ * we need to make to the existing managed entry. */
+ new_managed_entry = mep_create_managed_entry(config, post_e);
+ if (new_managed_entry == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+ "mep_modrdn_post_op: Unable to create in-memory "
+ "managed entry from origin entry \"%s\".\n", new_dn);
+ goto bailmod;
+ }
+
+ /* Check if the managed entry exists. It is possible that
+ * it has already been renamed by another plug-in. If it
+ * has already been renamed, we need to use the new DN to
+ * perform our updates. */
+ managed_sdn = slapi_sdn_new_dn_byref(managed_dn);
+
+ if (slapi_search_internal_get_entry(managed_sdn, 0,
+ NULL, mep_get_plugin_id()) == LDAP_NO_SUCH_OBJECT) {
+ slapi_ch_free_string(&managed_dn);
+ /* This DN is not a copy, so we don't want to free it later. */
+ managed_dn = slapi_entry_get_dn(new_managed_entry);
+ slapi_sdn_set_dn_byref(managed_sdn, managed_dn);
+ free_managed_dn = 0;
+ }
+
/* Perform the modify operation. */
slapi_log_error(SLAPI_LOG_PLUGIN, MEP_PLUGIN_SUBSYSTEM,
"mep_modrdn_post_op: Updating %s pointer to \"%s\" "
@@ -2465,12 +2491,7 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
"origin entry \"%s\" in managed entry \"%s\" "
"(%s).\n", new_dn, managed_dn, ldap_err2string(result));
} else {
- /* Create a new managed entry to determine what changes
- * we need to make to the existing managed entry. */
- new_managed_entry = mep_create_managed_entry(config, post_e);
-
/* 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) {
/* Rename the managed entry. */
slapi_log_error(SLAPI_LOG_PLUGIN, MEP_PLUGIN_SUBSYSTEM,
@@ -2510,14 +2531,17 @@ mep_modrdn_post_op(Slapi_PBlock *pb)
slapi_mods_free(&smods);
}
- slapi_sdn_free(&managed_sdn);
- slapi_entry_free(new_managed_entry);
}
+bailmod:
+ slapi_entry_free(new_managed_entry);
+ slapi_sdn_free(&managed_sdn);
}
slapi_pblock_destroy(mep_pb);
- slapi_ch_free_string(&managed_dn);
+ if (free_managed_dn) {
+ slapi_ch_free_string(&managed_dn);
+ }
mep_config_unlock();
} else {
diff --git a/ldap/servers/slapd/plugin_internal_op.c b/ldap/servers/slapd/plugin_internal_op.c
index 76f70e8..75d4e4a 100644
--- a/ldap/servers/slapd/plugin_internal_op.c
+++ b/ldap/servers/slapd/plugin_internal_op.c
@@ -872,7 +872,8 @@ void set_common_params (Slapi_PBlock *pb)
/*
* Given a DN, find an entry by doing an internal search. An LDAP error
- * code is returned.
+ * code is returned. To check if an entry exists without returning a
+ * copy of the entry, NULL can be passed for ret_entry.
*/
int
slapi_search_internal_get_entry( Slapi_DN *dn, char ** attrs, Slapi_Entry **ret_entry , void * component_identity)
@@ -881,7 +882,10 @@ slapi_search_internal_get_entry( Slapi_DN *dn, char ** attrs, Slapi_Entry **ret_
Slapi_PBlock *int_search_pb = NULL;
int rc = 0;
- *ret_entry = NULL;
+ if (ret_entry) {
+ *ret_entry = NULL;
+ }
+
int_search_pb = slapi_pblock_new ();
slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(dn), LDAP_SCOPE_BASE, "(|(objectclass=*)(objectclass=ldapsubentry))",
attrs ,
@@ -893,9 +897,12 @@ slapi_search_internal_get_entry( Slapi_DN *dn, char ** attrs, Slapi_Entry **ret_
if ( LDAP_SUCCESS == rc ) {
slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
if ( NULL != entries && NULL != entries[ 0 ]) {
- Slapi_Entry *temp_entry = NULL;
- temp_entry = entries[ 0 ];
- *ret_entry = slapi_entry_dup(temp_entry);
+ /* Only need to dup the entry if the caller passed ret_entry in. */
+ if (ret_entry) {
+ Slapi_Entry *temp_entry = NULL;
+ temp_entry = entries[ 0 ];
+ *ret_entry = slapi_entry_dup(temp_entry);
+ }
} else {
/* No entry there */
rc = LDAP_NO_SUCH_OBJECT;