From 5b11003aa7fb39029c9cc63a08aaaf2de28148f5 Mon Sep 17 00:00:00 2001 From: William Brown Date: Tue, 14 Dec 2021 13:19:08 +1000 Subject: [PATCH] Issue 5052 - BUG - Custom filters prevented entry deletion Bug Description: When a custom filter was provided, entries which were deleted in AD did not have that event correctly reflected in 389-ds. This was due to the behaviour that when an entry in AD is deleted, it is marked with a "deleted" flag which the objectClass=* filter would (accidentally) collect when it did a search. However, a custom user filter being specified would in some cases (such as a memberOf filter) NOT show up the deletion since the entry was considered to have moved out of scope rather than being a full delete. Fix Description: In the case that we have a userfilter, we wrap it in an OR condition that always requests isDeleted flags so that we can correctly reflect the delete status. fixes: https://github.com/389ds/389-ds-base/issues/5052 Author: William Brown Review by: ??? --- ldap/servers/plugins/replication/repl5_agmt.c | 2 ++ .../plugins/replication/windows_connection.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c index fe62f3faa1..c9caf94e9f 100644 --- a/ldap/servers/plugins/replication/repl5_agmt.c +++ b/ldap/servers/plugins/replication/repl5_agmt.c @@ -486,6 +486,8 @@ agmt_new_from_entry(Slapi_Entry *e) ra->agreement_type = REPLICA_TYPE_WINDOWS; windows_init_agreement_from_entry(ra, e); } else { + slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, + "agmt_new_from_entry: type -> %d\n", replica_get_type(replica)); slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "agmt_new_from_entry: failed to initialise windows replication" "agreement \"%s\" - replica is not a supplier (may be hub or consumer).\n", diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c index 5eca5fad1c..e4642ca5bf 100644 --- a/ldap/servers/plugins/replication/windows_connection.c +++ b/ldap/servers/plugins/replication/windows_connection.c @@ -776,14 +776,26 @@ send_dirsync_search(Repl_Connection *conn) slapi_log_err(SLAPI_LOG_REPL, windows_repl_plugin_name, "send_dirsync_search - Calling dirsync search request plugin\n"); userfilter = windows_private_get_windows_userfilter(conn->agmt); if (userfilter) { - filter = slapi_ch_strdup(userfilter); + /* + * When we have a userfilter, we encounter an issue where a previously + * matching object that is *deleted* that we had synced, was not being + * deleted. This is because in the unfiltered case, we relied on the + * objectClass=* to get everything, but when we apply a filter we are + * removing items that were deleted, especially if they were members of + * a group. As a result, we need to *always* request the isDeleted flag + * so that we can correct delete any remnants on our side. + */ + size_t buflen = 18 + strlen(userfilter); + filter = slapi_ch_calloc(1, buflen); + snprintf(filter, buflen, "(|(isDeleted=*)%s)", userfilter); } else { filter = slapi_ch_strdup("(objectclass=*)"); } winsync_plugin_call_dirsync_search_params_cb(conn->agmt, old_dn, &dn, &scope, &filter, &attrs, &server_controls); - slapi_log_err(SLAPI_LOG_REPL, windows_repl_plugin_name, "send_dirsync_search - Sending dirsync search request\n"); + slapi_log_err(SLAPI_LOG_REPL, windows_repl_plugin_name, "send_dirsync_search - Sending dirsync search request %s %d %s\n", + dn, scope, filter); rc = ldap_search_ext(conn->ld, dn, scope, filter, attrs, PR_FALSE, server_controls, NULL /* ClientControls */, 0, 0, &msgid);