summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldap/servers/plugins/replication/windows_connection.c132
-rw-r--r--ldap/servers/plugins/replication/windows_private.c415
-rw-r--r--ldap/servers/plugins/replication/windows_protocol_util.c136
-rw-r--r--ldap/servers/plugins/replication/windows_tot_protocol.c21
-rw-r--r--ldap/servers/plugins/replication/windowsrepl.h98
-rw-r--r--ldap/servers/plugins/replication/winsync-plugin.h534
-rw-r--r--ldap/servers/slapd/charray.c5
-rw-r--r--ldap/servers/slapd/control.c36
-rw-r--r--ldap/servers/slapd/slapi-plugin.h25
9 files changed, 1327 insertions, 75 deletions
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index 2c54c64b..32787c4c 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -512,15 +512,17 @@ windows_perform_operation(Repl_Connection *conn, int optype, const char *dn,
/* Copied from the chaining backend*/
static Slapi_Entry *
-windows_LDAPMessage2Entry(LDAP * ld, LDAPMessage * msg, int attrsonly) {
+windows_LDAPMessage2Entry(Repl_Connection *conn, LDAPMessage * msg, int attrsonly) {
- Slapi_Entry *e = slapi_entry_alloc();
+ Slapi_Entry *rawentry = NULL;
+ Slapi_Entry *e = NULL;
char *a = NULL;
BerElement * ber = NULL;
+ LDAP *ld = conn->ld;
+
+ windows_private_set_raw_entry(conn->agmt, NULL); /* clear it first */
- if ( e == NULL ) return NULL;
if (msg == NULL) {
- slapi_entry_free(e);
return NULL;
}
@@ -529,10 +531,21 @@ windows_LDAPMessage2Entry(LDAP * ld, LDAPMessage * msg, int attrsonly) {
* attribute type and values ARE allocated
*/
+ e = slapi_entry_alloc();
+ if ( e == NULL ) return NULL;
slapi_entry_set_dn( e, ldap_get_dn( ld, msg ) );
+ rawentry = slapi_entry_alloc();
+ if ( rawentry == NULL ) {
+ slapi_entry_free(e);
+ return NULL;
+ }
+ slapi_entry_set_dn( rawentry, slapi_ch_strdup(slapi_entry_get_dn(e)) );
for ( a = ldap_first_attribute( ld, msg, &ber ); a!=NULL; a=ldap_next_attribute( ld, msg, ber ) )
{
+ struct berval ** aVal = ldap_get_values_len( ld, msg, a);
+ slapi_entry_add_values(rawentry, a, aVal);
+
if (0 == strcasecmp(a,"dnsRecord") || 0 == strcasecmp(a,"dnsproperty") ||
0 == strcasecmp(a,"dscorepropagationdata"))
{
@@ -548,10 +561,8 @@ windows_LDAPMessage2Entry(LDAP * ld, LDAPMessage * msg, int attrsonly) {
if (attrsonly)
{
slapi_entry_add_value(e, a, (Slapi_Value *)NULL);
- ldap_memfree(a);
} else
{
- struct berval ** aVal = ldap_get_values_len( ld, msg, a);
char *type_to_use = NULL;
/* Work around the fact that we alias street and streetaddress, while Microsoft do not */
if (0 == strcasecmp(a,"streetaddress"))
@@ -575,15 +586,18 @@ windows_LDAPMessage2Entry(LDAP * ld, LDAPMessage * msg, int attrsonly) {
slapi_entry_add_values( e, type_to_use, aVal);
}
- ldap_memfree(a);
- ldap_value_free_len(aVal);
}
}
+ ldap_memfree(a);
+ ldap_value_free_len(aVal);
}
if ( NULL != ber )
{
ldap_ber_free( ber, 0 );
}
+
+ windows_private_set_raw_entry(conn->agmt, rawentry); /* windows private now owns rawentry */
+
return e;
}
@@ -599,11 +613,6 @@ ConnResult
windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter, Slapi_Entry **entry, LDAPControl **serverctrls)
{
ConnResult return_value = 0;
- int ldap_rc = 0;
- LDAPMessage *res = NULL;
- int nummessages = 0;
- int numentries = 0;
- int numreferences = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_search_entry\n", 0, 0, 0 );
@@ -611,15 +620,41 @@ windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter,
if (windows_conn_connected(conn))
{
- ldap_rc = ldap_search_ext_s(conn->ld, searchbase, LDAP_SCOPE_SUBTREE,
- filter, NULL, 0 /* attrsonly */,
- serverctrls , NULL /* client controls */,
+ int ldap_rc = 0;
+ LDAPMessage *res = NULL;
+ char *searchbase_copy = slapi_ch_strdup(searchbase);
+ int scope = LDAP_SCOPE_SUBTREE;
+ char *filter_copy = slapi_ch_strdup(filter);
+ char **attrs = NULL;
+ LDAPControl **serverctrls_copy = NULL;
+
+ slapi_add_controls(&serverctrls_copy, serverctrls, 1 /* make a copy we can free */);
+
+ LDAPDebug( LDAP_DEBUG_REPL, "Calling windows entry search request plugin\n", 0, 0, 0 );
+
+ winsync_plugin_call_pre_ad_search_cb(conn->agmt, NULL, &searchbase_copy, &scope, &filter_copy,
+ &attrs, &serverctrls_copy);
+
+ ldap_rc = ldap_search_ext_s(conn->ld, searchbase_copy, scope,
+ filter_copy, attrs, 0 /* attrsonly */,
+ serverctrls_copy , NULL /* client controls */,
&conn->timeout, 0 /* sizelimit */, &res);
+
+ slapi_ch_free_string(&searchbase_copy);
+ slapi_ch_free_string(&filter_copy);
+ slapi_ch_array_free(attrs);
+ attrs = NULL;
+ ldap_controls_free(serverctrls_copy);
+ serverctrls_copy = NULL;
+
if (LDAP_SUCCESS == ldap_rc)
{
LDAPMessage *message = ldap_first_entry(conn->ld, res);
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
+ int nummessages = 0;
+ int numentries = 0;
+ int numreferences = 0;
nummessages = ldap_count_messages(conn->ld, res);
numentries = ldap_count_entries(conn->ld, res);
numreferences = ldap_count_references(conn->ld, res);
@@ -629,7 +664,7 @@ windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter,
if (NULL != entry)
{
- *entry = windows_LDAPMessage2Entry(conn->ld,message,0);
+ *entry = windows_LDAPMessage2Entry(conn,message,0);
}
/* See if there are any more entries : if so then that's an error
* but we still need to get them to avoid gumming up the connection
@@ -664,42 +699,46 @@ windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter,
ConnResult
send_dirsync_search(Repl_Connection *conn)
{
- int rc;
ConnResult return_value;
- LDAPControl *server_controls[2];
- int msgid;
-
- const char *op_string = NULL;
-
- const char* old_dn = NULL;
- char* dn = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> send_dirsync_search\n", 0, 0, 0 );
- /* need to strip the dn down to dc= */
- old_dn = slapi_sdn_get_ndn( windows_private_get_windows_subtree(conn->agmt) );
- dn = strstr(old_dn, "dc=");
-
if (windows_conn_connected(conn))
{
+ const char *op_string = NULL;
+ int rc;
+ int scope = LDAP_SCOPE_SUBTREE;
+ char *filter = slapi_ch_strdup("(objectclass=*)");
+ 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) );
+ char *dn = slapi_ch_strdup(strstr(old_dn, "dc="));
+
if (conn->supports_dirsync == 0)
{
- server_controls[0] = NULL; /* unsupported */
+ /* unsupported */
} else
{
- server_controls[0] = windows_private_dirsync_control(conn->agmt);
+ slapi_add_control_ext(&server_controls,
+ windows_private_dirsync_control(conn->agmt),
+ 0 /* no copy - passin */);
}
- server_controls[1] = NULL;
conn->last_operation = CONN_SEARCH;
conn->status = STATUS_SEARCHING;
op_string = "search";
+ LDAPDebug( LDAP_DEBUG_REPL, "Calling dirsync search request plugin\n", 0, 0, 0 );
+
+ winsync_plugin_call_dirsync_search_params_cb(conn->agmt, old_dn, &dn, &scope, &filter,
+ &attrs, &server_controls);
+
LDAPDebug( LDAP_DEBUG_REPL, "Sending dirsync search request\n", 0, 0, 0 );
- rc = ldap_search_ext( conn->ld, dn, LDAP_SCOPE_SUBTREE, "(objectclass=*)", /* filter */
- NULL /*attrs */, PR_FALSE, server_controls, NULL, /* ClientControls */
- 0,0, &msgid);
+ rc = ldap_search_ext( conn->ld, dn, scope, filter, attrs, PR_FALSE, server_controls,
+ NULL /* ClientControls */, 0,0, &msgid);
if (LDAP_SUCCESS == rc)
{
@@ -723,11 +762,13 @@ send_dirsync_search(Repl_Connection *conn)
return_value = CONN_OPERATION_FAILED;
}
}
- if (server_controls[0])
- {
- ldap_control_free(server_controls[0]);
- }
-
+ /* cleanup */
+ 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;
}
else
{
@@ -852,7 +893,7 @@ Slapi_Entry * windows_conn_get_search_result(Repl_Connection *conn)
{
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"received entry from dirsync: %s\n", dn);
lm = ldap_first_entry( conn->ld, res );
- e = windows_LDAPMessage2Entry(conn->ld,lm,0);
+ e = windows_LDAPMessage2Entry(conn,lm,0);
ldap_memfree(dn);
}
}
@@ -1424,6 +1465,13 @@ windows_conn_replica_supports_dirsync(Repl_Connection *conn)
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_replica_supports_dirsync\n", 0, 0, 0 );
+#ifdef WINSYNC_TEST
+ /* used to fake out dirsync to think it's talking to a real ad when in fact
+ it's just talking to another directory server */
+ conn->supports_dirsync = 1;
+ return CONN_SUPPORTS_DIRSYNC;
+#endif
+
if (windows_conn_connected(conn))
{
if (conn->supports_dirsync == -1) {
@@ -1882,7 +1930,7 @@ repl5_stop_debug_timeout(Slapi_Eq_Context eqctx, int *setlevel)
LDAPDebug( LDAP_DEBUG_TRACE, "=> repl5_stop_debug_timeout\n", 0, 0, 0 );
if (eqctx && !*setlevel) {
- int found = slapi_eq_cancel(eqctx);
+ (void)slapi_eq_cancel(eqctx);
}
if (s_debug_timeout && s_debug_level && *setlevel) {
diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c
index 5baa7ce2..d6176b53 100644
--- a/ldap/servers/plugins/replication/windows_private.c
+++ b/ldap/servers/plugins/replication/windows_private.c
@@ -70,8 +70,12 @@ struct windowsprivate {
* 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 *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 */
+ void *api_cookie; /* private data used by api callbacks */
};
+static void windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain);
+
static int
true_value_from_string(char *val)
{
@@ -99,7 +103,6 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
windows_private_set_windows_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
}
retval = 1;
- slapi_ch_free((void**)&tmpstr);
}
if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7DirectoryReplicaArea))
{
@@ -109,7 +112,6 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
windows_private_set_directory_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
}
retval = 1;
- slapi_ch_free((void**)&tmpstr);
}
if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7CreateNewUsers))
{
@@ -173,6 +175,8 @@ windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e)
agmt_set_priv(ra,windows_private_new());
windows_parse_config_entry(ra,NULL,e);
+
+ windows_plugin_init(ra);
}
const char* windows_private_get_purl(const Repl_Agmt *ra)
@@ -214,6 +218,9 @@ void windows_agreement_delete(Repl_Agmt *ra)
slapi_filter_free(dp->directory_filter, 1);
slapi_filter_free(dp->deleted_filter, 1);
+ slapi_entry_free(dp->raw_entry);
+ dp->raw_entry = NULL;
+ dp->api_cookie = NULL;
slapi_ch_free((void **)dp);
LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_delete\n", 0, 0, 0 );
@@ -401,7 +408,7 @@ const Slapi_DN* windows_private_get_directory_subtree (const Repl_Agmt *ra)
}
/* Takes a copy of the sdn passed in */
-void windows_private_set_windows_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn )
+void windows_private_set_windows_subtree (const Repl_Agmt *ra,Slapi_DN* sdn )
{
Dirsync_Private *dp;
@@ -413,14 +420,15 @@ void windows_private_set_windows_subtree (const Repl_Agmt *ra,const Slapi_DN* sd
dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
-
- dp->windows_subtree = slapi_sdn_dup(sdn);
+
+ slapi_sdn_free(&dp->windows_subtree);
+ dp->windows_subtree = sdn;
LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_replarea\n", 0, 0, 0 );
}
/* Takes a copy of the sdn passed in */
-void windows_private_set_directory_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn )
+void windows_private_set_directory_subtree (const Repl_Agmt *ra,Slapi_DN* sdn )
{
Dirsync_Private *dp;
@@ -433,7 +441,8 @@ void windows_private_set_directory_subtree (const Repl_Agmt *ra,const Slapi_DN*
dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
- dp->directory_subtree = slapi_sdn_dup(sdn);
+ slapi_sdn_free(&dp->directory_subtree);
+ dp->directory_subtree = sdn;
LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_directory_replarea\n", 0, 0, 0 );
}
@@ -516,6 +525,7 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
LDAPControl *control = NULL;
BerElement *ber;
Dirsync_Private *dp;
+ char iscritical = PR_TRUE;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_dirsync_control\n", 0, 0, 0 );
@@ -527,7 +537,10 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
ber_printf( ber, "{iio}", dp->dirsync_flags, dp->dirsync_maxattributecount, dp->dirsync_cookie, dp->dirsync_cookie_len );
- slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, PR_TRUE, &control);
+#ifdef WINSYNC_TEST
+ iscritical = PR_FALSE;
+#endif
+ slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, iscritical, &control);
ber_free(ber,1);
@@ -787,3 +800,389 @@ int windows_private_load_dirsync_cookie(const Repl_Agmt *ra)
return rc;
}
+/* get returns a pointer to the structure - do not free */
+Slapi_Entry *windows_private_get_raw_entry(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_raw_entry\n", 0, 0, 0 );
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_raw_entry\n", 0, 0, 0 );
+
+ return dp->raw_entry;
+}
+
+/* this is passin - windows_private owns the pointer, not a copy */
+void windows_private_set_raw_entry(const Repl_Agmt *ra, Slapi_Entry *e)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_raw_entry\n", 0, 0, 0 );
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_entry_free(dp->raw_entry);
+ dp->raw_entry = e;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_raw_entry\n", 0, 0, 0 );
+}
+
+void *windows_private_get_api_cookie(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_api_cookie\n", 0, 0, 0 );
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_api_cookie\n", 0, 0, 0 );
+
+ return dp->api_cookie;
+}
+
+void windows_private_set_api_cookie(Repl_Agmt *ra, void *api_cookie)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_api_cookie\n", 0, 0, 0 );
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+ dp->api_cookie = api_cookie;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_api_cookie\n", 0, 0, 0 );
+}
+
+/* an array of function pointers */
+static void **_WinSyncAPI = NULL;
+
+void
+windows_plugin_init(Repl_Agmt *ra)
+{
+ void *cookie = NULL;
+ winsync_plugin_init_cb initfunc = NULL;
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "--> windows_plugin_init_start -- begin\n",0,0,0);
+
+ /* if the function pointer array is null, get the functions - we will
+ call init once per replication agreement, but will only grab the
+ api once */
+ if((NULL == _WinSyncAPI) &&
+ (slapi_apib_get_interface(WINSYNC_v1_0_GUID, &_WinSyncAPI) ||
+ (NULL == _WinSyncAPI)))
+ {
+ LDAPDebug( LDAP_DEBUG_PLUGIN,
+ "<-- windows_plugin_init_start -- no windows plugin API registered for GUID [%s] -- end\n",
+ WINSYNC_v1_0_GUID,0,0);
+ return;
+ }
+
+ initfunc = (winsync_plugin_init_cb)_WinSyncAPI[WINSYNC_PLUGIN_INIT_CB];
+ if (initfunc) {
+ cookie = (*initfunc)(windows_private_get_directory_subtree(ra),
+ windows_private_get_windows_subtree(ra));
+ }
+ windows_private_set_api_cookie(ra, cookie);
+
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "<-- windows_plugin_init_start -- end\n",0,0,0);
+ return;
+}
+
+void
+winsync_plugin_call_dirsync_search_params_cb(const Repl_Agmt *ra, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ winsync_search_params_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_DIRSYNC_SEARCH_CB]) ?
+ (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_DIRSYNC_SEARCH_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), agmt_dn, base, scope, filter,
+ attrs, serverctrls);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ad_search_cb(const Repl_Agmt *ra, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ winsync_search_params_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_SEARCH_CB]) ?
+ (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_SEARCH_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), agmt_dn, base, scope, filter,
+ attrs, serverctrls);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ds_search_entry_cb(const Repl_Agmt *ra, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ winsync_search_params_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ENTRY_CB]) ?
+ (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ENTRY_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), agmt_dn, base, scope, filter,
+ attrs, serverctrls);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ds_search_all_cb(const Repl_Agmt *ra, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ winsync_search_params_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ALL_CB]) ?
+ (winsync_search_params_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_SEARCH_ALL_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), agmt_dn, base, scope, filter,
+ attrs, serverctrls);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ad_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ winsync_pre_mod_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_CB]) ?
+ (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ ds_entry, smods, do_modify);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ad_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ winsync_pre_mod_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_CB]) ?
+ (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ ds_entry, smods, do_modify);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ds_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ winsync_pre_mod_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_USER_CB]) ?
+ (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_USER_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ ds_entry, smods, do_modify);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ds_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ winsync_pre_mod_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_GROUP_CB]) ?
+ (winsync_pre_mod_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_MOD_GROUP_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ ds_entry, smods, do_modify);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ds_add_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry)
+{
+ winsync_pre_add_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_USER_CB]) ?
+ (winsync_pre_add_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_USER_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ ds_entry);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ds_add_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry)
+{
+ winsync_pre_add_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_GROUP_CB]) ?
+ (winsync_pre_add_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_DS_ADD_GROUP_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ ds_entry);
+
+ return;
+}
+
+void
+winsync_plugin_call_get_new_ds_user_dn_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, char **new_dn_string,
+ const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix)
+{
+ winsync_get_new_dn_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_USER_DN_CB]) ?
+ (winsync_get_new_dn_cb)_WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_USER_DN_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ new_dn_string, ds_suffix, ad_suffix);
+
+ return;
+}
+
+void
+winsync_plugin_call_get_new_ds_group_dn_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, char **new_dn_string,
+ const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix)
+{
+ winsync_get_new_dn_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_GROUP_DN_CB]) ?
+ (winsync_get_new_dn_cb)_WinSyncAPI[WINSYNC_PLUGIN_GET_NEW_DS_GROUP_DN_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, ad_entry,
+ new_dn_string, ds_suffix, ad_suffix);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ad_mod_user_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ const Slapi_DN *local_dn, LDAPMod * const *origmods,
+ Slapi_DN *remote_dn, LDAPMod ***modstosend)
+{
+ winsync_pre_ad_mod_mods_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_MODS_CB]) ?
+ (winsync_pre_ad_mod_mods_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_USER_MODS_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, local_dn,
+ origmods, remote_dn, modstosend);
+
+ return;
+}
+
+void
+winsync_plugin_call_pre_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry,
+ const Slapi_DN *local_dn, LDAPMod * const *origmods,
+ Slapi_DN *remote_dn, LDAPMod ***modstosend)
+{
+ winsync_pre_ad_mod_mods_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_MODS_CB]) ?
+ (winsync_pre_ad_mod_mods_cb)_WinSyncAPI[WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_MODS_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return;
+ }
+
+ (*thefunc)(windows_private_get_api_cookie(ra), rawentry, local_dn,
+ origmods, remote_dn, modstosend);
+
+ return;
+}
+
+int
+winsync_plugin_call_can_add_entry_to_ad_cb(const Repl_Agmt *ra, const Slapi_Entry *local_entry,
+ const Slapi_DN *remote_dn)
+{
+ winsync_can_add_to_ad_cb thefunc =
+ (_WinSyncAPI && _WinSyncAPI[WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB]) ?
+ (winsync_can_add_to_ad_cb)_WinSyncAPI[WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB] :
+ NULL;
+
+ if (!thefunc) {
+ return 1; /* default is entry can be added to AD */
+ }
+
+ return (*thefunc)(windows_private_get_api_cookie(ra), local_entry, remote_dn);
+}
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index 8088d622..b893aac2 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -668,6 +668,7 @@ windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv, int check_ruv)
return_value = ACQUIRE_FATAL_ERROR;
}
slapi_sdn_free(&replarea_sdn);
+ csn_free(&current_csn);
}
}
@@ -1004,7 +1005,6 @@ process_replay_add(Private_Repl_Protocol *prp, slapi_operation_parameters *op, S
}
if (cn_string) {
- char *rdnstr = NULL;
char *container_str = NULL;
const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
@@ -1184,7 +1184,19 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
agmt_get_long_name(prp->agmt),
op2string(op->operation_type), op->target_address.dn, slapi_sdn_get_dn(remote_dn));
switch (op->operation_type) {
- /* For an ADD operation, we map the entry and then send the operation, which may fail if the peer entry already existed */
+ /*
+ we should check the modify case first and check the list of mods -
+ if the magic objectclass (ntuser) and attributes (ntUserCreateNewAccount
+ or ntGroupCreateNewAccount) then we should fall through to the ADD case
+ since the user wants to add the user to AD - could maybe just change
+ process_replay_add slightly, to add the mods list from the modify
+ operation - process_replay_add already turns the entry into a mods list
+ to pass to the ldap add operation, so it should not be too much more
+ trouble to apply the additional mods from the modify operation - we'll
+ have to pass in local entry, or perhaps just change the operation from
+ modify to an add, and set the op->p.p_add.target_entry to the local_entry
+ which gets retrieved above
+ */
case SLAPI_OPERATION_ADD:
return_value = process_replay_add(prp,op,local_entry,local_dn,remote_dn,is_user,missing_entry,&password);
break;
@@ -1193,6 +1205,22 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
LDAPMod **mapped_mods = NULL;
windows_map_mods_for_replay(prp,op->p.p_modify.modify_mods, &mapped_mods, is_user, &password);
+ if (is_user) {
+ winsync_plugin_call_pre_ad_mod_user_mods_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ local_dn,
+ op->p.p_modify.modify_mods,
+ remote_dn,
+ &mapped_mods);
+ } else if (is_group) {
+ winsync_plugin_call_pre_ad_mod_group_mods_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ local_dn,
+ op->p.p_modify.modify_mods,
+ remote_dn,
+ &mapped_mods);
+ }
+
/* It's possible that the mapping process results in an empty mod list, in which case we don't bother with the replay */
if ( mapped_mods == NULL || *(mapped_mods)== NULL )
{
@@ -1304,7 +1332,7 @@ is_straight_mapped_attr(const char *type, int is_user /* or group */, int is_nt4
char *this_attr = NULL;
char **list = is_user ? (is_nt4 ? nt4_user_matching_attributes : windows_user_matching_attributes) : (is_nt4 ? nt4_group_matching_attributes : windows_group_matching_attributes);
/* Look for the type in the list of straight mapped attrs for the appropriate object type */
- while (this_attr = list[offset])
+ while ((this_attr = list[offset]))
{
if (0 == slapi_attr_type_cmp(this_attr, type, SLAPI_TYPE_CMP_SUBTYPE))
{
@@ -1327,7 +1355,7 @@ windows_map_attr_name(const char *original_type , int to_windows, int is_user, i
*mapped_type = NULL;
/* Iterate over the map entries looking for the type we have */
- while(this_map = &(our_map[offset]))
+ while((this_map = &(our_map[offset])))
{
char *their_name = to_windows ? this_map->windows_attribute_name : this_map->ldap_attribute_name;
char *our_name = to_windows ? this_map->ldap_attribute_name : this_map->windows_attribute_name;
@@ -1500,7 +1528,6 @@ windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_ent
if (0 == slapi_attr_type_cmp(new_type, "streetAddress", SLAPI_TYPE_CMP_SUBTYPE)) {
if (slapi_valueset_count(vs) > 1) {
int i = 0;
- const char *street_value = NULL;
Slapi_Value *value = NULL;
Slapi_Value *new_value = NULL;
@@ -2026,6 +2053,10 @@ find_entry_by_attr_value(const char *attribute, const char *value, Slapi_Entry *
int rval = 0;
const char *subtree_dn = NULL;
int not_unique = 0;
+ char *subtree_dn_copy = NULL;
+ int scope = LDAP_SCOPE_SUBTREE;
+ char **attrs = NULL;
+ LDAPControl **server_controls = NULL;
if (pb == NULL)
goto done;
@@ -2036,12 +2067,21 @@ find_entry_by_attr_value(const char *attribute, const char *value, Slapi_Entry *
goto done;
subtree_dn = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
+ subtree_dn_copy = slapi_ch_strdup(subtree_dn);
- slapi_search_internal_set_pb(pb, subtree_dn,
- LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
+ winsync_plugin_call_pre_ds_search_entry_cb(ra, NULL, &subtree_dn_copy, &scope, &query,
+ &attrs, &server_controls);
+
+ slapi_search_internal_set_pb(pb, subtree_dn_copy,
+ scope, query, attrs, 0, server_controls, NULL,
(void *)plugin_get_default_component_id(), 0);
slapi_search_internal_pb(pb);
+ slapi_ch_free_string(&subtree_dn_copy);
slapi_ch_free_string(&query);
+ slapi_ch_array_free(attrs);
+ attrs = NULL;
+ ldap_controls_free(server_controls);
+ server_controls = NULL;
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);
if (rval != LDAP_SUCCESS)
@@ -2096,7 +2136,7 @@ dedash_guid(char *str)
char *p = str;
char c = '\0';
- while (c = *p)
+ while ((c = *p))
{
if ('-' == c)
{
@@ -2254,7 +2294,7 @@ 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))) {
+ if ((suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt)))) {
/* If this isn't found, it is treated as an error below. */
suffix = (const char *) PL_strcasestr(suffix,"dc=");
}
@@ -2358,7 +2398,6 @@ static Slapi_DN *make_dn_from_guid(char *guid, int is_nt4, const char* suffix)
char *dn_string = NULL;
if (guid)
{
- new_dn = slapi_sdn_new();
if (is_nt4)
{
dn_string = PR_smprintf("GUID=%s,%s",guid,suffix);
@@ -2366,7 +2405,7 @@ static Slapi_DN *make_dn_from_guid(char *guid, int is_nt4, const char* suffix)
{
dn_string = PR_smprintf("<GUID=%s>",guid);
}
- slapi_sdn_init_dn_byval(new_dn,dn_string);
+ new_dn = slapi_sdn_new_dn_byval(dn_string);
PR_smprintf_free(dn_string);
}
/* dn string is now inside the Slapi_DN, and will be freed by its owner */
@@ -2452,6 +2491,7 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
* without removing the ntUniqueID attribute. We should verify that the entry really
* exists in AD. */
rc = windows_get_remote_entry(prp, new_dn, &remote_entry);
+ slapi_sdn_free(&new_dn);
if (0 == rc && remote_entry) {
slapi_entry_free(remote_entry);
} else {
@@ -2471,7 +2511,6 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
}
if (cn_string) {
- char *rdnstr = NULL;
char *container_str = NULL;
container_str = extract_container(slapi_entry_get_sdn_const(e),
@@ -2719,9 +2758,23 @@ map_entry_dn_inbound(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra)
if (is_user)
{
new_dn_string = PR_smprintf("uid=%s,%s%s",username,container_str,suffix);
+ winsync_plugin_call_get_new_ds_user_dn_cb(ra,
+ windows_private_get_raw_entry(ra),
+ e,
+ &new_dn_string,
+ windows_private_get_directory_subtree(ra),
+ windows_private_get_windows_subtree(ra));
} else
{
new_dn_string = PR_smprintf("cn=%s,%s%s",username,container_str,suffix);
+ if (is_group) {
+ winsync_plugin_call_get_new_ds_group_dn_cb(ra,
+ windows_private_get_raw_entry(ra),
+ e,
+ &new_dn_string,
+ windows_private_get_directory_subtree(ra),
+ windows_private_get_windows_subtree(ra));
+ }
}
new_dn = slapi_sdn_new_dn_byval(new_dn_string);
PR_smprintf_free(new_dn_string);
@@ -2939,6 +2992,18 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
{
slapi_entry_add_string(local_entry,"sn",username);
}
+
+ if (is_user) {
+ winsync_plugin_call_pre_ds_add_user_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ remote_entry,
+ local_entry);
+ } else if (is_group) {
+ winsync_plugin_call_pre_ds_add_group_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ remote_entry,
+ local_entry);
+ }
/* Store it */
windows_dump_entry("Adding new local entry",local_entry);
pb = slapi_pblock_new();
@@ -2951,6 +3016,7 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
"add operation of entry %s returned: %d\n", slapi_sdn_get_dn(local_sdn), retval);
}
error:
+ slapi_ch_free_string(&guid_str);
if (pb)
{
slapi_pblock_destroy(pb);
@@ -3115,7 +3181,6 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
* sure we don't try to send more than one value. */
if (slapi_valueset_count(vs) > 1) {
int i = 0;
- const char *street_value = NULL;
Slapi_Value *value = NULL;
Slapi_Value *new_value = NULL;
@@ -3229,7 +3294,6 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
* sure we don't try to send more than one value. */
if (slapi_valueset_count(vs) > 1) {
int i = 0;
- const char *street_value = NULL;
Slapi_Value *value = NULL;
Slapi_Value *new_value = NULL;
@@ -3318,6 +3382,40 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
slapi_ch_free_string(&local_type);
}
+ if (to_windows) {
+ if (is_user) {
+ winsync_plugin_call_pre_ad_mod_user_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ local_entry, /* the cooked ad entry */
+ remote_entry, /* the ds entry */
+ smods,
+ do_modify);
+ } else if (is_group) {
+ winsync_plugin_call_pre_ad_mod_group_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ local_entry, /* the cooked ad entry */
+ remote_entry, /* the ds entry */
+ smods,
+ do_modify);
+ }
+ } else {
+ if (is_user) {
+ winsync_plugin_call_pre_ds_mod_user_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ remote_entry, /* the cooked ad entry */
+ local_entry, /* the ds entry */
+ smods,
+ do_modify);
+ } else if (is_group) {
+ winsync_plugin_call_pre_ds_mod_group_cb(prp->agmt,
+ windows_private_get_raw_entry(prp->agmt),
+ remote_entry, /* the cooked ad entry */
+ local_entry, /* the ds entry */
+ smods,
+ do_modify);
+ }
+ }
+
if (slapi_is_loglevel_set(SLAPI_LOG_REPL) && *do_modify)
{
slapi_mods_dump(smods,"windows sync");
@@ -3412,10 +3510,16 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r
Slapi_Entry *mapped_entry = NULL;
char *password = NULL;
const Slapi_DN* local_dn = NULL;
+ int can_add = winsync_plugin_call_can_add_entry_to_ad_cb(prp->agmt, e, remote_dn);
/* First map the entry */
local_dn = slapi_entry_get_sdn_const(e);
- if (missing_entry)
- retval = windows_create_remote_entry(prp, e, remote_dn, &mapped_entry, &password);
+ if (missing_entry) {
+ if (can_add) {
+ retval = windows_create_remote_entry(prp, e, remote_dn, &mapped_entry, &password);
+ } else {
+ return retval; /* cannot add and no entry to modify */
+ }
+ }
/* Convert entry to mods */
if (0 == retval && mapped_entry)
{
diff --git a/ldap/servers/plugins/replication/windows_tot_protocol.c b/ldap/servers/plugins/replication/windows_tot_protocol.c
index 6e01f633..09ecbc8e 100644
--- a/ldap/servers/plugins/replication/windows_tot_protocol.c
+++ b/ldap/servers/plugins/replication/windows_tot_protocol.c
@@ -99,11 +99,15 @@ windows_tot_run(Private_Repl_Protocol *prp)
int rc;
callback_data cb_data;
Slapi_PBlock *pb;
- const char* dn;
+ char* dn;
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;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_tot_run\n", 0, 0, 0 );
@@ -168,13 +172,15 @@ windows_tot_run(Private_Repl_Protocol *prp)
/* send everything */
- dn = slapi_sdn_get_dn( windows_private_get_directory_subtree(prp->agmt));
+ 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,
- LDAP_SCOPE_SUBTREE, "(|(objectclass=ntuser)(objectclass=ntgroup))", NULL, 0, NULL, NULL,
+ slapi_search_internal_set_pb (pb, dn, scope, filter, attrs, 0, server_controls, NULL,
repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
cb_data.prp = prp;
cb_data.rc = 0;
@@ -186,6 +192,13 @@ windows_tot_run(Private_Repl_Protocol *prp)
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);
agmt_set_last_init_end(prp->agmt, current_time());
rc = cb_data.rc;
diff --git a/ldap/servers/plugins/replication/windowsrepl.h b/ldap/servers/plugins/replication/windowsrepl.h
index 3691664a..47138656 100644
--- a/ldap/servers/plugins/replication/windowsrepl.h
+++ b/ldap/servers/plugins/replication/windowsrepl.h
@@ -44,9 +44,9 @@
/* windows_private.c */
typedef struct windowsprivate Dirsync_Private;
Dirsync_Private* windows_private_new();
-void windows_private_set_windows_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn );
+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);
-void windows_private_set_directory_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn );
+void windows_private_set_directory_subtree (const Repl_Agmt *ra,Slapi_DN* sdn );
const Slapi_DN* windows_private_get_directory_subtree (const Repl_Agmt *ra);
LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra);
ConnResult send_dirsync_search(Repl_Connection *conn);
@@ -63,7 +63,6 @@ PRBool windows_private_create_users(const Repl_Agmt *ra);
void windows_private_set_create_groups(const Repl_Agmt *ra, PRBool value);
PRBool windows_private_create_groups(const Repl_Agmt *ra);
const char *windows_private_get_windows_domain(const Repl_Agmt *ra);
-static void windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain);
int windows_private_get_isnt4(const Repl_Agmt *ra);
void windows_private_set_isnt4(const Repl_Agmt *ra, int isit);
int windows_private_get_iswin2k3(const Repl_Agmt *ra);
@@ -71,6 +70,16 @@ 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_deleted_filter(const Repl_Agmt *ra);
const char* windows_private_get_purl(const Repl_Agmt *ra);
+/*
+ * The raw entry is the last raw entry read from AD - raw as opposed
+ * "cooked" - that is, having had schema processing done
+ */
+/* get returns a pointer to the structure - do not free */
+Slapi_Entry *windows_private_get_raw_entry(const Repl_Agmt *ra);
+/* this is passin - windows_private owns the pointer, not a copy */
+void windows_private_set_raw_entry(const Repl_Agmt *ra, Slapi_Entry *e);
+void *windows_private_get_api_cookie(const Repl_Agmt *ra);
+void windows_private_set_api_cookie(Repl_Agmt *ra, void *cookie);
/* in windows_connection.c */
ConnResult windows_conn_connect(Repl_Connection *conn);
@@ -112,3 +121,86 @@ int windows_check_user_password(Repl_Connection *conn, Slapi_DN *sdn, char *pass
/* Used for GUID format conversion */
#define NTUNIQUEID_LENGTH 32
#define AD_GUID_LENGTH 36
+
+/* called for each replication agreement - so the winsync
+ plugin can be agreement specific and store agreement
+ specific data
+*/
+void windows_plugin_init(Repl_Agmt *ra);
+
+void winsync_plugin_call_dirsync_search_params_cb(const Repl_Agmt *ra, const char *agmt_dn, char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls);
+/* called before searching for a single entry from AD - agmt_dn will be NULL */
+void winsync_plugin_call_pre_ad_search_cb(const Repl_Agmt *ra, const char *agmt_dn, char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls);
+/* called before an internal search to get a single DS entry - agmt_dn will be NULL */
+void winsync_plugin_call_pre_ds_search_entry_cb(const Repl_Agmt *ra, const char *agmt_dn, char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls);
+/* called before the total update to get all entries from the DS to sync to AD */
+void winsync_plugin_call_pre_ds_search_all_cb(const Repl_Agmt *ra, const char *agmt_dn, char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls);
+
+void winsync_plugin_call_pre_ad_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify);
+void winsync_plugin_call_pre_ad_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify);
+void winsync_plugin_call_pre_ds_mod_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify);
+void winsync_plugin_call_pre_ds_mod_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify);
+
+void winsync_plugin_call_pre_ds_add_user_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry);
+void winsync_plugin_call_pre_ds_add_group_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry);
+
+void winsync_plugin_call_get_new_ds_user_dn_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry,
+ char **new_dn_string, const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix);
+void winsync_plugin_call_get_new_ds_group_dn_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry,
+ char **new_dn_string, const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix);
+
+void winsync_plugin_call_pre_ad_mod_user_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend);
+void winsync_plugin_call_pre_ad_mod_group_mods_cb(const Repl_Agmt *ra, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend);
+
+int winsync_plugin_call_can_add_entry_to_ad_cb(const Repl_Agmt *ra, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn);
+/*
+ Call stack for all places where windows_LDAPMessage2Entry is called:
+
+ windows_LDAPMessage2Entry
+ ++windows_seach_entry_ext
+ ++++windows_search_entry
+ ++++++windows_get_remote_entry
+ map_dn_values
+ windows_create_remote_entry
+ process_replay_add
+ windows_process_total_add
+ windows_map_mods_for_replay
+ windows_replay_update
+ send_updates
+ windows_inc_run
+ windows_create_local_entry
+ windows_process_dirsync_entry
+ windows_generate_update_mods
+ windows_update_remote_entry
+ process_replay_add
+ windows_process_total_add
+ windows_update_local_entry
+ windows_process_dirsync_entry
+ process_replay_add
+ windows_replay_update
+ map_entry_dn_outbound
+ map_dn_values
+ windows_replay_update
+ windows_process_total_entry
+ send_entry
+ windows_tot_run
+ windows_process_total_add
+ windows_process_total_entry
+ send_entry
+ windows_tot_run
+ windows_process_dirsync_entry
+ windows_dirsync_inc_run
+ find_entry_by_attr_value_remote
+ map_entry_dn_outbound
+ ++++windows_get_remote_tombstone
+ map_windows_tombstone_dn
+ process_replay_add
+ ++windows_conn_get_search_result
+ windows_dirsync_inc_run
+
+
+ windows_inc_protocol
+ ++send_updates
+ ++++windows_replay_update
+*/
+/* #define WINSYNC_TEST 1 */ /* fake ad is really just a regular ds */
diff --git a/ldap/servers/plugins/replication/winsync-plugin.h b/ldap/servers/plugins/replication/winsync-plugin.h
new file mode 100644
index 00000000..882e4144
--- /dev/null
+++ b/ldap/servers/plugins/replication/winsync-plugin.h
@@ -0,0 +1,534 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#ifndef WINSYNC_PLUGIN_PUBLIC_API
+#define WINSYNC_PLUGIN_PUBLIC_API
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* windows_private.c */
+
+#include "slapi-plugin.h"
+
+/*
+ * WinSync plug-in API
+ */
+#define WINSYNC_v1_0_GUID "CDA8F029-A3C6-4EBB-80B8-A2E183DB0481"
+
+/*
+ * The plugin will define this callback in order to initialize itself.
+ * The ds subtree and the ad subtree from the sync agreement are passed in.
+ * These are read only.
+ * The return value is private data to the plugin that will be passed back
+ * at each callback
+ */
+typedef void * (*winsync_plugin_init_cb)(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree);
+#define WINSYNC_PLUGIN_INIT_CB 1
+/* agmt_dn - const - the original AD base dn from the winsync agreement
+ scope - set directly e.g. *scope = 42;
+ base, filter - malloced - to set, free first e.g.
+ slapi_ch_free_string(filter);
+ *base = slapi_ch_strdup("(objectclass=foobar)");
+ winsync code will use slapi_ch_free_string to free this value, so no static strings
+ attrs - NULL or null terminated array of strings - can use slapi_ch_array_add to add e.g.
+ slapi_ch_array_add(attrs, slapi_ch_strdup("myattr"));
+ attrs will be freed with slapi_ch_array_free, so caller must own the memory
+ serverctrls - NULL or null terminated array of LDAPControl* - can use slapi_add_control_ext to add
+ slapi_add_control_ext(serverctrls, mynewctrl, 1 / add a copy /);
+ serverctrls will be freed with ldap_controls_free, so caller must own memory
+*/
+typedef void (*winsync_search_params_cb)(void *cookie, const char *agmt_dn, char **base, int *scope, char **filter, char ***attrs, LDAPControl ***serverctrls);
+#define WINSYNC_PLUGIN_DIRSYNC_SEARCH_CB 2 /* serverctrls will already contain the DirSync control */
+#define WINSYNC_PLUGIN_PRE_AD_SEARCH_CB 3
+#define WINSYNC_PLUGIN_PRE_DS_SEARCH_ENTRY_CB 4
+#define WINSYNC_PLUGIN_PRE_DS_SEARCH_ALL_CB 5
+/*
+ * These callbacks are the main entry points that allow the plugin
+ * to intercept modifications to local and remote entries.
+ * rawentry - the raw AD entry, read directly from AD - this is read only
+ * ad_entry - the "cooked" AD entry - the DN in this entry should be set
+ * when the operation is to modify the AD entry
+ * ds_entry - the entry from the ds - the DN in this entry should be set
+ * when the operation is to modify the DS entry
+ * smods - the post-processing modifications - these should be modified
+ * by the plugin as needed
+ * do_modify - if the code has some modifications that need to be applied, this
+ * will be set to true - if the plugin has added some items to smods
+ * this should be set to true - if the plugin has removed all of
+ * the smods, and no operation should be performed, this should
+ * be set to false
+ */
+typedef void (*winsync_pre_mod_cb)(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry, Slapi_Mods *smods, int *do_modify);
+#define WINSYNC_PLUGIN_PRE_AD_MOD_USER_CB 6
+#define WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_CB 7
+#define WINSYNC_PLUGIN_PRE_DS_MOD_USER_CB 8
+#define WINSYNC_PLUGIN_PRE_DS_MOD_GROUP_CB 9
+/*
+ * These callbacks are called when a new entry is being added to the
+ * local directory server from AD.
+ * rawentry - the raw AD entry, read directly from AD - this is read only
+ * ad_entry - the "cooked" AD entry
+ * ds_entry - the entry to be added to the DS - all modifications should
+ * be made to this entry, including changing the DN if needed,
+ * since the DN of this entry will be used as the ADD target DN
+ * This entry will already have had the default schema mapping applied
+ */
+typedef void (*winsync_pre_add_cb)(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, Slapi_Entry *ds_entry);
+#define WINSYNC_PLUGIN_PRE_DS_ADD_USER_CB 10
+#define WINSYNC_PLUGIN_PRE_DS_ADD_GROUP_CB 11
+/*
+ * If a new entry has been added to AD, and we're sync'ing it over
+ * to the DS, we may need to create a new DN for the entry. The
+ * code tries to come up with a reasonable DN, but the plugin may
+ * have different ideas. These callbacks allow the plugin to specify
+ * what the new DN for the new entry should be. This is called from
+ * map_entry_dn_inbound which is called from various places where the DN for
+ * the new entry is needed. The winsync_plugin_call_pre_ds_add_* callbacks
+ * can also be used to set the DN just before the entry is stored in the DS.
+ * This is also used when we are mapping a dn valued attribute e.g. owner
+ * or secretary
+ * rawentry - the raw AD entry, read directly from AD - this is read only
+ * ad_entry - the "cooked" AD entry
+ * new_dn_string - the given value will be the default value created by the sync code
+ * to change it, slapi_ch_free_string first, then malloc the value to use
+ * ds_suffix - the suffix from the DS side of the sync agreement
+ * ad_suffix - the suffix from the AD side of the sync agreement
+ */
+typedef void (*winsync_get_new_dn_cb)(void *cookie, const Slapi_Entry *rawentry, Slapi_Entry *ad_entry, char **new_dn_string,
+ const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix);
+#define WINSYNC_PLUGIN_GET_NEW_DS_USER_DN_CB 12
+#define WINSYNC_PLUGIN_GET_NEW_DS_GROUP_DN_CB 13
+/*
+ * These callbacks are called when a mod operation is going to be replayed
+ * to AD. This case is different than the pre add or pre mod callbacks
+ * above because in this context, we may only have the list of modifications
+ * and the DN to which the mods were applied.
+ * rawentry - the raw AD entry, read directly from AD - may be NULL
+ * local_dn - the original local DN used in the modification
+ * origmods - the original mod list
+ * remote_dn - this is the DN which will be used with the remote modify operation
+ * to AD - the winsync code may have already attempted to calculate its value
+ * modstosend - this is the list of modifications which will be sent - the winsync
+ * code will already have done its default mapping to these values
+ *
+ */
+typedef void (*winsync_pre_ad_mod_mods_cb)(void *cookie, const Slapi_Entry *rawentry, const Slapi_DN *local_dn, LDAPMod * const *origmods, Slapi_DN *remote_dn, LDAPMod ***modstosend);
+#define WINSYNC_PLUGIN_PRE_AD_MOD_USER_MODS_CB 14
+#define WINSYNC_PLUGIN_PRE_AD_MOD_GROUP_MODS_CB 15
+
+/*
+ * Callbacks used to determine if an entry should be added to the
+ * AD side if it does not already exist.
+ * local_entry - the candidate entry to test
+ * remote_DN - the candidate remote entry to add
+ */
+typedef int (*winsync_can_add_to_ad_cb)(void *cookie, const Slapi_Entry *local_entry, const Slapi_DN *remote_dn);
+#define WINSYNC_PLUGIN_CAN_ADD_ENTRY_TO_AD_CB 16
+
+/*
+ The following are sample code stubs to show how to implement
+ a plugin which uses this api
+*/
+
+#ifdef WINSYNC_SAMPLE_CODE
+
+#include "slapi-plugin.h"
+#include "winsync-plugin.h"
+
+static char *test_winsync_plugin_name = "test_winsync_api";
+
+static void *
+test_winsync_api_init(const Slapi_DN *ds_subtree, const Slapi_DN *ad_subtree)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_init [%s] [%s] -- begin\n",
+ slapi_sdn_get_dn(ds_subtree),
+ slapi_sdn_get_dn(ad_subtree));
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_init -- end\n");
+
+ return NULL;
+}
+
+static void
+test_winsync_dirsync_search_params_cb(void *cbdata, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_dirsync_search_params_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_dirsync_search_params_cb -- end\n");
+
+ return;
+}
+
+/* called before searching for a single entry from AD - agmt_dn will be NULL */
+static void
+test_winsync_pre_ad_search_cb(void *cbdata, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ad_search_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ad_search_cb -- end\n");
+
+ return;
+}
+
+/* called before an internal search to get a single DS entry - agmt_dn will be NULL */
+static void
+test_winsync_pre_ds_search_entry_cb(void *cbdata, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ds_search_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ds_search_cb -- end\n");
+
+ return;
+}
+
+/* called before the total update to get all entries from the DS to sync to AD */
+static void
+test_winsync_pre_ds_search_all_cb(void *cbdata, const char *agmt_dn,
+ char **base, int *scope, char **filter,
+ char ***attrs, LDAPControl ***serverctrls)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ds_search_all_cb -- orig filter [%s] -- begin\n",
+ ((filter && *filter) ? *filter : "NULL"));
+
+ /* We only want to grab users from the ds side - no groups */
+ slapi_ch_free_string(filter);
+ /* maybe use ntUniqueId=* - only get users that have already been
+ synced with AD already - ntUniqueId and ntUserDomainId are
+ indexed for equality only - need to add presence? */
+ *filter = slapi_ch_strdup("(&(objectclass=ntuser)(ntUserDomainId=*))");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ds_search_all_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ad_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ad_mod_user_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ad_mod_user_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ad_mod_group_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ad_mod_group_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ad_mod_group_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ds_mod_user_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ds_mod_user_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ds_mod_user_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ds_mod_group_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry,
+ Slapi_Mods *smods, int *do_modify)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ds_mod_group_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ds_mod_group_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ds_add_user_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ds_add_user_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ds_add_user_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ds_add_group_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, Slapi_Entry *ds_entry)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ds_add_group_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ds_add_group_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_get_new_ds_user_dn_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, char **new_dn_string,
+ const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix)
+{
+ char **rdns = NULL;
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_get_new_ds_user_dn_cb -- old dn [%s] -- begin\n",
+ *new_dn_string);
+
+ rdns = ldap_explode_dn(*new_dn_string, 0);
+ if (!rdns || !rdns[0]) {
+ ldap_value_free(rdns);
+ return;
+ }
+
+ slapi_ch_free_string(new_dn_string);
+ *new_dn_string = PR_smprintf("%s,%s", rdns[0], slapi_sdn_get_dn(ds_suffix));
+ ldap_value_free(rdns);
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_get_new_ds_user_dn_cb -- new dn [%s] -- end\n",
+ *new_dn_string);
+
+ return;
+}
+
+static void
+test_winsync_get_new_ds_group_dn_cb(void *cbdata, const Slapi_Entry *rawentry,
+ Slapi_Entry *ad_entry, char **new_dn_string,
+ const Slapi_DN *ds_suffix, const Slapi_DN *ad_suffix)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_get_new_ds_group_dn_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_get_new_ds_group_dn_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ad_mod_user_mods_cb(void *cbdata, const Slapi_Entry *rawentry,
+ const Slapi_DN *local_dn, LDAPMod * const *origmods,
+ Slapi_DN *remote_dn, LDAPMod ***modstosend)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ad_mod_user_mods_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ad_mod_user_mods_cb -- end\n");
+
+ return;
+}
+
+static void
+test_winsync_pre_ad_mod_group_mods_cb(void *cbdata, const Slapi_Entry *rawentry,
+ const Slapi_DN *local_dn, LDAPMod * const *origmods,
+ Slapi_DN *remote_dn, LDAPMod ***modstosend)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_pre_ad_mod_group_mods_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_pre_ad_mod_group_mods_cb -- end\n");
+
+ return;
+}
+
+static int
+test_winsync_can_add_entry_to_ad_cb(void *cbdata, const Slapi_Entry *local_entry,
+ const Slapi_DN *remote_dn)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_can_add_entry_to_ad_cb -- begin\n");
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_can_add_entry_to_ad_cb -- end\n");
+
+ return 0; /* false - do not allow entries to be added to ad */
+}
+
+/**
+ * Plugin identifiers
+ */
+static Slapi_PluginDesc test_winsync_pdesc = {
+ "test-winsync-plugin",
+ PLUGIN_MAGIC_VENDOR_STR,
+ PRODUCTTEXT,
+ "test winsync plugin"
+};
+
+static Slapi_ComponentId *test_winsync_plugin_id = NULL;
+
+static void *test_winsync_api[] = {
+ NULL, /* reserved for api broker use, must be zero */
+ test_winsync_api_init,
+ test_winsync_dirsync_search_params_cb,
+ test_winsync_pre_ad_search_cb,
+ test_winsync_pre_ds_search_entry_cb,
+ test_winsync_pre_ds_search_all_cb,
+ test_winsync_pre_ad_mod_user_cb,
+ test_winsync_pre_ad_mod_group_cb,
+ test_winsync_pre_ds_mod_user_cb,
+ test_winsync_pre_ds_mod_group_cb,
+ test_winsync_pre_ds_add_user_cb,
+ test_winsync_pre_ds_add_group_cb,
+ test_winsync_get_new_ds_user_dn_cb,
+ test_winsync_get_new_ds_group_dn_cb,
+ test_winsync_pre_ad_mod_user_mods_cb,
+ test_winsync_pre_ad_mod_group_mods_cb,
+ test_winsync_can_add_entry_to_ad_cb
+};
+
+static int
+test_winsync_plugin_start(Slapi_PBlock *pb)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_plugin_start -- begin\n");
+
+ if( slapi_apib_register(WINSYNC_v1_0_GUID, test_winsync_api) ) {
+ slapi_log_error( SLAPI_LOG_FATAL, test_winsync_plugin_name,
+ "<-- test_winsync_plugin_start -- failed to register winsync api -- end\n");
+ return -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_plugin_start -- end\n");
+ return 0;
+}
+
+static int
+test_winsync_plugin_close(Slapi_PBlock *pb)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_plugin_close -- begin\n");
+
+ slapi_apib_unregister(WINSYNC_v1_0_GUID);
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_plugin_close -- end\n");
+ return 0;
+}
+
+/* this is the slapi plugin init function,
+ not the one used by the winsync api
+*/
+int test_winsync_plugin_init(Slapi_PBlock *pb)
+{
+ slapi_log_error(SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "--> test_winsync_plugin_init -- begin\n");
+
+ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
+ SLAPI_PLUGIN_VERSION_01 ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
+ (void *) test_winsync_plugin_start ) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
+ (void *) test_winsync_plugin_close ) != 0 ||
+ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&test_winsync_pdesc ) != 0 )
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, test_winsync_plugin_name,
+ "<-- test_winsync_plugin_init -- failed to register plugin -- end\n");
+ return -1;
+ }
+
+ /* Retrieve and save the plugin identity to later pass to
+ internal operations */
+ if (slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &test_winsync_plugin_id) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, test_winsync_plugin_name,
+ "<-- test_winsync_plugin_init -- failed to retrieve plugin identity -- end\n");
+ return -1;
+ }
+
+ slapi_log_error( SLAPI_LOG_PLUGIN, test_winsync_plugin_name,
+ "<-- test_winsync_plugin_init -- end\n");
+ return 0;
+}
+
+/*
+dn: cn=Test Winsync API,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: Test Winsync API
+nsslapd-pluginpath: libtestwinsync-plugin
+nsslapd-plugininitfunc: test_winsync_plugin_init
+nsslapd-plugintype: preoperation
+nsslapd-pluginenabled: on
+nsslapd-plugin-depends-on-type: database
+nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
+*/
+
+#endif /* WINSYNC_SAMPLE_CODE */
+
+#endif /* WINSYNC_PLUGIN_PUBLIC_API */
diff --git a/ldap/servers/slapd/charray.c b/ldap/servers/slapd/charray.c
index 2f97f4d1..e57d9099 100644
--- a/ldap/servers/slapd/charray.c
+++ b/ldap/servers/slapd/charray.c
@@ -246,6 +246,11 @@ slapi_ch_array_free( char **array )
charray_free (array);
}
+void
+slapi_ch_array_add( char ***a, char *s )
+{
+ charray_add(a, s);
+}
/* case insensitive search */
int
diff --git a/ldap/servers/slapd/control.c b/ldap/servers/slapd/control.c
index 5bf4c7e3..3d0a4f9e 100644
--- a/ldap/servers/slapd/control.c
+++ b/ldap/servers/slapd/control.c
@@ -474,9 +474,14 @@ write_controls( BerElement *ber, LDAPControl **ctrls )
/*
* duplicate "newctrl" and add it to the array of controls "*ctrlsp"
* note that *ctrlsp may be reset and that it is okay to pass NULL for it.
+ * IF copy is true, a copy of the passed in control will be added - copy
+ * made with slapi_dup_control - if copy is false, the control
+ * will be used directly and may be free'd by ldap_controls_free - so
+ * make sure it is ok for the control array to own the pointer you
+ * pass in
*/
void
-add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl )
+add_control_ext( LDAPControl ***ctrlsp, LDAPControl *newctrl, int copy )
{
int count;
@@ -491,10 +496,29 @@ add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl )
*ctrlsp = (LDAPControl **)slapi_ch_realloc( (char *)*ctrlsp,
( count + 2 ) * sizeof(LDAPControl *));
- (*ctrlsp)[ count ] = slapi_dup_control( newctrl );
+ if (copy) {
+ (*ctrlsp)[ count ] = slapi_dup_control( newctrl );
+ } else {
+ (*ctrlsp)[ count ] = newctrl;
+ }
(*ctrlsp)[ ++count ] = NULL;
}
+/*
+ * duplicate "newctrl" and add it to the array of controls "*ctrlsp"
+ * note that *ctrlsp may be reset and that it is okay to pass NULL for it.
+ */
+void
+add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl )
+{
+ add_control_ext(ctrlsp, newctrl, 1 /* copy */);
+}
+
+void
+slapi_add_control_ext( LDAPControl ***ctrlsp, LDAPControl *newctrl, int copy )
+{
+ add_control_ext(ctrlsp, newctrl, copy);
+}
/*
* return a malloc'd copy of "ctrl"
@@ -527,6 +551,14 @@ slapi_dup_control( LDAPControl *ctrl )
return( rctrl );
}
+void
+slapi_add_controls( LDAPControl ***ctrlsp, LDAPControl **newctrls, int copy )
+{
+ int ii;
+ for (ii = 0; newctrls && newctrls[ii]; ++ii) {
+ slapi_add_control_ext(ctrlsp, newctrls[ii], copy);
+ }
+}
int
slapi_build_control( char *oid, BerElement *ber,
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 56959b3d..23fa2af9 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -835,6 +835,24 @@ int slapi_build_control( char *oid, BerElement *ber,
int slapi_build_control_from_berval( char *oid, struct berval *bvp,
char iscritical, LDAPControl **ctrlp );
+/* Given an array of controls e.g. LDAPControl **ctrls, add the given
+ control to the end of the array, growing the array with realloc
+ e.g. slapi_add_control_ext(&ctrls, newctrl, 1);
+ if ctrls is NULL, the array will be created with malloc
+ if copy is true, the given control will be copied
+ if copy is false, the given control will be used and owned by the array
+ if copy is false, make sure the control can be freed by ldap_controls_free
+*/
+void slapi_add_control_ext( LDAPControl ***ctrlsp, LDAPControl *newctrl, int copy );
+
+/* Given an array of controls e.g. LDAPControl **ctrls, add all of the given
+ controls in the newctrls array to the end of ctrls, growing the array with realloc
+ if ctrls is NULL, the array will be created with malloc
+ if copy is true, each given control will be copied
+ if copy is false, each given control will be used and owned by the array
+ if copy is false, make sure each control can be freed by ldap_controls_free
+*/
+void slapi_add_controls( LDAPControl ***ctrlsp, LDAPControl **newctrls, int copy );
/*
* routines for dealing with extended operations
@@ -865,6 +883,13 @@ int slapi_pwpolicy_make_response_control (Slapi_PBlock *pb, int seconds, int log
* routine for freeing the ch_arrays returned by the slapi_get*_copy functions above
*/
void slapi_ch_array_free( char **array );
+/*
+ * Add the given string to the given null terminated array.
+ * s is not copied, so if you want to add a copy of s to the
+ * array, use slapi_ch_strdup(s)
+ * if *a is NULL, a new array will be created
+ */
+void slapi_ch_array_add( char ***array, char *string );
/*