ldap/schema/02common.ldif | 5
ldap/servers/plugins/replication/repl5.h | 3
ldap/servers/plugins/replication/repl_globals.c | 3
ldap/servers/plugins/replication/windows_connection.c | 19
ldap/servers/plugins/replication/windows_private.c | 581 ++++++++++++---
ldap/servers/plugins/replication/windows_protocol_util.c | 552 ++++++++++----
ldap/servers/plugins/replication/windows_tot_protocol.c | 125 ++-
ldap/servers/plugins/replication/windowsrepl.h | 18
ldap/servers/slapd/dn.c | 93 ++
ldap/servers/slapd/slapi-plugin.h | 45 +
ldap/servers/slapd/util.c | 2
11 files changed, 1163 insertions(+), 283 deletions(-)
New commits:
commit c410b87b2b345711faed0a5767d97827bfc417c1
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Wed Sep 18 14:05:40 2013 -0700
Ticket #460 - support multiple subtrees and filters
Description:
1. Support multiple subtrees
new config parameter in windwows sync agreement:
winSyncSubtreePair: <DS Subtree>:<AD Subtree>
Example:
winSyncSubtreePair: ou=OU1,dc=DSexample,dc=com:ou=OU1,DC=ADexample,DC=com
winSyncSubtreePair: ou=OU2,dc=DSexample,dc=com:ou=OU2,DC=ADexample,DC=com
winSyncSubtreePair: ou=OU3,dc=DSexample,dc=com:ou=OU3,DC=ADexample,DC=com
. Attribute type "winSyncSubtreePair" is added to the objectclass
"nsDSWindowsReplicationAgreement".
. If "winSyncSubtreePair" is not set, there is not behavioral
difference: the AD subtree "nsds7WindowsReplicaSubtree" and the
DS subtree "nsds7DirectoryReplicaSubtree" are used for the sync
target checks.
. When "winSyncSubtreePair" is set, the above 2 config parameters
are ignored.
To determine if an entry is the target of the synchronization,
the DN is examined whether the DN is a descendent of any of the
subtrees or not. If it is, the subtree of the counter part is
retrieved.
Moving an entry from one subtree to another is synchronized.
Members of a group is synchronized as long as the member entry
is in any of the defined subtrees.
2. Support filters
new config parameters in windwows sync agreement:
winSyncWindowsFilter: <additional filter on AD>
winSyncDirectoryFilter: <additional filter on DS>
Example:
winSyncWindowsFilter: (|(cn=*user*)(cn=*group*))
winSyncDirectoryFilter: (|(uid=*user*)(cn=*group*))
. The filters are set to the windows_userfilter and directory_
userfilter in the private area in the windows agreement. And
when each server is searched the filters are added to the internal
filter. For instance, filters shown in the above Example allow
synchronizing the entries which CN contains "user" or "group".
3. Misc
. Added slapi_sdn_set_ndn_byref, slapi_sdn_set_ndn_passin, and
slapi_sdn_common_ancestor to dn.c (see also slapi-plugin.h).
. Fixed memory leaks.
. Fixed some of the mixed indentations.
https://fedorahosted.org/389/ticket/460
Reviewed by Rich (Thank you!!)
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif
index b67ec8d..724c532 100644
--- a/ldap/schema/02common.ldif
+++ b/ldap/schema/02common.ldif
@@ -148,6 +148,9 @@ attributeTypes: ( 2.16.840.1.113730.3.1.1099 NAME
'winSyncInterval' DESC 'Netsca
attributeTypes: ( 2.16.840.1.113730.3.1.1100 NAME 'oneWaySync' DESC 'Netscape
defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN
'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.1101 NAME 'nsRoleScopeDN' DESC 'Scope
of a role' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN '389
Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2139 NAME 'winSyncMoveAction' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2162 NAME 'winSyncDirectoryFilter' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2163 NAME 'winSyncWindowsFilter' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2164 NAME 'winSyncSubtreePair' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape Directory Server' )
attributeTypes: ( 1.3.6.1.1.4 NAME 'vendorName' EQUALITY
1.3.6.1.4.1.1466.109.114.1 SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
NO-USER-MODIFICATION USAGE dSAOperation X-ORIGIN 'RFC 3045' )
attributeTypes: ( 1.3.6.1.1.5 NAME 'vendorVersion' EQUALITY
1.3.6.1.4.1.1466.109.114.1 SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE
NO-USER-MODIFICATION USAGE dSAOperation X-ORIGIN 'RFC 3045' )
attributeTypes: ( 2.16.840.1.113730.3.1.3023 NAME 'nsViewFilter' DESC
'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN
'Netscape Directory Server' )
@@ -182,7 +185,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.99 NAME
'cosSuperDefinition' DESC 'Netsca
objectClasses: ( 2.16.840.1.113730.3.2.100 NAME 'cosClassicDefinition' DESC
'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosTemplateDn $
cosspecifier ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.101 NAME 'cosPointerDefinition' DESC
'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosTemplateDn )
X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.102 NAME 'cosIndirectDefinition' DESC
'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosIndirectSpecifier )
X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.503 NAME 'nsDSWindowsReplicationAgreement'
DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $
nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $
nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $
nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $
description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $
nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $
nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress
$ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $
nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime $
nsds7WindowsReplicaSubtree $ nsds7DirectoryReplicaSubtree $ nsds7NewWinUserSyncEnabled $
nsds7NewWinGroupSyncEnabled $ nsds7WindowsDomain $ nsds7DirsyncCookie $ winSyncInterval $
oneWaySync $ winSyncM
oveAction $ nsds5ReplicaEnabled ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.503 NAME 'nsDSWindowsReplicationAgreement'
DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $
nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $
nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $
nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $
description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $
nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $
nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress
$ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $
nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime $
nsds7WindowsReplicaSubtree $ nsds7DirectoryReplicaSubtree $ nsds7NewWinUserSyncEnabled $
nsds7NewWinGroupSyncEnabled $ nsds7WindowsDomain $ nsds7DirsyncCookie $ winSyncInterval $
oneWaySync $ winSyncM
oveAction $ nsds5ReplicaEnabled $ winSyncDirectoryFilter $ winSyncWindowsFilter $
winSyncSubtreePair ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.128 NAME 'costemplate' DESC 'Netscape
defined objectclass' SUP top MAY ( cn $ cospriority ) X-ORIGIN 'Netscape Directory
Server' )
objectClasses: ( 2.16.840.1.113730.3.2.304 NAME 'nsView' DESC 'Netscape
defined objectclass' SUP top AUXILIARY MAY ( nsViewFilter $ description ) X-ORIGIN
'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.316 NAME 'nsAttributeEncryption' DESC
'Netscape defined objectclass' SUP top MUST ( cn $ nsEncryptionAlgorithm )
X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/plugins/replication/repl5.h
b/ldap/servers/plugins/replication/repl5.h
index b2c69a3..fc11232 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -182,6 +182,9 @@ extern const char *type_nsds7WindowsDomain;
extern const char *type_winSyncInterval;
extern const char *type_oneWaySync;
extern const char *type_winsyncMoveAction;
+extern const char *type_winSyncWindowsFilter;
+extern const char *type_winSyncDirectoryFilter;
+extern const char *type_winSyncSubtreePair;
/* To Allow Consumer Initialisation when adding an agreement - */
extern const char *type_nsds5BeginReplicaRefresh;
diff --git a/ldap/servers/plugins/replication/repl_globals.c
b/ldap/servers/plugins/replication/repl_globals.c
index b934354..c0b8712 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -145,6 +145,9 @@ const char *type_nsds7DirsyncCookie = "nsds7DirsyncCookie";
const char *type_winSyncInterval = "winSyncInterval";
const char *type_oneWaySync = "oneWaySync";
const char *type_winsyncMoveAction = "winSyncMoveAction";
+const char *type_winSyncWindowsFilter = "winSyncWindowsFilter";
+const char *type_winSyncDirectoryFilter = "winSyncDirectoryFilter";
+const char *type_winSyncSubtreePair = "winSyncSubtreePair";
/* To Allow Consumer Initialization when adding an agreement - */
const char *type_nsds5BeginReplicaRefresh = "nsds5BeginReplicaRefresh";
diff --git a/ldap/servers/plugins/replication/windows_connection.c
b/ldap/servers/plugins/replication/windows_connection.c
index e6bd062..c7c7a98 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -846,12 +846,13 @@ send_dirsync_search(Repl_Connection *conn)
const char *op_string = NULL;
int rc;
int scope = LDAP_SCOPE_SUBTREE;
- char *filter = slapi_ch_strdup("(objectclass=*)");
+ const char *userfilter = NULL;
+ char *filter = NULL;
char **attrs = NULL;
LDAPControl **server_controls = NULL;
int msgid;
- /* need to strip the dn down to dc= */
const char *old_dn = slapi_sdn_get_ndn(
windows_private_get_windows_subtree(conn->agmt) );
+ /* LDAP_SERVER_DIRSYNC_OID requires the search base Naming Context */
char *dn = slapi_ch_strdup(strstr(old_dn, "dc="));
char **exattrs = NULL;
@@ -861,8 +862,8 @@ send_dirsync_search(Repl_Connection *conn)
} else
{
slapi_add_control_ext(&server_controls,
- windows_private_dirsync_control(conn->agmt),
- 0 /* no copy - passin */);
+ windows_private_dirsync_control(conn->agmt),
+ 0 /* no copy - passin */);
}
conn->last_operation = CONN_SEARCH;
@@ -870,9 +871,15 @@ send_dirsync_search(Repl_Connection *conn)
op_string = "search";
LDAPDebug( LDAP_DEBUG_REPL, "Calling dirsync search request plugin\n", 0, 0,
0 );
+ userfilter = windows_private_get_windows_userfilter(conn->agmt);
+ if (userfilter) {
+ filter = slapi_ch_strdup(userfilter);
+ } else {
+ filter = slapi_ch_strdup("(objectclass=*)");
+ }
winsync_plugin_call_dirsync_search_params_cb(conn->agmt, old_dn, &dn,
&scope, &filter,
- &attrs, &server_controls);
+ &attrs, &server_controls);
exattrs = windows_private_get_range_attrs(conn->agmt);
charray_merge(&attrs, exattrs, 0 /* pass in */);
slapi_ch_free((void **)&exattrs); /* strings are passed in */
@@ -1038,7 +1045,7 @@ Slapi_Entry * windows_conn_get_search_result(Repl_Connection *conn)
{
char **exattrs = NULL;
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"received entry from
dirsync: %s\n", dn);
- lm = ldap_first_entry( conn->ld, res );
+ lm = ldap_first_entry( conn->ld, res );
e = windows_private_get_curr_entry(conn->agmt); /* if range search, e != NULL */
e = windows_LDAPMessage2Entry(e, conn, lm, 0, &exattrs);
ldap_memfree(dn);
diff --git a/ldap/servers/plugins/replication/windows_private.c
b/ldap/servers/plugins/replication/windows_private.c
index 51e959a..cfa2704 100644
--- a/ldap/servers/plugins/replication/windows_private.c
+++ b/ldap/servers/plugins/replication/windows_private.c
@@ -52,12 +52,12 @@
struct windowsprivate {
- Slapi_DN *windows_subtree; /* DN of synchronized subtree (on the windows side) */
+ Slapi_DN *windows_subtree; /* DN of synchronized subtree (on the windows side) */
Slapi_DN *directory_subtree; /* DN of synchronized subtree on directory side */
- /* this simplifies the mapping as it's simply
- from the former to the latter container, or
- vice versa */
- ber_int_t dirsync_flags;
+ /* this simplifies the mapping as it's simply
+ from the former to the latter container, or
+ vice versa */
+ ber_int_t dirsync_flags;
ber_int_t dirsync_maxattributecount;
char *dirsync_cookie;
int dirsync_cookie_len;
@@ -70,6 +70,7 @@ struct windowsprivate {
/* This filter is used to determine if an entry belongs to this agreement. We put it
here
* so we only have to allocate each filter once instead of doing it every time we
receive a change. */
Slapi_Filter *directory_filter; /* Used for checking if local entries need to be
sync'd to AD */
+ Slapi_Filter *windows_filter; /* Used for checking if remote entries need to be
sync'd to DS */
Slapi_Filter *deleted_filter; /* Used for checking if an entry is an AD tombstone */
Slapi_Entry *raw_entry; /* "raw" un-schema processed last entry read from AD
*/
int keep_raw_entry; /* flag to control when the raw entry is set */
@@ -79,9 +80,20 @@ struct windowsprivate {
int move_action; /* Indicates what to do with DS entry if AD entry is moved out of
scope */
Slapi_Entry *curr_entry; /* entry being retrieved; used for the range retrieval */
char **range_attrs; /* next attributes for the range retrieval */
+ char *windows_userfilter;
+ char *directory_userfilter;
+ struct subtreepair *subtree_pairs; /* Array of subtree pairs (winSyncSubtreePair) */
+ Slapi_DN *windows_treetop; /* Common subtree top to sync on AD */
+ /* If winSyncSubtreePair is not set, identical to
windows_subtree.
+ * If set, ancestor node of all AD subtrees. */
+ Slapi_DN *directory_treetop; /* Common subtree top to sync on DS */
+ /* If winSyncSubtreePair is not set, identical to
directory_subtree.
+ * If set, ancestor node of all DS subtrees. */
};
static void windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain);
+static subtreePair *create_subtree_pairs(char **pairs);
+static void free_subtree_pairs(subtreePair **pairs);
static int
true_value_from_string(char *val)
@@ -153,6 +165,10 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type,
Slapi_Entry *e)
return retval;
}
+ /*
+ * if winSyncSubtreePair is set, WindowsReplicaArea and DirectoryReplicaArea
+ * are ignored.
+ */
if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsReplicaArea))
{
tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea);
@@ -295,6 +311,29 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type,
Slapi_Entry *e)
}
retval = 1;
}
+ if (type == NULL || slapi_attr_types_equivalent(type,type_winSyncWindowsFilter))
+ {
+ tmpstr = slapi_entry_attr_get_charptr(e, type_winSyncWindowsFilter);
+ windows_private_set_windows_userfilter(ra, tmpstr); /* if NULL, set it */
+ retval = 1;
+ }
+ if (type == NULL || slapi_attr_types_equivalent(type,type_winSyncDirectoryFilter))
+ {
+ tmpstr = slapi_entry_attr_get_charptr(e, type_winSyncDirectoryFilter);
+ windows_private_set_directory_userfilter(ra, tmpstr); /* if NULL, set it */
+ retval = 1;
+ }
+ if (type == NULL || slapi_attr_types_equivalent(type, type_winSyncSubtreePair))
+ {
+ char **parray = slapi_entry_attr_get_charray(e, type_winSyncSubtreePair);
+
+ /* If winSyncSubtreePair is not set, subtree_pairs is NULL */
+ windows_private_set_subtreepairs(ra, parray);
+ slapi_ch_array_free(parray);
+ retval = 1;
+ }
+ windows_private_set_windows_treetop(ra, NULL);
+ windows_private_set_directory_treetop(ra, NULL);
return retval;
}
@@ -370,8 +409,14 @@ Dirsync_Private* windows_private_new()
dp->dirsync_maxattributecount = -1;
dp->directory_filter = NULL;
+ dp->windows_filter = NULL;
dp->deleted_filter = NULL;
dp->sync_interval = PERIODIC_DIRSYNC_INTERVAL;
+ dp->windows_userfilter = NULL;
+ dp->directory_userfilter = NULL;
+ dp->subtree_pairs = NULL;
+ dp->windows_treetop = NULL;
+ dp->directory_treetop = NULL;
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_new\n" );
return dp;
@@ -380,6 +425,7 @@ Dirsync_Private* windows_private_new()
void windows_agreement_delete(Repl_Agmt *ra)
{
+ const subtreePair *sp;
Dirsync_Private *dp = (Dirsync_Private *) agmt_get_priv(ra);
LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_delete\n" );
@@ -394,12 +440,25 @@ void windows_agreement_delete(Repl_Agmt *ra)
slapi_sdn_free(&dp->directory_subtree);
slapi_sdn_free(&dp->windows_subtree);
slapi_filter_free(dp->directory_filter, 1);
+ slapi_filter_free(dp->windows_filter, 1);
slapi_filter_free(dp->deleted_filter, 1);
slapi_entry_free(dp->raw_entry);
slapi_ch_free_string(&dp->windows_domain);
dp->raw_entry = NULL;
dp->api_cookie = NULL;
- slapi_ch_free((void **)dp);
+ slapi_ch_free_string(&dp->dirsync_cookie);
+ dp->dirsync_cookie_len = 0;
+
+ slapi_ch_free_string(&dp->windows_userfilter);
+ slapi_ch_free_string(&dp->directory_userfilter);
+ slapi_sdn_free((Slapi_DN **)&dp->windows_treetop);
+ slapi_sdn_free((Slapi_DN **)&dp->directory_treetop);
+ for (sp = dp->subtree_pairs; sp && sp->ADsubtree &&
sp->DSsubtree; sp++) {
+ slapi_sdn_free((Slapi_DN **)&sp->ADsubtree);
+ slapi_sdn_free((Slapi_DN **)&sp->DSsubtree);
+ }
+ slapi_ch_free((void **)&dp->subtree_pairs);
+ slapi_ch_free((void **)&dp);
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_delete\n" );
@@ -407,183 +466,228 @@ void windows_agreement_delete(Repl_Agmt *ra)
int windows_private_get_isnt4(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_isnt4\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_isnt4\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_isnt4\n" );
-
- return dp->isnt4;
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_isnt4\n" );
+
+ return dp->isnt4;
}
void windows_private_set_isnt4(const Repl_Agmt *ra, int isit)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_isnt4\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_isnt4\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- dp->isnt4 = isit;
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_isnt4\n" );
+ dp->isnt4 = isit;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_isnt4\n" );
}
int windows_private_get_iswin2k3(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_iswin2k3\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_iswin2k3\n" );
- return dp->iswin2k3;
+ return dp->iswin2k3;
}
void windows_private_set_iswin2k3(const Repl_Agmt *ra, int isit)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_iswin2k3\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- dp->iswin2k3 = isit;
+ dp->iswin2k3 = isit;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_iswin2k3\n" );
}
/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */
Slapi_Filter* windows_private_get_directory_filter(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_directory_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_directory_filter\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- if (dp->directory_filter == NULL) {
- char *string_filter =
slapi_ch_strdup("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))");
- /* The filter gets freed in windows_agreement_delete() */
- dp->directory_filter = slapi_str2filter( string_filter );
- slapi_ch_free_string(&string_filter);
+ if (dp->directory_filter == NULL) {
+ char *string_filter = NULL;
+ const char *userfilter = windows_private_get_directory_userfilter(ra);
+ if (userfilter) {
+ if ('(' == *userfilter) {
+ string_filter =
slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*)%s)",
+ userfilter);
+ } else {
+ string_filter =
slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*)(%s))",
+ userfilter);
+ }
+ } else {
+ string_filter =
slapi_ch_strdup("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))");
}
+ /* The filter gets freed in windows_agreement_delete() */
+ dp->directory_filter = slapi_str2filter( string_filter );
+ slapi_ch_free_string(&string_filter);
+ }
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_directory_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_directory_filter\n" );
- return dp->directory_filter;
+ return dp->directory_filter;
}
/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */
-Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra)
+Slapi_Filter*
+windows_private_get_windows_filter(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_deleted_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_filter\n"
);
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- if (dp->deleted_filter == NULL) {
- char *string_filter = slapi_ch_strdup("(isdeleted=*)");
+ if (dp->windows_filter == NULL) {
+ const char *userfilter = windows_private_get_windows_userfilter(ra);
+ if (userfilter) {
+ char *string_filter = NULL;
+ if ('(' == *userfilter) {
+ string_filter = slapi_ch_strdup(userfilter);
+ } else {
+ string_filter = slapi_ch_smprintf("(%s)", userfilter);
+ }
/* The filter gets freed in windows_agreement_delete() */
- dp->deleted_filter = slapi_str2filter( string_filter );
+ dp->windows_filter = slapi_str2filter( string_filter );
slapi_ch_free_string(&string_filter);
}
+ }
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_filter\n"
);
+
+ return dp->windows_filter;
+}
+
+/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */
+Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_deleted_filter\n"
);
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ if (dp->deleted_filter == NULL) {
+ char *string_filter = slapi_ch_strdup("(isdeleted=*)");
+ /* The filter gets freed in windows_agreement_delete() */
+ dp->deleted_filter = slapi_str2filter( string_filter );
+ slapi_ch_free_string(&string_filter);
+ }
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_deleted_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_deleted_filter\n"
);
- return dp->deleted_filter;
+ return dp->deleted_filter;
}
/* Returns a copy of the Slapi_DN pointer, no need to free it */
const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_windows_subtree\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_windows_subtree\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_windows_subtree\n" );
-
- return dp->windows_subtree;
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_windows_subtree\n" );
+
+ return dp->windows_subtree;
}
const char *
windows_private_get_windows_domain(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_windows_domain\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_domain\n"
);
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_windows_domain\n" );
-
- return dp->windows_domain;
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_domain\n"
);
+
+ return dp->windows_domain;
}
static void
windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_set_windows_domain\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_domain\n"
);
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- slapi_ch_free_string(&dp->windows_domain);
- dp->windows_domain = domain;
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_set_windows_domain\n" );
- }
+ slapi_ch_free_string(&dp->windows_domain);
+ dp->windows_domain = domain;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_domain\n"
);
+}
/* Returns a copy of the Slapi_DN pointer, no need to free it */
const Slapi_DN* windows_private_get_directory_subtree (const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_directory_replarea\n" );
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_directory_replarea\n" );
+ PR_ASSERT(ra);
- PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_directory_replarea\n" );
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_directory_replarea\n" );
-
- return dp->directory_subtree;
+ return dp->directory_subtree;
}
/* Takes a copy of the sdn passed in */
@@ -724,6 +828,299 @@ void windows_private_set_one_way(const Repl_Agmt *ra, int value)
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_one_way\n" );
}
+const char*
+windows_private_get_windows_userfilter(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_windows_userfilter\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_windows_userfilter\n" );
+
+ return dp->windows_userfilter;
+}
+
+/* filter is passed in */
+void
+windows_private_set_windows_userfilter(const Repl_Agmt *ra, char *filter)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_set_windows_userfilter\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_ch_free_string(&dp->windows_userfilter);
+ dp->windows_userfilter = filter;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_set_windows_userfilter\n" );
+}
+
+const char*
+windows_private_get_directory_userfilter(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_directory_userfilter\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_directory_userfilter\n" );
+
+ return dp->directory_userfilter;
+}
+
+/* filter is passed in */
+void
+windows_private_set_directory_userfilter(const Repl_Agmt *ra, char *filter)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_set_directory_userfilter\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_ch_free_string(&dp->directory_userfilter);
+ dp->directory_userfilter = filter;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_set_directory_userfilter\n" );
+}
+
+const subtreePair*
+windows_private_get_subtreepairs(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_subtreepairs\n"
);
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_subtreepairs\n"
);
+
+ return dp->subtree_pairs;
+}
+
+/* parray is NOT passed in */
+void
+windows_private_set_subtreepairs(const Repl_Agmt *ra, char **parray)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_subtreepairs\n"
);
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ free_subtree_pairs(&(dp->subtree_pairs));
+ dp->subtree_pairs = create_subtree_pairs(parray);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_subtreepairs\n"
);
+}
+
+/*
+ * winSyncSubtreePair: <DS_SUBTREE>:<WINDOWS_SUBTREE>
+ * E.g.,
+ * winSyncSubtreePair: ou=people,dc=example,dc=com:CN=users,DC=example,DC=com
+ * winSyncSubtreePair: ou=adminpeople,dc=example,dc=com:CN=adminusers,DC=example,DC=com
+ */
+static subtreePair *
+create_subtree_pairs(char **pairs)
+{
+ subtreePair *subtree_pairs = NULL;
+ subtreePair *spp;
+ char **ptr;
+ char *p0, *p1;
+ char *saveptr;
+ int cnt;
+
+ for (cnt = 0, ptr = pairs; ptr && *ptr; cnt++, ptr++) ;
+ if (0 == cnt) {
+ return NULL;
+ }
+ subtree_pairs = (subtreePair *)slapi_ch_calloc(cnt + 1, sizeof(subtreePair));
+ spp = subtree_pairs;
+
+ for (ptr = pairs; ptr && *ptr; ptr++) {
+ p0 = ldap_utf8strtok_r(*ptr, ":", &saveptr);
+ p1 = ldap_utf8strtok_r(NULL, ":", &saveptr);
+ spp->DSsubtree = slapi_sdn_new_dn_byval(p0);
+ if (NULL == spp->DSsubtree) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "create_subtree_pairs: "
+ "Ignoring invalid DS subtree \"%s\".\n",
+ p0);
+ continue;
+ }
+ spp->ADsubtree = slapi_sdn_new_dn_byval(p1);
+ if (NULL == spp->ADsubtree) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "create_subtree_pairs: "
+ "Ignoring invalid AD subtree \"%s\".\n",
+ p1);
+ slapi_sdn_free(&(spp->DSsubtree));
+ continue;
+ }
+ spp++;
+ }
+ return subtree_pairs;
+}
+
+static void
+free_subtree_pairs(subtreePair **pairs)
+{
+ subtreePair *p;
+
+ if (NULL == pairs) {
+ return;
+ }
+ for (p = *pairs; p; p++) {
+ slapi_sdn_free(&(p->ADsubtree));
+ slapi_sdn_free(&(p->DSsubtree));
+ }
+ slapi_ch_free((void **)pairs);
+}
+
+const Slapi_DN*
+windows_private_get_windows_treetop(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_windows_treetop\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_windows_treetop\n" );
+
+ return dp->windows_treetop;
+}
+
+/* treetop is NOT passed in */
+void
+windows_private_set_windows_treetop(const Repl_Agmt *ra, char *treetop)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_set_windows_treetop\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_sdn_free(&(dp->windows_treetop));
+ if (treetop) {
+ dp->windows_treetop = slapi_sdn_new_dn_byval(treetop);
+ } else {
+ const subtreePair *subtree_pairs = windows_private_get_subtreepairs(ra);
+ const subtreePair *sp;
+ if (subtree_pairs) {
+ Slapi_DN *treetop_sdn = NULL;
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ if (NULL == treetop_sdn) {
+ treetop_sdn = slapi_sdn_dup(sp->ADsubtree);
+ } else {
+ Slapi_DN *prev = treetop_sdn;
+ treetop_sdn = slapi_sdn_common_ancestor(prev, sp->ADsubtree);
+ slapi_sdn_free(&prev);
+ }
+ }
+ if (treetop_sdn) {
+ dp->windows_treetop = treetop_sdn;
+ } else {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "windows_private_set_windows_treetop: "
+ "winSyncSubtreePair contains inconsistent Windows
subtrees.\n");
+ dp->windows_treetop = NULL;
+ }
+ } else {
+ const Slapi_DN *windows_subtree = windows_private_get_windows_subtree(ra);
+ dp->windows_treetop = slapi_sdn_dup(windows_subtree);
+ }
+ }
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_set_windows_treetop\n" );
+}
+
+const Slapi_DN*
+windows_private_get_directory_treetop(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_get_directory_treetop\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_get_directory_treetop\n" );
+
+ return dp->directory_treetop;
+}
+
+/* treetop is NOT passed in */
+void
+windows_private_set_directory_treetop(const Repl_Agmt *ra, char *treetop)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=>
windows_private_set_directory_treetop\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_sdn_free(&(dp->directory_treetop));
+ if (treetop) {
+ dp->directory_treetop = slapi_sdn_new_dn_byval(treetop);
+ } else {
+ const subtreePair *subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair *sp;
+ Slapi_DN *treetop_sdn = NULL;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (NULL == treetop_sdn) {
+ treetop_sdn = slapi_sdn_dup(sp->DSsubtree);
+ } else {
+ Slapi_DN *prev = treetop_sdn;
+ treetop_sdn = slapi_sdn_common_ancestor(prev, sp->DSsubtree);
+ slapi_sdn_free(&prev);
+ }
+ }
+ if (treetop_sdn) {
+ dp->directory_treetop = treetop_sdn;
+ } else {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "windows_private_set_directory_treetop: "
+ "winSyncSubtreePair contains inconsistent Windows
subtrees.\n");
+ dp->directory_treetop = NULL;
+ }
+ } else {
+ const Slapi_DN *directory_subtree = windows_private_get_directory_subtree(ra);
+ dp->directory_treetop = slapi_sdn_dup(directory_subtree);
+ }
+ }
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<=
windows_private_set_directory_treetop\n" );
+}
/*
This function returns the current Dirsync_Private that's inside
@@ -744,7 +1141,7 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
- ber = ber_alloc();
+ ber = ber_alloc();
ber_printf( ber, "{iio}", dp->dirsync_flags,
dp->dirsync_maxattributecount, dp->dirsync_cookie ? dp->dirsync_cookie :
"", dp->dirsync_cookie_len );
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c
b/ldap/servers/plugins/replication/windows_protocol_util.c
index e618be0..40b5c3f 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -1136,10 +1136,33 @@ process_replay_add(Private_Repl_Protocol *prp, Slapi_Entry
*add_entry, Slapi_Ent
if (cn_string) {
char *container_str = NULL;
- const char *suffix =
slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ const char *suffix = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
+ /* Figure out the Windows subtree from the local subtree... */
+ local_sdn = slapi_entry_get_sdn_const(local_entry);
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (slapi_sdn_scope_test(local_sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE)) {
+ suffix = slapi_sdn_get_dn(sp->ADsubtree);
+ break;
+ }
+ }
+ }
+ if (NULL == suffix) {
+ suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ }
- container_str = extract_container(slapi_entry_get_sdn_const(local_entry),
- windows_private_get_directory_subtree(prp->agmt));
+ if (sp && sp->DSsubtree) {
+ container_str = extract_container(slapi_entry_get_sdn_const(local_entry),
+ sp->DSsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(local_entry),
+
windows_private_get_directory_subtree(prp->agmt));
+ }
new_dn_string = slapi_create_dn_string("cn=\"%s\",%s%s",
cn_string, container_str, suffix);
if (new_dn_string) {
@@ -1311,7 +1334,9 @@ process_replay_rename(Private_Repl_Protocol *prp,
char *remote_rdn = NULL;
char *remote_dn = NULL;
char *local_pndn = NULL;
-
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
if (NULL == local_origsdn || NULL == local_newentry) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"process_replay_rename: %s is empty\n",
@@ -1324,29 +1349,40 @@ process_replay_rename(Private_Repl_Protocol *prp,
/* Generate newsuperior for AD */
winrepl_agmt = prp->agmt;
- remote_subtree =
- slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
- local_subtree =
- slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
- if (NULL == remote_subtree || NULL == local_subtree ||
- '\0' == *remote_subtree || '\0' == *local_subtree) {
+ remote_subtree = slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
+ local_subtree = slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
+ subtree_pairs = windows_private_get_subtreepairs(winrepl_agmt);
+ if ((NULL == remote_subtree || NULL == local_subtree ||
+ '\0' == *remote_subtree || '\0' == *local_subtree) &&
+ (NULL == subtree_pairs)) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"process_replay_rename: local subtree \"%s\" or "
- "remote subtree \"%s\" is empty\n",
+ "remote subtree \"%s\" and "
+ "subtree_pairs are empty\n",
local_subtree?local_subtree:"empty",
remote_subtree?remote_subtree:"empty");
goto bail;
}
- /* if given, newparent is already normzlized; just ignore the case */
+ /* if given, newparent is already normalized; just ignore the case */
if (newparent) {
norm_newparent = slapi_ch_strdup(newparent);
+ slapi_dn_ignore_case(norm_newparent);
} else {
/* newparent is NULL; set the original parent */
/* slapi_dn_parent returns the dup'ed dn */
norm_newparent = slapi_dn_parent(slapi_sdn_get_ndn(local_origsdn));
}
- slapi_dn_ignore_case(norm_newparent);
- p = strstr(norm_newparent, local_subtree);
+ p = NULL;
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ p = strstr(norm_newparent, slapi_sdn_get_ndn(sp->DSsubtree));
+ if (p) {
+ break;
+ }
+ }
+ } else {
+ p = strstr(norm_newparent, local_subtree);
+ }
if (NULL == p) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"process_replay_rename: new superior \"%s\" is not "
@@ -1354,11 +1390,20 @@ process_replay_rename(Private_Repl_Protocol *prp,
norm_newparent, local_subtree);
goto bail; /* not in the subtree */
}
- *p = '\0';
- if (p == norm_newparent) {
- newsuperior = PR_smprintf("%s", remote_subtree);
+ if (sp && sp->DSsubtree) {
+ if (p == norm_newparent) {
+ newsuperior = PR_smprintf("%s", slapi_sdn_get_ndn(sp->ADsubtree));
+ } else {
+ *p = '\0';
+ newsuperior = PR_smprintf("%s%s", norm_newparent,
slapi_sdn_get_ndn(sp->ADsubtree));
+ }
} else {
- newsuperior = PR_smprintf("%s%s", norm_newparent, remote_subtree);
+ if (p == norm_newparent) {
+ newsuperior = PR_smprintf("%s", remote_subtree);
+ } else {
+ *p = '\0';
+ newsuperior = PR_smprintf("%s%s", norm_newparent, remote_subtree);
+ }
}
if (is_user) {
@@ -1385,7 +1430,16 @@ process_replay_rename(Private_Repl_Protocol *prp,
/* local parent normalized dn */
local_pndn = /* strdup'ed */
slapi_dn_parent((const char *)slapi_sdn_get_ndn(local_origsdn));
- p = strstr(local_pndn, local_subtree);
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ p = strstr(local_pndn, slapi_sdn_get_ndn(sp->DSsubtree));
+ if (p) {
+ break;
+ }
+ }
+ } else {
+ p = strstr(local_pndn, local_subtree);
+ }
if (NULL == p) {
/* Original entry is not in the subtree.
* To add the entry after returning from this function,
@@ -1393,10 +1447,23 @@ process_replay_rename(Private_Repl_Protocol *prp,
windows_conn_set_error(prp->conn, LDAP_NO_SUCH_OBJECT);
goto bail;
}
- *p = '\0';
/* generate a remote dn */
- remote_dn = PR_smprintf("%s,%s%s", remote_rdn, local_pndn, remote_subtree);
+ if (sp && sp->DSsubtree) {
+ if (p == local_pndn) {
+ remote_dn = PR_smprintf("%s,%s", remote_rdn,
slapi_sdn_get_ndn(sp->ADsubtree));
+ } else {
+ *p = '\0';
+ remote_dn = PR_smprintf("%s,%s%s", remote_rdn, local_pndn,
slapi_sdn_get_ndn(sp->ADsubtree));
+ }
+ } else {
+ if (p == local_pndn) {
+ remote_dn = PR_smprintf("%s,%s", remote_rdn, remote_subtree);
+ } else {
+ *p = '\0';
+ remote_dn = PR_smprintf("%s,%s%s", remote_rdn, local_pndn, remote_subtree);
+ }
+ }
if (!deleteoldrdn) {
/* AD does not accept deleteoldrdn == 0 */
/*
@@ -1677,7 +1744,7 @@ windows_replay_update(Private_Repl_Protocol *prp,
slapi_operation_parameters *op
case SLAPI_OPERATION_MODRDN:
/* only move case (newsuperior: ...) comse here since local leaf RDN is
* not identical to the remote leaf RDN. */
- {
+ {
return_value = process_replay_rename(prp, local_entry, local_dn,
op->p.p_modrdn.modrdn_newrdn,
REPL_GET_DN(&op->p.p_modrdn.modrdn_newsuperior_address),
@@ -1696,7 +1763,7 @@ windows_replay_update(Private_Repl_Protocol *prp,
slapi_operation_parameters *op
}
}
break;
- }
+ }
default:
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: replay_update:
Unknown "
"operation type %lu found in changelog - skipping change.\n",
@@ -2372,8 +2439,12 @@ windows_get_superior_change(Private_Repl_Protocol *prp,
char *local_pndn = NULL; /* Normalized parent dn of the local entry */
const char *remote_subtree = NULL; /* Normalized subtree of the remote entry */
const char *local_subtree = NULL; /* Normalized subtree of the local entry */
- char *ptr = NULL;
+ char *mptr = NULL;
+ char *lptr = NULL;
int rc = -1;
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* msp = NULL;
+ const subtreePair* lsp = NULL;
if (NULL == newsuperior) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
@@ -2389,15 +2460,16 @@ windows_get_superior_change(Private_Repl_Protocol *prp,
/* Check if modrdn with superior has happened on AD */
winrepl_agmt = prp->agmt;
- remote_subtree =
- slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
- local_subtree =
- slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
- if (NULL == remote_subtree || NULL == local_subtree ||
- '\0' == *remote_subtree || '\0' == *local_subtree) {
+ remote_subtree = slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
+ local_subtree = slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
+ subtree_pairs = windows_private_get_subtreepairs(winrepl_agmt);
+ if ((NULL == remote_subtree || NULL == local_subtree ||
+ '\0' == *remote_subtree || '\0' == *local_subtree) &&
+ (NULL == subtree_pairs)) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"windows_get_superior_change: local subtree \"%s\" or "
- "remote subtree \"%s\" is empty\n",
+ "remote subtree \"%s\" and "
+ "subtree_pairs are empty\n",
local_subtree?local_subtree:"empty",
remote_subtree?remote_subtree:"empty");
goto bail;
@@ -2423,18 +2495,69 @@ windows_get_superior_change(Private_Repl_Protocol *prp,
mapped_pndn?mapped_pndn:"empty");
goto bail;
}
- ptr = strstr(mapped_pndn, local_subtree);
- if (ptr) {
- *ptr = '\0'; /* if ptr != mapped_pndn, mapped_pndn ends with ',' */
- ptr = strstr(local_pndn, local_subtree);
- if (ptr) {
- *ptr = '\0'; /* if ptr != local_pndn, local_pndn ends with ',' */
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (msp = subtree_pairs; msp && msp->DSsubtree; msp++) {
+ mptr = strstr(mapped_pndn, slapi_sdn_get_ndn(msp->DSsubtree));
+ if (mptr) {
+ break;
+ }
+ }
+ } else {
+ mptr = strstr(mapped_pndn, local_subtree);
+ }
+ if (mptr) {
+ /* mapped DN (originally from AD) is in the DS subtree(s) defined in the agreement */
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (lsp = subtree_pairs; lsp && lsp->DSsubtree; lsp++) {
+ lptr = strstr(local_pndn, slapi_sdn_get_ndn(lsp->DSsubtree));
+ if (lptr) {
+ break;
+ }
+ }
+ } else {
+ lptr = strstr(local_pndn, local_subtree);
+ }
+ if (lptr) {
+ /* local DN is in the DS subtree(s) defined in the agreement*/
if (0 != strcmp(mapped_pndn, local_pndn)) {
- /* the remote parent is different from the local parent */
- if (to_windows) {
- *newsuperior = slapi_create_dn_string("%s%s", local_pndn,
remote_subtree);
- } else {
- *newsuperior = slapi_create_dn_string("%s%s", mapped_pndn,
local_subtree);
+ /*
+ * The mapped remote parent is different from the local parent.
+ * we need to move the entry to the new superior.
+ */
+ if (to_windows) { /* from DS to AD */
+ if (lsp && lsp->ADsubtree) {
+ if (lptr == local_pndn) {
+ *newsuperior = slapi_ch_strdup(slapi_sdn_get_ndn(lsp->ADsubtree));
+ } else {
+ *lptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", local_pndn,
+ slapi_sdn_get_ndn(lsp->ADsubtree));
+ }
+ } else {
+ if (lptr == local_pndn) {
+ *newsuperior = slapi_ch_smprintf("%s", remote_subtree);
+ } else {
+ *lptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", local_pndn, remote_subtree);
+ }
+ }
+ } else { /* from AD to DS */
+ if (msp && msp->DSsubtree) {
+ if (mptr == mapped_pndn) {
+ *newsuperior = slapi_ch_strdup(slapi_sdn_get_ndn(msp->DSsubtree));
+ } else {
+ *mptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", mapped_pndn,
+ slapi_sdn_get_ndn(msp->DSsubtree));
+ }
+ } else {
+ if (mptr == mapped_pndn) {
+ *newsuperior = slapi_ch_strdup(local_subtree);
+ } else {
+ *mptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", mapped_pndn, local_subtree);
+ }
+ }
}
rc = 0;
}
@@ -2642,6 +2765,7 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,
const Slapi_Entry *ad_entry = NULL;
Slapi_Entry *ad_entry_copy = NULL;
const Slapi_DN *windows_subtree = NULL;
+ const subtreePair* subtree_pairs = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_map_mods_for_replay\n", 0, 0, 0
);
if (NULL == prp) {
@@ -2650,7 +2774,8 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,
return;
}
windows_subtree = windows_private_get_windows_subtree(prp->agmt);
- if (NULL == windows_subtree) {
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if ((NULL == windows_subtree) && (NULL == subtree_pairs)) {
LDAPDebug(LDAP_DEBUG_TRACE,
"<= windows_map_mods_for_replay; NULL agreement subtree;
NOOP\n", 0, 0, 0);
return;
@@ -2770,8 +2895,17 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,
const char *strval = slapi_value_get_string(valp); /* no dup */
if (strval) {
slapi_sdn_set_dn_byref(sdn, strval);
- is_in_subtree = slapi_sdn_scope_test(sdn, windows_subtree,
- LDAP_SCOPE_SUBTREE);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ is_in_subtree = slapi_sdn_scope_test(sdn, sp->ADsubtree,
LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree) {
+ break;
+ }
+ }
+ } else {
+ is_in_subtree = slapi_sdn_scope_test(sdn, windows_subtree,
LDAP_SCOPE_SUBTREE);
+ }
if (is_in_subtree) {
/*
* If delete all on DS,
@@ -3015,18 +3149,18 @@ find_entry_by_attr_value_remote(const char *attribute, const char
*value, Slapi_
int retval = 0;
ConnResult cres = 0;
char *filter = NULL;
- const char *searchbase = NULL;
+ const Slapi_DN *searchbase = NULL;
Slapi_Entry *found_entry = NULL;
/* should not have to escape attribute names */
filter = slapi_filter_sprintf("(%s=%s%s)",attribute, ESC_NEXT_VAL, value);
- searchbase = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
- cres = windows_search_entry(prp->conn, (char*)searchbase, filter, &found_entry);
+ searchbase = windows_private_get_windows_treetop(prp->agmt);
+ cres = windows_search_entry(prp->conn, (char*)slapi_sdn_get_dn(searchbase), filter,
&found_entry);
if (cres)
{
retval = -1;
} else
- {
+ {
if (found_entry)
{
*e = found_entry;
@@ -3136,7 +3270,7 @@ find_entry_by_attr_value(const char *attribute, const char *value,
Slapi_Entry *
Slapi_Entry **entries = NULL, **ep = NULL;
Slapi_Entry *entry_found = NULL;
LDAPControl **server_controls = NULL;
- const char *subtree_dn = NULL;
+ const Slapi_DN *subtree_sdn = NULL;
char *subtree_dn_copy = NULL;
char **attrs = NULL;
char *query = NULL;
@@ -3152,10 +3286,10 @@ find_entry_by_attr_value(const char *attribute, const char *value,
Slapi_Entry *
query = slapi_filter_sprintf("(%s=%s%s)", attribute, ESC_NEXT_VAL, value);
if (query == NULL)
- goto done;
+ goto done;
- subtree_dn = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
- subtree_dn_copy = slapi_ch_strdup(subtree_dn);
+ subtree_sdn = windows_private_get_directory_treetop(ra);
+ subtree_dn_copy = slapi_ch_strdup(slapi_sdn_get_ndn(subtree_sdn));
winsync_plugin_call_pre_ds_search_entry_cb(ra, NULL, &subtree_dn_copy,
&scope, &query,
&attrs, &server_controls);
@@ -3391,9 +3525,10 @@ map_windows_tombstone_dn(Slapi_Entry *e, Slapi_DN **dn,
Private_Repl_Protocol *p
/* The tombstone suffix discards any containers, so we need
* to trim the DN to only dc components. */
- if ((suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt)))) {
+ suffix = slapi_sdn_get_ndn(windows_private_get_windows_treetop(prp->agmt));
+ if (suffix) {
/* If this isn't found, it is treated as an error below. */
- suffix = (const char *) PL_strcasestr(suffix,"dc=");
+ suffix = (const char *)PL_strstr(suffix, "dc=");
}
if (cn && guid && suffix) {
@@ -3566,7 +3701,18 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn,
Private_Repl_Protocol *prp,
char *guid = NULL;
Slapi_DN *new_dn = NULL;
int is_nt4 = windows_private_get_isnt4(prp->agmt);
- const char *suffix =
slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ const char *suffix = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
+ if (NULL == e) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_outbound: NULL entry.\n",
+ agmt_get_long_name(prp->agmt));
+ return -1;
+ }
+
/* To find the DN of the peer entry we first look for an ntUniqueId attribute
* on the local entry. If that's present, we generate a GUID-form DN.
* If there's no GUID, then we look for an ntUserDomainId attribute
@@ -3585,6 +3731,25 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn,
Private_Repl_Protocol *prp,
*dn = NULL;
*missing_entry = 0;
+ local_sdn = slapi_entry_get_sdn_const(e);
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (slapi_sdn_scope_test(local_sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE)) {
+ suffix = slapi_sdn_get_dn(sp->ADsubtree);
+ break;
+ }
+ }
+ } else {
+ suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ }
+ if (NULL == suffix) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_outbound: Failed to get the AD suffix of
%s.\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(local_sdn));
+ return -1;
+ }
+
guid = slapi_entry_attr_get_charptr(e,"ntUniqueId");
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
"%s: map_entry_dn_outbound: looking for AD entry for DS "
@@ -3646,8 +3811,12 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn,
Private_Repl_Protocol *prp,
if (cn_string) {
char *container_str = NULL;
- container_str = extract_container(slapi_entry_get_sdn_const(e),
- windows_private_get_directory_subtree(prp->agmt));
+ if (sp) {
+ container_str = extract_container(slapi_entry_get_sdn_const(e), sp->DSsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
+
windows_private_get_directory_subtree(prp->agmt));
+ }
new_dn_string = slapi_create_dn_string("cn=\"%s\",%s%s",
cn_string, container_str, suffix);
if (new_dn_string) {
@@ -3714,7 +3883,12 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn,
Private_Repl_Protocol *prp,
char *rdnstr = NULL;
char *container_str = NULL;
- container_str = extract_container(slapi_entry_get_sdn_const(e),
windows_private_get_directory_subtree(prp->agmt));
+ if (sp) {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
sp->DSsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
+
windows_private_get_directory_subtree(prp->agmt));
+ }
rdnstr = is_nt4 ? "samaccountname=\"%s\",%s%s" :
"cn=\"%s\",%s%s";
@@ -3843,6 +4017,14 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const
Repl_Agmt *ra, int
int is_user = 0;
int is_group = 0;
int is_nt4 = windows_private_get_isnt4(ra);
+ char *container_str = NULL;
+
+ if (NULL == e) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_inbound: entry is NULL.\n",
+ agmt_get_long_name(ra));
+ return -1;
+ }
/* To map a non-tombstone's DN we need to first try to look it up by GUID.
* If we do not find it, then we need to generate the DN that it would have if added as
a new entry.
@@ -3967,10 +4149,34 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const
Repl_Agmt *ra, int
char *new_dn_string = NULL;
if (username)
{
- const char *suffix = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
- char *container_str = NULL;
+ const char *suffix = NULL;
+ const subtreePair* subtree_pairs = windows_private_get_subtreepairs(ra);
+ const subtreePair* sp = NULL;
+ const Slapi_DN *remote_sdn = slapi_entry_get_sdn_const(e);
+
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ if (slapi_sdn_scope_test(remote_sdn, sp->ADsubtree, LDAP_SCOPE_SUBTREE)) {
+ suffix = slapi_sdn_get_dn(sp->DSsubtree);
+ break;
+ }
+ }
+ } else {
+ suffix = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
+ }
- container_str = extract_container(slapi_entry_get_sdn_const(e),
windows_private_get_windows_subtree(ra));
+ if (sp) {
+ container_str = extract_container(slapi_entry_get_sdn_const(e), sp->ADsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
+ windows_private_get_windows_subtree(ra));
+ }
+ if (NULL == suffix) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_inbound: Failed to retrieve local suiffx from %s\n",
+ agmt_get_long_name(ra), slapi_sdn_get_dn(remote_sdn));
+ goto error;
+ }
/* Local DNs for users and groups are different */
if (is_user)
{
@@ -3979,8 +4185,10 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const
Repl_Agmt *ra, int
windows_private_get_raw_entry(ra),
e,
&new_dn_string,
- windows_private_get_directory_subtree(ra),
- windows_private_get_windows_subtree(ra));
+ sp?sp->DSsubtree:
+ windows_private_get_directory_subtree(ra),
+ sp?sp->ADsubtree:
+ windows_private_get_windows_subtree(ra));
} else
{
new_dn_string =
slapi_create_dn_string("cn=\"%s\",%s%s",username,container_str,suffix);
@@ -3989,8 +4197,10 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const
Repl_Agmt *ra, int
windows_private_get_raw_entry(ra),
e,
&new_dn_string,
- windows_private_get_directory_subtree(ra),
- windows_private_get_windows_subtree(ra));
+ sp?sp->DSsubtree:
+ windows_private_get_directory_subtree(ra),
+ sp?sp->ADsubtree:
+ windows_private_get_windows_subtree(ra));
}
}
/*
@@ -3998,7 +4208,6 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const
Repl_Agmt *ra, int
* which is normalized. Thus, we can use _normdn_.
*/
new_dn = slapi_sdn_new_normdn_passin(new_dn_string);
- slapi_ch_free_string(&container_str);
} else
{
/* Error, no username */
@@ -4015,14 +4224,9 @@ error:
{
PR_smprintf_free(guid);
}
- if (matching_entry)
- {
- slapi_entry_free(matching_entry);
- }
- if (username)
- {
- slapi_ch_free_string(&username);
- }
+ slapi_entry_free(matching_entry);
+ slapi_ch_free_string(&username);
+ slapi_ch_free_string(&container_str);
return retval;
}
@@ -4034,30 +4238,41 @@ is_subject_of_agreement_local(const Slapi_Entry *local_entry,
const Repl_Agmt *r
{
int retval = 0;
int is_in_subtree = 0;
- const Slapi_DN *agreement_subtree = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
- /* First test for the sync'ed subtree */
- agreement_subtree = windows_private_get_directory_subtree(ra);
- if (NULL == agreement_subtree)
- {
+ if (!local_entry) {
+ /* Error: couldn't find the entry */
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "failed to find entry in is_subject_of_agreement_local\n");
goto error;
}
- is_in_subtree = slapi_sdn_scope_test(slapi_entry_get_sdn_const(local_entry),
agreement_subtree, LDAP_SCOPE_SUBTREE);
- if (is_in_subtree)
- {
- /* Next test for the correct kind of entry */
- if (local_entry) {
- if (slapi_filter_test_simple( (Slapi_Entry*)local_entry,
- (Slapi_Filter*)windows_private_get_directory_filter(ra)) == 0)
- {
- retval = 1;
+
+ /* First test for the sync'ed subtree */
+ local_sdn = slapi_entry_get_sdn_const(local_entry);
+ subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ is_in_subtree = slapi_sdn_scope_test(local_sdn,
+ sp->DSsubtree, LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree) {
+ break;
}
- } else
- {
- /* Error: couldn't find the entry */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "failed to find entry in is_subject_of_agreement_local: %d\n", retval);
- retval = 0;
+ }
+ } else {
+ const Slapi_DN *agreement_subtree = NULL;
+ agreement_subtree = windows_private_get_directory_subtree(ra);
+ if (agreement_subtree) {
+ is_in_subtree = slapi_sdn_scope_test(local_sdn,
+ agreement_subtree, LDAP_SCOPE_SUBTREE);
+ }
+ }
+ if (is_in_subtree) {
+ /* Next test for the correct kind of entry */
+ if (slapi_filter_test_simple((Slapi_Entry*)local_entry,
+ windows_private_get_directory_filter(ra)) == 0) {
+ retval = 1;
}
}
error:
@@ -4069,19 +4284,26 @@ static int
is_dn_subject_of_agreement_local(const Slapi_DN *sdn, const Repl_Agmt *ra)
{
int retval = 0;
- const Slapi_DN *agreement_subtree = NULL;
+ const subtreePair* subtree_pairs = NULL;
/* Get the subtree from the agreement */
- agreement_subtree = windows_private_get_directory_subtree(ra);
- if (NULL == agreement_subtree)
- {
- goto error;
+ subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ retval = slapi_sdn_scope_test(sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE);
+ if (retval) {
+ break;
+ }
+ }
+ } else {
+ const Slapi_DN *agreement_subtree = NULL;
+ agreement_subtree = windows_private_get_directory_subtree(ra);
+ if (agreement_subtree) {
+ /* Check if the DN is within the subtree */
+ retval = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
+ }
}
-
- /* Check if the DN is within the subtree */
- retval = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
-
-error:
return retval;
}
@@ -4097,20 +4319,41 @@ is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt
*ra)
int retval = 0;
int is_in_subtree = 0;
const Slapi_DN *agreement_subtree = NULL;
- const Slapi_DN *sdn;
-
- /* First test for the sync'ed subtree */
- agreement_subtree = windows_private_get_windows_subtree(ra);
- if (NULL == agreement_subtree)
- {
+ const Slapi_DN *sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+
+ if (!e) {
goto error;
}
sdn = slapi_entry_get_sdn_const(e);
- is_in_subtree = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
+ /* First test for the sync'ed subtree */
+ /* check the subtree pairs; if not set, check windows_subtree */
+ subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ is_in_subtree = slapi_sdn_scope_test(sdn, sp->ADsubtree, LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree) {
+ agreement_subtree = sp->ADsubtree;
+ break;
+ }
+ }
+ } else {
+ agreement_subtree = windows_private_get_windows_subtree(ra);
+ if (agreement_subtree) {
+ is_in_subtree = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
+ }
+ }
if (is_in_subtree)
{
Slapi_DN psdn = {0};
Slapi_Entry *pentry = NULL;
+
+ if (windows_private_get_windows_filter(ra) &&
+ slapi_filter_test_simple(e, windows_private_get_windows_filter(ra))) {
+ /* type_winSyncWindowsFilter is set and the remote entry does not match the filter */
+ goto error;
+ }
/*
* Check whether the parent of the entry exists or not.
* If it does not, treat the entry e is out of scope.
@@ -4357,9 +4600,16 @@ windows_generate_dn_value_mods(char *local_type, const Slapi_Attr
*attr, Slapi_M
return ret;
}
-/* Generate the mods for an update in either direction. Be careful... the
"remote" entry is the DS entry in the to_windows case, but the AD entry in the
other case. */
+/*
+ * Generate the mods for an update in either direction.
+ */
static int
-windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entry,Slapi_Entry *local_entry, int to_windows, Slapi_Mods *smods, int
*do_modify)
+windows_generate_update_mods(Private_Repl_Protocol *prp,
+ Slapi_Entry *remote_entry,
+ Slapi_Entry *local_entry,
+ int to_windows,
+ Slapi_Mods *smods,
+ int *do_modify)
{
int retval = 0;
Slapi_Attr *attr = NULL;
@@ -4369,6 +4619,10 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entr
int rc = 0;
int is_nt4 = windows_private_get_isnt4(prp->agmt);
const Slapi_DN *local_subtree = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+ Slapi_Entry *target_entry = NULL;
+
/* Iterate over the attributes on the remote entry, updating the local entry where
appropriate */
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_generate_update_mods\n", 0, 0, 0
);
@@ -4385,14 +4639,16 @@ windows_generate_update_mods(Private_Repl_Protocol
*prp,Slapi_Entry *remote_entr
if (to_windows)
{
- windows_is_local_entry_user_or_group(remote_entry,&is_user,&is_group);
+ windows_is_local_entry_user_or_group(local_entry,&is_user,&is_group);
+ target_entry = local_entry;
} else
{
windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
+ target_entry = remote_entry;
}
- for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0;
- rc = slapi_entry_next_attr(remote_entry, attr, &attr))
+ for (rc = slapi_entry_first_attr(target_entry, &attr); rc == 0;
+ rc = slapi_entry_next_attr(target_entry, attr, &attr))
{
int is_present_local = 0;
char *type = NULL;
@@ -4432,7 +4688,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entr
}
if (to_windows && (0 == slapi_attr_type_cmp(local_type,
"streetAddress", SLAPI_TYPE_CMP_SUBTYPE))) {
- slapi_entry_attr_find(local_entry,FAKE_STREET_ATTR_NAME,&local_attr);
+ slapi_entry_attr_find(remote_entry,FAKE_STREET_ATTR_NAME,&local_attr);
} else {
slapi_entry_attr_find(local_entry,local_type,&local_attr);
}
@@ -4474,8 +4730,8 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entr
if (!values_equal)
{
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "windows_generate_update_mods: %s, %s : values are different\n",
- slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type);
+ "windows_generate_update_mods: %s, %s : values are
different\n",
+ slapi_entry_get_dn_const(local_entry), local_type);
if (to_windows && ((0 == slapi_attr_type_cmp(local_type,
"streetAddress", SLAPI_TYPE_CMP_SUBTYPE)) ||
(0 == slapi_attr_type_cmp(local_type, "telephoneNumber",
SLAPI_TYPE_CMP_SUBTYPE)) ||
@@ -4531,7 +4787,8 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entr
} else
{
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "windows_generate_update_mods: %s, %s : values are equal\n",
slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type);
+ "windows_generate_update_mods: %s, %s : values are
equal\n",
+ slapi_entry_get_dn_const(local_entry), local_type);
}
} else {
/* A dn-valued attribute : need to take special steps */
@@ -4702,7 +4959,22 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entr
/* Check if any attributes were deleted from the remote entry */
entry_first_deleted_attribute(remote_entry, &del_attr);
- local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ local_sdn = slapi_entry_get_sdn_const(local_entry);
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (slapi_sdn_scope_test(local_sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE)) {
+ local_subtree = sp->DSsubtree;
+ break;
+ }
+ }
+ } else {
+ local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ }
+ if (NULL == local_subtree) {
+ goto bail;
+ }
while (del_attr != NULL) {
Slapi_Attr *local_attr = NULL;
char *type = NULL;
@@ -4832,14 +5104,14 @@ bail:
static int
windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entry,Slapi_Entry *local_entry, int is_user)
{
- Slapi_Mods smods = {0};
+ Slapi_Mods smods = {0};
int retval = 0;
int do_modify = 0;
int ldap_op = 0;
int ldap_result_code = 0;
- slapi_mods_init (&smods, 0);
- retval =
windows_generate_update_mods(prp,local_entry,remote_entry,1,&smods,&do_modify);
+ slapi_mods_init (&smods, 0);
+ retval = windows_generate_update_mods(prp, remote_entry, local_entry, 1, &smods,
&do_modify);
/* Now perform the modify if we need to */
if (0 == retval && do_modify)
{
@@ -4943,7 +5215,7 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry
*remote_entry,
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "renaming entry
\"%s\" - "
"(newrdn: \"%s\", newsuperior: \"%s\"\n", newdn,
newrdn ? newrdn:"NULL", newsuperior ? newsuperior:"NULL");
- slapi_sdn_init_dn_byref(&newsuperior_sdn, newsuperior);
+ slapi_sdn_init_ndn_byref(&newsuperior_sdn, newsuperior);
slapi_rename_internal_set_pb_ext (pb,
slapi_entry_get_sdn(local_entry),
newrdn, &newsuperior_sdn, 1 /* delete old RDNS */,
@@ -5076,7 +5348,7 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e,
Slapi_DN* r
(void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */,
&entryattrs);
if (NULL == entryattrs)
{
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s:
windows_replay_update: Cannot convert entry to
LDAPMods.\n",agmt_get_long_name(prp->agmt));
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s:
windows_process_total_add: Cannot convert entry to
LDAPMods.\n",agmt_get_long_name(prp->agmt));
retval = CONN_LOCAL_ERROR;
}
else
@@ -5112,7 +5384,7 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e,
Slapi_DN* r
/* It's possible that the entry already exists in AD, in which case we fall back
to modify it */
if (retval)
{
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s:
windows_replay_update: Cannot replay add
operation.\n",agmt_get_long_name(prp->agmt));
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s:
windows_process_total_add: Cannot replay add
operation.\n",agmt_get_long_name(prp->agmt));
}
ldap_mods_free(entryattrs, 1);
entryattrs = NULL;
@@ -5183,7 +5455,7 @@ int windows_process_total_entry(Private_Repl_Protocol
*prp,Slapi_Entry *e)
if (retval || NULL == remote_dn)
{
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "%s: windows_replay_update: failed map dn for total update
dn=\"%s\"\n",
+ "%s: windows_process_total_entry: failed map dn for total update
dn=\"%s\"\n",
agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(local_dn));
goto error;
}
@@ -5198,19 +5470,27 @@ error:
}
static int
-windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid,
char ** attrs, Slapi_Entry **ret_entry, int tombstone, void * component_identity, int
is_global)
+windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp,
+ const char *uniqueid,
+ char ** attrs,
+ Slapi_Entry **ret_entry,
+ int tombstone,
+ void * component_identity,
+ int is_global)
{
- Slapi_Entry **entries = NULL;
- Slapi_PBlock *int_search_pb = NULL;
- int rc = 0;
+ Slapi_Entry **entries = NULL;
+ Slapi_PBlock *int_search_pb = NULL;
+ int rc = 0;
char *filter_string = NULL;
const Slapi_DN *local_subtree = NULL;
+ const Slapi_DN *local_subtree_sdn = NULL;
- *ret_entry = NULL;
+ *ret_entry = NULL;
if (is_global) { /* Search from the suffix (rename case) */
local_subtree = agmt_get_replarea(prp->agmt);
+ local_subtree_sdn = local_subtree;
} else {
- local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ local_subtree_sdn = windows_private_get_directory_treetop(prp->agmt);
}
/* Searching for tombstones can be expensive, so the caller needs to specify if
@@ -5222,7 +5502,7 @@ windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp,
const char *u
}
int_search_pb = slapi_pblock_new ();
- slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(local_subtree),
LDAP_SCOPE_SUBTREE, filter_string,
+ slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(local_subtree_sdn),
LDAP_SCOPE_SUBTREE, filter_string,
attrs ,
0 /* attrsonly */, NULL /* controls */,
NULL /* uniqueid */,
diff --git a/ldap/servers/plugins/replication/windows_tot_protocol.c
b/ldap/servers/plugins/replication/windows_tot_protocol.c
index 0791941..c81974b 100644
--- a/ldap/servers/plugins/replication/windows_tot_protocol.c
+++ b/ldap/servers/plugins/replication/windows_tot_protocol.c
@@ -85,6 +85,57 @@ static void get_result (int rc, void *cb_data);
static int send_entry (Slapi_Entry *e, void *callback_data);
static void windows_tot_delete(Private_Repl_Protocol **prp);
+static void
+_windows_tot_send_entry(const Repl_Agmt *ra, callback_data *cbp, const Slapi_DN
*local_sdn)
+{
+ Slapi_PBlock *pb = NULL;
+ char* dn = NULL;
+ int scope = LDAP_SCOPE_SUBTREE;
+ char *filter = NULL;
+ const char *userfilter = NULL;
+ char **attrs = NULL;
+ LDAPControl **server_controls = NULL;
+
+ if ((NULL == ra) || (NULL == cbp) || (NULL == local_sdn)) {
+ return;
+ }
+ dn = slapi_ch_strdup(slapi_sdn_get_dn(local_sdn));
+ userfilter = windows_private_get_directory_userfilter(ra);
+ if (userfilter) {
+ if ('(' == *userfilter) {
+ filter =
slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))%s)",
+ userfilter);
+ } else {
+ filter =
slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))(%s))",
+ userfilter);
+ }
+ } else {
+ filter = slapi_ch_strdup("(|(objectclass=ntuser)(objectclass=ntgroup))");
+ }
+
+ winsync_plugin_call_pre_ds_search_all_cb(ra, NULL, &dn, &scope, &filter,
+ &attrs, &server_controls);
+
+ pb = slapi_pblock_new ();
+ /* Perform a subtree search for any ntuser or ntgroup entries underneath the
+ * suffix defined in the sync agreement. */
+ slapi_search_internal_set_pb(pb, dn, scope, filter, attrs, 0, server_controls, NULL,
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
0);
+
+ slapi_search_internal_callback_pb(pb, cbp /* callback data */,
+ get_result /* result callback */,
+ send_entry /* entry callback */,
+ NULL /* referral callback */);
+
+ slapi_ch_free_string(&dn);
+ slapi_ch_free_string(&filter);
+ slapi_ch_array_free(attrs);
+ attrs = NULL;
+ ldap_controls_free(server_controls);
+ server_controls = NULL;
+ slapi_pblock_destroy (pb);
+}
+
/*
* Completely refresh a replica. The basic protocol interaction goes
* like this:
@@ -98,16 +149,10 @@ windows_tot_run(Private_Repl_Protocol *prp)
{
int rc;
callback_data cb_data;
- Slapi_PBlock *pb = NULL;
- char* dn = NULL;
RUV *ruv = NULL;
RUV *starting_ruv = NULL;
Replica *replica = NULL;
Object *local_ruv_obj = NULL;
- int scope = LDAP_SCOPE_SUBTREE;
- char *filter =
slapi_ch_strdup("(|(objectclass=ntuser)(objectclass=ntgroup))");
- char **attrs = NULL;
- LDAPControl **server_controls = NULL;
int one_way;
LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_tot_run\n" );
@@ -160,9 +205,9 @@ windows_tot_run(Private_Repl_Protocol *prp)
/* call begin total update callback */
winsync_plugin_call_begin_update_cb(prp->agmt,
- windows_private_get_directory_subtree(prp->agmt),
- windows_private_get_windows_subtree(prp->agmt),
- 1 /* is_total == TRUE */);
+
windows_private_get_directory_treetop(prp->agmt),
+ windows_private_get_windows_treetop(prp->agmt),
+ 1 /* is_total == TRUE */);
if ((one_way == ONE_WAY_SYNC_DISABLED) || (one_way == ONE_WAY_SYNC_FROM_AD)) {
/* get everything */
@@ -178,10 +223,10 @@ windows_tot_run(Private_Repl_Protocol *prp)
* the incremental sync protocol ( send_updates() ). We will
* use this value for setting the consumer RUV if the total
* update succeeds. */
- replica = object_get_data(prp->replica_object);
- local_ruv_obj = replica_get_ruv (replica);
- starting_ruv = ruv_dup((RUV*) object_get_data ( local_ruv_obj ));
- object_release (local_ruv_obj);
+ replica = object_get_data(prp->replica_object);
+ local_ruv_obj = replica_get_ruv (replica);
+ starting_ruv = ruv_dup((RUV*)object_get_data ( local_ruv_obj ));
+ object_release (local_ruv_obj);
/* Set up the callback data. */
cb_data.prp = prp;
@@ -190,44 +235,30 @@ windows_tot_run(Private_Repl_Protocol *prp)
cb_data.sleep_on_busy = 0UL;
cb_data.last_busy = current_time ();
- /* Don't send anything if one-way is set. */
+ /* Don't send anything if one-way (ONE_WAY_SYNC_FROM_AD) is set. */
if ((one_way == ONE_WAY_SYNC_DISABLED) || (one_way == ONE_WAY_SYNC_TO_AD)) {
/* send everything */
- dn = slapi_ch_strdup(slapi_sdn_get_dn(
windows_private_get_directory_subtree(prp->agmt)));
-
- winsync_plugin_call_pre_ds_search_all_cb(prp->agmt, NULL, &dn, &scope,
&filter,
- &attrs, &server_controls);
-
- pb = slapi_pblock_new ();
- /* Perform a subtree search for any ntuser or ntgroup entries underneath the
- * suffix defined in the sync agreement. */
- slapi_search_internal_set_pb (pb, dn, scope, filter, attrs, 0, server_controls, NULL,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
-
- slapi_search_internal_callback_pb (pb, &cb_data /* callback data */,
- get_result /* result callback */,
- send_entry /* entry callback */,
- NULL /* referral callback*/);
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ _windows_tot_send_entry(prp->agmt, &cb_data, sp->DSsubtree);
+ }
+ } else {
+ _windows_tot_send_entry(prp->agmt, &cb_data,
windows_private_get_directory_subtree(prp->agmt));
+ }
}
-
- slapi_ch_free_string(&dn);
- slapi_ch_free_string(&filter);
- slapi_ch_array_free(attrs);
- attrs = NULL;
- ldap_controls_free(server_controls);
- server_controls = NULL;
-
- slapi_pblock_destroy (pb);
rc = cb_data.rc;
windows_release_replica(prp);
- if (rc != LDAP_SUCCESS)
- {
- slapi_log_error (SLAPI_LOG_REPL, windows_repl_plugin_name, "%s:
windows_tot_run: "
- "failed to obtain data to send to the consumer; LDAP error
- %d\n",
- agmt_get_long_name(prp->agmt), rc);
+ if (rc != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "%s: windows_tot_run:
"
+ "failed to obtain data to send to the consumer; LDAP error -
%d\n",
+ agmt_get_long_name(prp->agmt), rc);
agmt_set_last_init_status(prp->agmt, rc, 0, "Total update aborted");
- } else {
+ } else {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "Finished total update
of replica "
"\"%s\". Sent %lu entries.\n",
agmt_get_long_name(prp->agmt), cb_data.num_entries);
agmt_set_last_init_status(prp->agmt, 0, 0, "Total update succeeded");
@@ -256,9 +287,9 @@ windows_tot_run(Private_Repl_Protocol *prp)
/* call end total update callback */
winsync_plugin_call_end_update_cb(prp->agmt,
- windows_private_get_directory_subtree(prp->agmt),
- windows_private_get_windows_subtree(prp->agmt),
- 1 /* is_total == TRUE */);
+ windows_private_get_directory_treetop(prp->agmt),
+ windows_private_get_windows_treetop(prp->agmt),
+ 1 /* is_total == TRUE */);
done:
if (starting_ruv)
diff --git a/ldap/servers/plugins/replication/windowsrepl.h
b/ldap/servers/plugins/replication/windowsrepl.h
index 9279179..f9c747c 100644
--- a/ldap/servers/plugins/replication/windowsrepl.h
+++ b/ldap/servers/plugins/replication/windowsrepl.h
@@ -43,6 +43,11 @@
/* windows_private.c */
typedef struct windowsprivate Dirsync_Private;
+typedef struct subtreepair {
+ Slapi_DN *ADsubtree;
+ Slapi_DN *DSsubtree;
+} subtreePair;
+
Dirsync_Private* windows_private_new();
void windows_private_set_windows_subtree (const Repl_Agmt *ra,Slapi_DN* sdn );
const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra);
@@ -68,6 +73,7 @@ void windows_private_set_isnt4(const Repl_Agmt *ra, int isit);
int windows_private_get_iswin2k3(const Repl_Agmt *ra);
void windows_private_set_iswin2k3(const Repl_Agmt *ra, int isit);
Slapi_Filter* windows_private_get_directory_filter(const Repl_Agmt *ra);
+Slapi_Filter* windows_private_get_windows_filter(const Repl_Agmt *ra);
Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra);
const char* windows_private_get_purl(const Repl_Agmt *ra);
/*
@@ -94,6 +100,18 @@ void windows_private_set_curr_entry(const Repl_Agmt *ra, Slapi_Entry
*e);
char **windows_private_get_range_attrs(const Repl_Agmt *ra);
void windows_private_set_range_attrs(const Repl_Agmt *ra, char **attrs);
+void windows_private_set_directory_userfilter(const Repl_Agmt *ra, char *filter);
+void windows_private_set_windows_userfilter(const Repl_Agmt *ra, char *filter);
+const char* windows_private_get_directory_userfilter(const Repl_Agmt *ra);
+const char* windows_private_get_windows_userfilter(const Repl_Agmt *ra);
+
+const subtreePair* windows_private_get_subtreepairs(const Repl_Agmt *ra);
+void windows_private_set_subtreepairs(const Repl_Agmt *ra, char **parray);
+const Slapi_DN* windows_private_get_windows_treetop(const Repl_Agmt *ra);
+void windows_private_set_windows_treetop(const Repl_Agmt *ra, char *treetop);
+const Slapi_DN* windows_private_get_directory_treetop(const Repl_Agmt *ra);
+void windows_private_set_directory_treetop(const Repl_Agmt *ra, char *treetop);
+
/* in windows_connection.c */
ConnResult windows_conn_connect(Repl_Connection *conn);
void windows_conn_disconnect(Repl_Connection *conn);
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 9ed8091..8328ed5 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -2011,6 +2011,17 @@ slapi_sdn_new_ndn_byref(const char *ndn)
return sdn;
}
+/* use when dn is already fully normalized */
+Slapi_DN *
+slapi_sdn_new_ndn_passin(const char *ndn)
+{
+ Slapi_DN *sdn = slapi_sdn_new();
+ slapi_sdn_set_ndn_passin(sdn, ndn);
+ SDN_DUMP( sdn, "slapi_sdn_new_ndn_passin");
+ return sdn;
+}
+
+
/* use when dn is already normalized */
Slapi_DN *
slapi_sdn_new_normdn_byref(const char *normdn)
@@ -2154,6 +2165,20 @@ slapi_sdn_set_ndn_byref(Slapi_DN *sdn, const char *ndn)
return sdn;
}
+Slapi_DN *
+slapi_sdn_set_ndn_passin(Slapi_DN *sdn, const char *ndn)
+{
+ slapi_sdn_done(sdn);
+ sdn->flag = slapi_setbit_uchar(sdn->flag, FLAG_NDN);
+ sdn->ndn = ndn;
+ if (ndn == NULL) {
+ sdn->ndn_len = 0;
+ } else {
+ sdn->ndn_len = strlen(ndn);
+ }
+ return sdn;
+}
+
/*
* Set the RDN of the DN.
*/
@@ -3017,3 +3042,71 @@ ndn_cache_get_stats(PRUint64 *hits, PRUint64 *tries, size_t *size,
size_t *max_s
slapi_rwlock_unlock(ndn_cache_lock);
}
+/* Common ancestor sdn is allocated.
+ * caller is responsible to free it */
+Slapi_DN *
+slapi_sdn_common_ancestor(Slapi_DN *dn1, Slapi_DN *dn2)
+{
+ const char *dn1str = NULL;
+ const char *dn2str = NULL;
+ char **dns1 = NULL;
+ char **dns2 = NULL;
+ char **dn1p, **dn2p;
+ char **dn1end;
+ int dn1len = 0;
+ int dn2len = 0;
+ char *common = NULL;
+ char *cp = 0;
+ if ((NULL == dn1) || (NULL == dn2)) {
+ return NULL;
+ }
+ dn1str = slapi_sdn_get_ndn(dn1);
+ dn2str = slapi_sdn_get_ndn(dn2);
+ if (0 == strcmp(dn1str, dn2str)) {
+ /* identical */
+ return slapi_sdn_dup(dn1);
+ }
+ dn1len = strlen(dn1str);
+ dn2len = strlen(dn2str);
+ if (dn1len > dn2len) {
+ if (slapi_sdn_isparent(dn2, dn1)) {
+ /* dn2 is dn1's parent */
+ return slapi_sdn_dup(dn2);
+ }
+ } else if (dn1len < dn2len) {
+ if (slapi_sdn_isparent(dn1, dn2)) {
+ /* dn1 is dn2's parent */
+ return slapi_sdn_dup(dn1);
+ }
+ }
+ dns1 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(dn1), 0);
+ dns2 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(dn2), 0);
+ for (dn1p = dns1; dn1p && *dn1p; dn1p++) ;
+ for (dn2p = dns2; dn2p && *dn2p; dn2p++) ;
+ dn1end = dn1p;
+ while (--dn1p && --dn2p && (dn1p >= dns1) && (dn2p >=
dns2)) {
+ if (strcmp(*dn1p, *dn2p)) {
+ break;
+ }
+ }
+ if (dn1end == ++dn1p) {
+ /* No common ancestor */
+ charray_free(dns1);
+ charray_free(dns2);
+ return NULL;
+ }
+ dn1len += 1;
+ cp = common = slapi_ch_malloc(dn1len);
+ *common = '\0';
+ do {
+ PR_snprintf(cp, dn1len, "%s,", *dn1p);
+ cp += strlen(*dn1p) + 1/*,*/;
+ } while (++dn1p < dn1end);
+ dn1len = strlen(common);
+ if (',' == *(common + dn1len - 1)) {
+ *(common + dn1len - 1) = '\0';
+ }
+ charray_free(dns1);
+ charray_free(dns2);
+ return slapi_sdn_new_ndn_passin(common);
+}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 233dbe9..97fb81f 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -2262,6 +2262,7 @@ Slapi_DN *slapi_sdn_new_dn_byval(const char *dn);
* \warning The \c ndn value is copied by the function itself. The caller
* is still responsible for the memory used by \c ndn.
* \see slapi_sdn_new_ndn_byref()
+ * \see slapi_sdn_new_ndn_passin()
* \see slapi_sdn_free()
* \see slapi_sdn_copy()
* \see slapi_sdn_done()
@@ -2301,6 +2302,7 @@ Slapi_DN *slapi_sdn_new_dn_byref(const char *dn);
* memory should not be freed until the returned \c Slapi_DN has been
* disposed of or reinitialized.
* \see slapi_sdn_new_ndn_byval()
+ * \see slapi_sdn_new_ndn_passin()
* \see slapi_sdn_free()
* \see slapi_sdn_copy()
* \see slapi_sdn_done()
@@ -2308,6 +2310,23 @@ Slapi_DN *slapi_sdn_new_dn_byref(const char *dn);
Slapi_DN *slapi_sdn_new_ndn_byref(const char *ndn);
/**
+ * Creates a new \c Slapi_DN structure and intializes it's normalized and case
ignored DN to a requested value.
+ *
+ * The normalized and case ignored DN of the new structure will point to the same string
pointed to by \c ndn.
+ * Ownership of the memory pointed to by \c ndn is tranferred to the Slapi_DN.
+ *
+ * \param ndn The normalized and case ignored DN value to be set in the new \c Slapi_DN
structure.
+ * \return A pointer to the newly allocated \c Slapi_DN structure with
+ * the normalized and case ignored DN value set to the content of \c ndn.
+ * \see slapi_sdn_new_ndn_byval()
+ * \see slapi_sdn_new_ndn_byref()
+ * \see slapi_sdn_free()
+ * \see slapi_sdn_copy()
+ * \see slapi_sdn_done()
+ */
+Slapi_DN *slapi_sdn_new_ndn_passin(const char *ndn);
+
+/**
* Creates a new \c Slapi_DN structure and intializes it's DN to a requested value.
*
* The DN of the new structure will point to the same string pointed to by \c dn.
@@ -2494,6 +2513,7 @@ Slapi_DN *slapi_sdn_set_normdn_byval(Slapi_DN *sdn, const char
*dn);
* \warning The \c ndn value is copied by the function itself. The caller
* is still responsible for the memory used by \c ndn.
* \see slapi_sdn_set_ndn_byref()
+ * \see slapi_sdn_set_ndn_passin()
*/
Slapi_DN *slapi_sdn_set_ndn_byval(Slapi_DN *sdn, const char *ndn);
@@ -2510,10 +2530,26 @@ Slapi_DN *slapi_sdn_set_ndn_byval(Slapi_DN *sdn, const char
*ndn);
* memory should not be freed until the returned \c Slapi_DN has been
* disposed of or reinitialized.
* \see slapi_sdn_set_ndn_byval()
+ * \see slapi_sdn_set_ndn_passin()
*/
Slapi_DN *slapi_sdn_set_ndn_byref(Slapi_DN *sdn, const char *ndn);
/**
+ * Sets a normalized DN value in a \c Slapi_DN structure.
+ *
+ * The normalized DN of the structure will point to the same string pointed to
+ * by \c ndn.
+ * Ownership of the memory pointed to by \c ndn is tranferred to the Slapi_DN.
+ *
+ * \param sdn The target \c Slapi_DN structure.
+ * \param ndn The normalized DN value to be set in \c sdn.
+ * \return A pointer to the \c Slapi_DN structure containing the new normalized DN
value.
+ * \see slapi_sdn_set_ndn_byval()
+ * \see slapi_sdn_set_ndn_byref()
+ */
+Slapi_DN *slapi_sdn_set_ndn_passin(Slapi_DN *sdn, const char *ndn);
+
+/**
* Clears the contents of a Slapi_DN structure.
*
* Both the DN and the normalized DN are freed if the \c Slapi_DN structure
@@ -3631,6 +3667,15 @@ int slapi_rdn2typeval( char *rdn, char **type, struct berval *bv
);
*/
char *slapi_dn_plus_rdn(const char *dn, const char *rdn);
+/**
+ * Create an Slapi_DN that is a common ancestor of given 2 Slapi_DN's
+ *
+ * \param dn1 The first DN
+ * \param dn2 the second DN
+ * \return A pointer to the new Slapi_DN that is a common ancestor of dn1 and dn2
+ * \warning The caller must free the returnd Slapi_DN
+ */
+Slapi_DN *slapi_sdn_common_ancestor(Slapi_DN *dn1, Slapi_DN *dn2);
/*
* thread safe random functions
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index fb92867..1991040 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -604,7 +604,7 @@ int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod
**iattrs)
if (rc != LDAP_SUCCESS)
{
LDAPDebug2Args(LDAP_DEBUG_ANY,
- "slapi_add_internal: add_values for type %s failed (rc:
%d)\n",
+ "slapi_mods2entry: add_values for type %s failed (rc: %d)\n",
normtype, rc );
slapi_entry_free (*e);
*e = NULL;