|
|
dc8c34 |
From 8436befeeb9f1d62cf1a48329e9933387d89e394 Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Noriko Hosoi <nhosoi@redhat.com>
|
|
|
dc8c34 |
Date: Thu, 20 Feb 2014 14:29:16 -0800
|
|
|
dc8c34 |
Subject: [PATCH 165/225] Ticket #47642 - Windows Sync group issues
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug Description: When an entry is moved on AD, and the entry is
|
|
|
dc8c34 |
a member of a group, the value of the member in the group is
|
|
|
dc8c34 |
automatically updated. But Windows Sync Control request only
|
|
|
dc8c34 |
returns the renamed entry; it does not return the group having
|
|
|
dc8c34 |
the member in it even though the value is updated. This is
|
|
|
dc8c34 |
because an AD group stores DNT (Distinguish Name Tag -- ID in
|
|
|
dc8c34 |
integer) instead of the dn itself. Since the rename operation
|
|
|
dc8c34 |
does not change DNT, the group entry on AD has no change, either.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
On the DS side, the group entry stores the full DN which needs
|
|
|
dc8c34 |
to be adjusted to the renamed DN to complete the synchronization
|
|
|
dc8c34 |
with AD.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Fix Description: Once rename operation is received from AD,
|
|
|
dc8c34 |
windows_update_local_entry searches groups having a member value
|
|
|
dc8c34 |
matches the pre-renamed dn on DS, and replaces the old dn with the
|
|
|
dc8c34 |
renamed one.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Thanks to tbordaz@redhat.com for pointing out the possibility of
|
|
|
dc8c34 |
NULL dereference. The problem is fixed, as well.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Thanks to rmeggins@redhat.com for suggesting to escape the search
|
|
|
dc8c34 |
filter value. It was added.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47642
|
|
|
dc8c34 |
(cherry picked from commit 98ddd817e26f236adebd80270ec71d7ec372c20e)
|
|
|
dc8c34 |
(cherry picked from commit 86515d1b18a96b9d7e6143f870b343030a7af5a7)
|
|
|
dc8c34 |
(cherry picked from commit ab4893cb851533d89e1b02c91972255a48776ce4)
|
|
|
dc8c34 |
(cherry picked from commit 5324aeca04c8fd0dd3787565815e92bfad1eb3d4)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
.../plugins/replication/windows_protocol_util.c | 117 +++++++++++++++++++--
|
|
|
dc8c34 |
1 file changed, 111 insertions(+), 6 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
|
|
|
dc8c34 |
index 93246ec..bac6573 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
|
|
|
dc8c34 |
@@ -3871,6 +3871,7 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
|
|
|
dc8c34 |
} else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* Error, no username */
|
|
|
dc8c34 |
+ retval = ENTRY_NOTFOUND;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (new_dn)
|
|
|
dc8c34 |
@@ -4689,7 +4690,7 @@ windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- Slapi_Mods smods = {0};
|
|
|
dc8c34 |
+ Slapi_Mods smods;
|
|
|
dc8c34 |
int retval = 0;
|
|
|
dc8c34 |
Slapi_PBlock *pb = NULL;
|
|
|
dc8c34 |
int do_modify = 0;
|
|
|
dc8c34 |
@@ -4701,14 +4702,24 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
|
|
|
dc8c34 |
Slapi_DN *mapped_sdn = NULL;
|
|
|
dc8c34 |
Slapi_RDN rdn = {0};
|
|
|
dc8c34 |
Slapi_Entry *orig_local_entry = NULL;
|
|
|
dc8c34 |
+ const Slapi_DN *orig_local_sdn = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* Variables for updating local groups */
|
|
|
dc8c34 |
+ Slapi_Entry **entries = NULL;
|
|
|
dc8c34 |
+ char *filter_string = NULL;
|
|
|
dc8c34 |
+ const Slapi_DN *local_subtree = NULL;
|
|
|
dc8c34 |
+ const Slapi_DN *local_subtree_sdn = NULL;
|
|
|
dc8c34 |
+ char *attrs[3];
|
|
|
dc8c34 |
+ /* Variables for updating local groups */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ slapi_mods_init(&smods, 0);
|
|
|
dc8c34 |
windows_is_local_entry_user_or_group(local_entry, &is_user, &is_group);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Get the mapped DN. We don't want to locate the existing entry by
|
|
|
dc8c34 |
* guid or username. We want to get the mapped DN just as we would
|
|
|
dc8c34 |
* if we were creating a new entry. */
|
|
|
dc8c34 |
retval = map_entry_dn_inbound_ext(remote_entry, &mapped_sdn, prp->agmt, 0 /* use_guid */, 0 /* use_username */);
|
|
|
dc8c34 |
- if (retval != 0) {
|
|
|
dc8c34 |
+ if (retval || (NULL == mapped_sdn)) {
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
|
|
|
dc8c34 |
"unable to map remote entry to local DN\n");
|
|
|
dc8c34 |
return retval;
|
|
|
dc8c34 |
@@ -4730,8 +4741,10 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
|
|
|
dc8c34 |
&newsuperior, 0 /* to_windows */);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (newsuperior || newrdn) {
|
|
|
dc8c34 |
+ char *escaped_filter_val;
|
|
|
dc8c34 |
+ const char *ptr;
|
|
|
dc8c34 |
/* remote parent is different from the local parent */
|
|
|
dc8c34 |
- Slapi_PBlock *pb = slapi_pblock_new ();
|
|
|
dc8c34 |
+ pb = slapi_pblock_new ();
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (NULL == newrdn) {
|
|
|
dc8c34 |
newdn = slapi_entry_get_dn_const(local_entry);
|
|
|
dc8c34 |
@@ -4778,10 +4791,102 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
|
|
|
dc8c34 |
orig_local_entry = NULL;
|
|
|
dc8c34 |
goto bail;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- slapi_mods_init (&smods, 0);
|
|
|
dc8c34 |
+ /* WinSync control req does not return the member updates
|
|
|
dc8c34 |
+ * in the groups caused by moving member entries.
|
|
|
dc8c34 |
+ * We need to update the local groups manually... */
|
|
|
dc8c34 |
+ local_subtree = agmt_get_replarea(prp->agmt);
|
|
|
dc8c34 |
+ local_subtree_sdn = local_subtree;
|
|
|
dc8c34 |
+ orig_local_sdn = slapi_entry_get_sdn_const(orig_local_entry);
|
|
|
dc8c34 |
+ escaped_filter_val = slapi_ch_malloc(slapi_sdn_get_ndn_len(orig_local_sdn) * 3 + 1);
|
|
|
dc8c34 |
+ ptr = escape_filter_value((char *)slapi_sdn_get_ndn(orig_local_sdn),
|
|
|
dc8c34 |
+ slapi_sdn_get_ndn_len(orig_local_sdn), escaped_filter_val);
|
|
|
dc8c34 |
+ /* Search entries which have pre-renamed members */
|
|
|
dc8c34 |
+ filter_string = PR_smprintf("(&(objectclass=ntGroup)(|(member=%s)(uniquemember=%s)))",
|
|
|
dc8c34 |
+ ptr, ptr);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&escaped_filter_val);
|
|
|
dc8c34 |
+ attrs[0] = "member";
|
|
|
dc8c34 |
+ attrs[1] = "uniquemember";
|
|
|
dc8c34 |
+ attrs[2] = NULL;
|
|
|
dc8c34 |
+ pb = slapi_pblock_new ();
|
|
|
dc8c34 |
+ slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(local_subtree_sdn),
|
|
|
dc8c34 |
+ LDAP_SCOPE_SUBTREE, filter_string, attrs, 0, NULL, NULL,
|
|
|
dc8c34 |
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
|
|
|
dc8c34 |
+ slapi_search_internal_pb(pb);
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
|
|
|
dc8c34 |
+ if (LDAP_SUCCESS == retval) {
|
|
|
dc8c34 |
+ Slapi_Entry **ep;
|
|
|
dc8c34 |
+ const char *prev_member = slapi_sdn_get_ndn(orig_local_sdn);
|
|
|
dc8c34 |
+ const char *new_member = slapi_sdn_get_ndn(mapped_sdn);
|
|
|
dc8c34 |
+ size_t prev_member_len = slapi_sdn_get_ndn_len(orig_local_sdn);
|
|
|
dc8c34 |
+ size_t new_member_len = strlen(new_member);
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
|
dc8c34 |
+ for (ep = entries; ep && *ep; ep++) {
|
|
|
dc8c34 |
+ /* there are group entries whose member matches the renamed entry. */
|
|
|
dc8c34 |
+ Slapi_PBlock *mod_pb = NULL;
|
|
|
dc8c34 |
+ Slapi_Attr *mattr = NULL;
|
|
|
dc8c34 |
+ Slapi_Attr *umattr = NULL;
|
|
|
dc8c34 |
+ char *type = NULL;
|
|
|
dc8c34 |
+ slapi_entry_attr_find(*ep, "member", &mattr);
|
|
|
dc8c34 |
+ slapi_entry_attr_find(*ep, "uniquemember", &umattr);
|
|
|
dc8c34 |
+ if (mattr) {
|
|
|
dc8c34 |
+ if (umattr) {
|
|
|
dc8c34 |
+ /* This entry has both member and uniquemember ... */
|
|
|
dc8c34 |
+ Slapi_Value *v = NULL;
|
|
|
dc8c34 |
+ int i = 0;
|
|
|
dc8c34 |
+ for (i = slapi_attr_first_value(mattr, &v);
|
|
|
dc8c34 |
+ v && (i != -1);
|
|
|
dc8c34 |
+ i = slapi_attr_next_value(mattr, i, &v)) {
|
|
|
dc8c34 |
+ const char *s = slapi_value_get_string(v);
|
|
|
dc8c34 |
+ if (NULL == s) {
|
|
|
dc8c34 |
+ continue;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (0 == strcasecmp(s, prev_member)) {
|
|
|
dc8c34 |
+ type = "member";
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (!type) {
|
|
|
dc8c34 |
+ type = "uniquemember";
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ type = "member";
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ if (umattr) {
|
|
|
dc8c34 |
+ type = "uniquemember";
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (type) {
|
|
|
dc8c34 |
+ mod_pb = slapi_pblock_new();
|
|
|
dc8c34 |
+ slapi_mods_add(&smods, LDAP_MOD_DELETE, type, prev_member_len, prev_member);
|
|
|
dc8c34 |
+ slapi_mods_add(&smods, LDAP_MOD_ADD, type, new_member_len, new_member);
|
|
|
dc8c34 |
+ slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(*ep),
|
|
|
dc8c34 |
+ slapi_mods_get_ldapmods_byref(&smods), NULL, NULL,
|
|
|
dc8c34 |
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
|
|
|
dc8c34 |
+ 0);
|
|
|
dc8c34 |
+ slapi_modify_internal_pb(mod_pb);
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
|
|
|
dc8c34 |
+ "windows_update_local_entry: "
|
|
|
dc8c34 |
+ "failed to modify entry %s replacing %s with %s "
|
|
|
dc8c34 |
+ "- error %d:%s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(*ep), prev_member, new_member,
|
|
|
dc8c34 |
+ retval, ldap_err2string(retval));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_pblock_destroy(mod_pb);
|
|
|
dc8c34 |
+ slapi_mods_done(&smods);
|
|
|
dc8c34 |
+ } /* if (type) */
|
|
|
dc8c34 |
+ } /* for (ep = entries; ep && *ep; ep++) */
|
|
|
dc8c34 |
+ } /* if (LDAP_SUCCESS == retval) - searching with "(|(member=..)(uniquemember=..)) */
|
|
|
dc8c34 |
+ slapi_free_search_results_internal(pb);
|
|
|
dc8c34 |
+ slapi_pblock_destroy(pb);
|
|
|
dc8c34 |
+ if (filter_string) {
|
|
|
dc8c34 |
+ PR_smprintf_free(filter_string);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_sdn_free((Slapi_DN **)&local_subtree);
|
|
|
dc8c34 |
+ } /* if (newsuperior || newrdn) */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
retval = windows_generate_update_mods(prp,remote_entry,local_entry,0,&smods,&do_modify);
|
|
|
dc8c34 |
/* Now perform the modify if we need to */
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.8.1.4
|
|
|
dc8c34 |
|