Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 313466 Details for
Bug 457846
The Windows Sync API should have plug-in points
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
new diffs
cvsdiffs (text/plain), 63.85 KB, created by
Rich Megginson
on 2008-08-05 17:19:31 UTC
(
hide
)
Description:
new diffs
Filename:
MIME Type:
Creator:
Rich Megginson
Created:
2008-08-05 17:19:31 UTC
Size:
63.85 KB
patch
obsolete
>Index: ldapserver/ldap/servers/plugins/replication/windows_connection.c >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/windows_connection.c,v >retrieving revision 1.18 >diff -u -8 -r1.18 windows_connection.c >--- ldapserver/ldap/servers/plugins/replication/windows_connection.c 18 Oct 2007 00:08:31 -0000 1.18 >+++ ldapserver/ldap/servers/plugins/replication/windows_connection.c 5 Aug 2008 17:16:27 -0000 >@@ -507,56 +507,67 @@ > return_value = CONN_NOT_CONNECTED; > } > LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_perform_operation\n", 0, 0, 0 ); > return return_value; > } > > /* 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; > } > > /* > * dn not allocated by slapi > * 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")) > { > /* AD returns us entries with these attributes that we are not interested in, > * but they break the entry attribute code (I think it is looking at null-terminated > * string values, but the values are binary here). It appears that AD has some problems > * with allowing duplicate values for system-only multi-valued attributes. So we skip > * those attributes as a workaround. > */ > ; > } else > { > 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")) > { > type_to_use = FAKE_STREET_ATTR_NAME; > } else > { > type_to_use = a; >@@ -570,71 +581,93 @@ > * on the AD side. Add this attribute to the deleted attributes list */ > Slapi_Attr *attr = slapi_attr_new(); > slapi_attr_init(attr, type_to_use); > entry_add_deleted_attribute_wsi(e, attr); > } else { > 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; > } > > /* Perform a simple search against Windows with no controls */ > ConnResult > windows_search_entry(Repl_Connection *conn, char* searchbase, char *filter, Slapi_Entry **entry) > { > return windows_search_entry_ext(conn, searchbase, filter, entry, NULL); > } > > /* Perform a simple search against Windows with optional controls */ > 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 ); > > *entry = NULL; > > 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); >+ ldap_controls_free(serverctrls_copy); >+ > 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); > LDAPDebug( LDAP_DEBUG_REPL, "windows_search_entry: recieved %d messages, %d entries, %d references\n", > nummessages, numentries, numreferences ); > } > > 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 > */ > while (NULL != ( message = ldap_next_entry(conn->ld,message))) ; > return_value = CONN_OPERATION_SUCCESS; > } > else if (IS_DISCONNECT_ERROR(ldap_rc)) >@@ -659,52 +692,56 @@ > } > LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_search_entry\n", 0, 0, 0 ); > return return_value; > } > > 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) > { > return_value = 0; > } > else > { > slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, >@@ -718,21 +755,23 @@ > return_value = CONN_NOT_CONNECTED; > } > else > { > conn->status = STATUS_CONNECTED; > 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 > { > /* conn->last_ldap_error has been set to a more specific value > * in windows_conn_connected() > * conn->last_ldap_error = LDAP_SERVER_DOWN; > */ > return_value = CONN_NOT_CONNECTED; >@@ -847,17 +886,17 @@ > } > break; > case LDAP_RES_SEARCH_ENTRY: > { > if (( dn = ldap_get_dn( conn->ld, res )) != 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 ); >- e = windows_LDAPMessage2Entry(conn->ld,lm,0); >+ e = windows_LDAPMessage2Entry(conn,lm,0); > ldap_memfree(dn); > } > } > break; > > } /* switch */ > } /* if */ > >@@ -1419,16 +1458,23 @@ > ConnResult > windows_conn_replica_supports_dirsync(Repl_Connection *conn) > { > ConnResult return_value; > int ldap_rc; > > 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) { > LDAPMessage *res = NULL; > LDAPMessage *entry = NULL; > char *attrs[] = {"supportedcontrol", NULL}; > > conn->status = STATUS_SEARCHING; >@@ -1877,17 +1923,17 @@ > repl5_stop_debug_timeout(Slapi_Eq_Context eqctx, int *setlevel) > { > char buf[20]; > char msg[SLAPI_DSE_RETURNTEXT_SIZE]; > > 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) { > /* No longer needed as we are including the one in slap.h */ > sprintf(buf, "%d", 0); > config_set_errorlog_level("nsslapd-errorlog-level", buf, msg, 1); > } > >Index: ldapserver/ldap/servers/plugins/replication/windows_private.c >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/windows_private.c,v >retrieving revision 1.17 >diff -u -8 -r1.17 windows_private.c >--- ldapserver/ldap/servers/plugins/replication/windows_private.c 18 Oct 2007 00:08:31 -0000 1.17 >+++ ldapserver/ldap/servers/plugins/replication/windows_private.c 5 Aug 2008 17:16:27 -0000 >@@ -65,18 +65,22 @@ > PRBool create_groups_from_dirsync; > char *windows_domain; > int isnt4; > int iswin2k3; > /* 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 *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) > { > if (strcasecmp (val, "on") == 0 || strcasecmp (val, "yes") == 0 || > strcasecmp (val, "true") == 0 || strcasecmp (val, "1") == 0) > { > return 1; > } else >@@ -94,27 +98,25 @@ > if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsReplicaArea)) > { > tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea); > if (NULL != tmpstr) > { > 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)) > { > tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7DirectoryReplicaArea); > if (NULL != tmpstr) > { > 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)) > { > tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewUsers); > if (NULL != tmpstr && true_value_from_string(tmpstr)) > { > windows_private_set_create_users(ra, PR_TRUE); > } >@@ -168,16 +170,18 @@ > } > > void > 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) > { > const char* windows_purl; > char *hostname; > > hostname = agmt_get_hostname(ra); >@@ -209,16 +213,19 @@ > > Dirsync_Private *dp = (Dirsync_Private *) agmt_get_priv(ra); > LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_delete\n", 0, 0, 0 ); > > PR_ASSERT(dp != NULL); > > 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 ); > > } > > int windows_private_get_isnt4(const Repl_Agmt *ra) > { >@@ -396,49 +403,51 @@ > PR_ASSERT (dp); > > LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_replarea\n", 0, 0, 0 ); > > return dp->directory_subtree; > } > > /* 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; > > LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_replarea\n", 0, 0, 0 ); > > PR_ASSERT(ra); > PR_ASSERT(sdn); > > 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; > > LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_directory_replarea\n", 0, 0, 0 ); > > PR_ASSERT(ra); > PR_ASSERT(sdn); > > 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 ); > } > > PRBool windows_private_create_users(const Repl_Agmt *ra) > { > Dirsync_Private *dp; > >@@ -511,28 +520,32 @@ > > */ > 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 ); > > PR_ASSERT(ra); > > dp = (Dirsync_Private *) agmt_get_priv(ra); > PR_ASSERT (dp); > ber = ber_alloc(); > > 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); > > LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_dirsync_control\n", 0, 0, 0 ); > > > return control; > >@@ -782,8 +795,394 @@ > slapi_sdn_free( &sdn); > slapi_pblock_destroy (pb); > > LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_load_dirsync_cookie\n", 0, 0, 0 ); > > 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); >+} >Index: ldapserver/ldap/servers/plugins/replication/windows_protocol_util.c >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/windows_protocol_util.c,v >retrieving revision 1.38 >diff -u -8 -r1.38 windows_protocol_util.c >--- ldapserver/ldap/servers/plugins/replication/windows_protocol_util.c 19 Oct 2007 02:09:24 -0000 1.38 >+++ ldapserver/ldap/servers/plugins/replication/windows_protocol_util.c 5 Aug 2008 17:16:28 -0000 >@@ -663,16 +663,17 @@ > /* Couldn't get a current CSN */ > slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, > "%s: Unable to obtain current CSN. " > "Replication is aborting.\n", > agmt_get_long_name(prp->agmt)); > return_value = ACQUIRE_FATAL_ERROR; > } > slapi_sdn_free(&replarea_sdn); >+ csn_free(¤t_csn); > } > } > > if (ACQUIRE_SUCCESS != return_value) > { > /* could not acquire the replica, so reinstate the linger timer, since this > means we won't call release_replica, which also reinstates the timer */ > windows_conn_start_linger(conn); >@@ -999,17 +1000,16 @@ > > /* We can't use a GUID DN, so rewrite to the new mapped DN. */ > cn_string = slapi_entry_attr_get_charptr(local_entry,"cn"); > if (!cn_string) { > cn_string = slapi_entry_attr_get_charptr(local_entry,"ntuserdomainid"); > } > > if (cn_string) { >- char *rdnstr = NULL; > char *container_str = NULL; > const char *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)); > new_dn_string = PR_smprintf("cn=%s,%s%s", cn_string, container_str, suffix); > > if (new_dn_string) { >@@ -1179,25 +1179,53 @@ > op2string(op->operation_type), op->target_address.dn); > goto error; > } > slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, > "%s: windows_replay_update: Processing %s operation local dn=\"%s\" remote dn=\"%s\"\n", > 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; > case SLAPI_OPERATION_MODIFY: > { > 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 ) > { > return_value = CONN_OPERATION_SUCCESS; > } else > { > if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) > { >@@ -1299,17 +1327,17 @@ > static int > is_straight_mapped_attr(const char *type, int is_user /* or group */, int is_nt4) > { > int found = 0; > size_t offset = 0; > 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)) > { > found = 1; > break; > } > offset++; > } >@@ -1322,17 +1350,17 @@ > char *new_type = NULL; > windows_attribute_map *our_map = is_user ? user_attribute_map : group_attribute_map; > windows_attribute_map *this_map = NULL; > size_t offset = 0; > > *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; > > if (NULL == their_name) > { > /* End of the list */ > break; >@@ -1495,17 +1523,16 @@ > > /* AD treats streetAddress as a single-valued attribute, while we define it > * as a multi-valued attribute as it's defined in rfc 4519. We only > * sync the first value to AD to avoid a constraint violation. > */ > 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; > > i = slapi_valueset_first_value(vs,&value); > if (i >= 0) { > /* Dup the first value, trash the valueset, then copy > * in the dup'd value. */ > new_value = slapi_value_dup(value); >@@ -2021,32 +2048,45 @@ > Slapi_PBlock *pb = slapi_pblock_new(); > Slapi_Entry **entries = NULL, **ep = NULL; > Slapi_Entry *entry_found = NULL; > char *query = NULL; > int found_or_not = ENTRY_NOTFOUND; > 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; > > query = slapi_ch_smprintf("(%s=%s)", attribute, value); > > if (query == NULL) > 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) > { > goto done; > } > > slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries); >@@ -2091,17 +2131,17 @@ > > /* Remove dashes from a GUID string. */ > static void > dedash_guid(char *str) > { > char *p = str; > char c = '\0'; > >- while (c = *p) >+ while ((c = *p)) > { > if ('-' == c) > { > /* Move on down please */ > char *q = p; > char *r = q + 1; > while (*r) > { >@@ -2249,17 +2289,17 @@ > /* the GUID is in a different form in the tombstone DN, so > * we need to transform it from the way we store it. */ > decrypt_guid(guid); > dash_guid(&guid); > } > > /* 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="); > } > > if (cn && guid && suffix) { > tombstone_dn = PR_smprintf("cn=%s\\0ADEL:%s,cn=Deleted Objects,%s", > cn, guid, suffix); > >@@ -2353,25 +2393,24 @@ > } > > static Slapi_DN *make_dn_from_guid(char *guid, int is_nt4, const char* suffix) > { > Slapi_DN *new_dn = NULL; > char *dn_string = NULL; > if (guid) > { >- new_dn = slapi_sdn_new(); > if (is_nt4) > { > dn_string = PR_smprintf("GUID=%s,%s",guid,suffix); > } else > { > 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 */ > return new_dn; > } > > static char* > extract_container(const Slapi_DN *entry_dn, const Slapi_DN *suffix_dn) >@@ -2447,16 +2486,17 @@ > Slapi_Entry *remote_entry = NULL; > new_dn = make_dn_from_guid(guid, is_nt4, suffix); > slapi_ch_free_string(&guid); > /* There are certain cases where we will have a GUID, but the entry does not exist in > * AD. This happens when you delete an entry, then add it back elsewhere in the tree > * 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 { > /* We need to re-write the DN to a non-GUID DN if we're syncing to a > * Windows 2000 Server since tombstone reanimation is not supported. > * If we're syncing with Windows 2003 Server, we'll just use the GUID > * to reanimate the tombstone when processing the add operation. */ > *missing_entry = 1; >@@ -2466,17 +2506,16 @@ > > /* We can't use a GUID DN, so rewrite to the mapped DN. */ > cn_string = slapi_entry_attr_get_charptr(e,"cn"); > if (!cn_string) { > cn_string = slapi_entry_attr_get_charptr(e,"ntuserdomainid"); > } > > if (cn_string) { >- char *rdnstr = NULL; > char *container_str = NULL; > > container_str = extract_container(slapi_entry_get_sdn_const(e), > windows_private_get_directory_subtree(prp->agmt)); > new_dn_string = PR_smprintf("cn=%s,%s%s", cn_string, container_str, suffix); > > if (new_dn_string) { > if (new_dn) { >@@ -2714,19 +2753,33 @@ > const char *suffix = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra)); > char *container_str = NULL; > > container_str = extract_container(slapi_entry_get_sdn_const(e), windows_private_get_windows_subtree(ra)); > /* Local DNs for users and groups are different */ > 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); > slapi_ch_free_string(&container_str); > /* Clear any earlier error */ > retval = 0; > } else > { >@@ -2934,28 +2987,41 @@ > /* Fatal error : need the guid */ > goto error; > } > /* Hack for NT4, which has no surname */ > if (is_nt4 && is_user) > { > 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(); > slapi_add_entry_internal_set_pb(pb, local_entry, NULL,repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),0); > slapi_add_internal_pb(pb); > slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval); > > if (retval) { > slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, > "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); > } > if (username) > { > slapi_ch_free_string(&username); > } >@@ -3110,17 +3176,16 @@ > slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type); > > if ((0 == slapi_attr_type_cmp(local_type, "streetAddress", > SLAPI_TYPE_CMP_SUBTYPE) && to_windows)) { > /* streetAddress is single-valued in AD, so make > * 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; > > i = slapi_valueset_first_value(vs,&value); > if (i >= 0) { > /* Dup the first value, trash the valueset, then copy > * in the dup'd value. */ > new_value = slapi_value_dup(value); >@@ -3224,17 +3289,16 @@ > } else > { > if ((0 == slapi_attr_type_cmp(local_type, "streetAddress", > SLAPI_TYPE_CMP_SUBTYPE) && to_windows)) { > /* streetAddress is single-valued in AD, so make > * 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; > > i = slapi_valueset_first_value(vs,&value); > if (i >= 0) { > /* Dup the first value, trash the valueset, then copy > * in the dup'd value. */ > new_value = slapi_value_dup(value); >@@ -3313,16 +3377,50 @@ > *do_modify = 1; > } > } > > entry_next_deleted_attribute(remote_entry, &del_attr); > 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"); > } > LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_generate_update_mods: %d\n", retval, 0, 0 ); > return retval; > } > >@@ -3407,20 +3505,26 @@ > static int > windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* remote_dn, int missing_entry) > { > int retval = 0; > LDAPMod **entryattrs = NULL; > 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) > { > (void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */, &entryattrs); > slapi_entry_free(mapped_entry); > mapped_entry = NULL; > if (NULL == entryattrs) > { >Index: ldapserver/ldap/servers/plugins/replication/windows_tot_protocol.c >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/windows_tot_protocol.c,v >retrieving revision 1.12 >diff -u -8 -r1.12 windows_tot_protocol.c >--- ldapserver/ldap/servers/plugins/replication/windows_tot_protocol.c 18 Oct 2007 00:08:31 -0000 1.12 >+++ ldapserver/ldap/servers/plugins/replication/windows_tot_protocol.c 5 Aug 2008 17:16:28 -0000 >@@ -94,21 +94,25 @@ > * - send an EndReplicationRequest extended operation > */ > static void > 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 ); > > PR_ASSERT(NULL != prp); > > prp->stopped = 0; > if (prp->terminate) > { >@@ -163,34 +167,43 @@ > * 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); > > > /* 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; > cb_data.num_entries = 0UL; > cb_data.sleep_on_busy = 0UL; > cb_data.last_busy = current_time (); > > slapi_search_internal_callback_pb (pb, &cb_data /* 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); > agmt_set_last_init_end(prp->agmt, current_time()); > 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: " >Index: ldapserver/ldap/servers/plugins/replication/windowsrepl.h >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/replication/windowsrepl.h,v >retrieving revision 1.14 >diff -u -8 -r1.14 windowsrepl.h >--- ldapserver/ldap/servers/plugins/replication/windowsrepl.h 27 Sep 2007 18:33:30 -0000 1.14 >+++ ldapserver/ldap/servers/plugins/replication/windowsrepl.h 5 Aug 2008 17:16:28 -0000 >@@ -39,43 +39,52 @@ > #ifdef HAVE_CONFIG_H > # include <config.h> > #endif > > > /* 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); > ConnResult windows_search_entry(Repl_Connection *conn, char* searchbase, char *filter, Slapi_Entry **entry); > ConnResult windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter, Slapi_Entry **entry, LDAPControl **serverctrls); > Slapi_Entry *windows_conn_get_search_result(Repl_Connection *conn ); > void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls ); > PRBool windows_private_dirsync_has_more(const Repl_Agmt *ra); > void windows_private_null_dirsync_cookie(const Repl_Agmt *ra); > int windows_private_save_dirsync_cookie(const Repl_Agmt *ra); > int windows_private_load_dirsync_cookie(const Repl_Agmt *ra); > void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value); > 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); > 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); > void windows_conn_disconnect(Repl_Connection *conn); > void windows_conn_delete(Repl_Connection *conn); > void windows_conn_get_error(Repl_Connection *conn, int *operation, int *error); > ConnResult windows_conn_send_add(Repl_Connection *conn, const char *dn, LDAPMod **attrs, > LDAPControl **server_controls, LDAPControl ***returned_controls); >@@ -107,8 +116,91 @@ > /* Used to work around contrained attribute legth for initials on AD */ > #define AD_INITIALS_LENGTH 6 > /* Used to check for pre-hashed passwords when syncing */ > #define PASSWD_CLEAR_PREFIX "{clear}" > #define PASSWD_CLEAR_PREFIX_LEN 7 > /* 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 */ >Index: ldapserver/ldap/servers/slapd/charray.c >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/charray.c,v >retrieving revision 1.7 >diff -u -8 -r1.7 charray.c >--- ldapserver/ldap/servers/slapd/charray.c 27 Jun 2008 19:28:21 -0000 1.7 >+++ ldapserver/ldap/servers/slapd/charray.c 5 Aug 2008 17:16:28 -0000 >@@ -241,16 +241,21 @@ > * slapi_get_supported_controls_copy > */ > void > 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 > charray_inlist( > char **a, > char *s > ) > { >Index: ldapserver/ldap/servers/slapd/control.c >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/control.c,v >retrieving revision 1.7 >diff -u -8 -r1.7 control.c >--- ldapserver/ldap/servers/slapd/control.c 10 Nov 2006 23:45:40 -0000 1.7 >+++ ldapserver/ldap/servers/slapd/control.c 5 Aug 2008 17:16:28 -0000 >@@ -469,37 +469,61 @@ > > return( 0 ); > } > > > /* > * 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; > > if ( *ctrlsp == NULL ) { > count = 0; > } else { > for ( count = 0; (*ctrlsp)[count] != NULL; ++count ) { > ; > } > } > > *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" > */ > LDAPControl * > slapi_dup_control( LDAPControl *ctrl ) > { > LDAPControl *rctrl; >@@ -522,16 +546,24 @@ > slapi_ch_malloc( ctrl->ldctl_value.bv_len ); > memcpy( rctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_val, > ctrl->ldctl_value.bv_len ); > } > > 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, > char iscritical, LDAPControl **ctrlp ) > { > int rc = 0; > int return_value = LDAP_SUCCESS; > struct berval *bvp = NULL; >Index: ldapserver/ldap/servers/slapd/slapi-plugin.h >=================================================================== >RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-plugin.h,v >retrieving revision 1.26 >diff -u -8 -r1.26 slapi-plugin.h >--- ldapserver/ldap/servers/slapd/slapi-plugin.h 15 Jul 2008 16:49:42 -0000 1.26 >+++ ldapserver/ldap/servers/slapd/slapi-plugin.h 5 Aug 2008 17:16:28 -0000 >@@ -830,16 +830,34 @@ > #define SLAPI_OPERATION_NONE 0x00000000UL > int slapi_get_supported_controls_copy( char ***ctrloidsp, > unsigned long **ctrlopsp ); > int slapi_build_control( char *oid, BerElement *ber, > char iscritical, LDAPControl **ctrlp ); > 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 > */ > char **slapi_get_supported_extended_ops_copy( void ); > > > /* >@@ -860,16 +878,23 @@ > #define LDAP_PWPOLICY_PWDTOOSHORT 6 > #define LDAP_PWPOLICY_PWDTOOYOUNG 7 > #define LDAP_PWPOLICY_PWDINHISTORY 8 > > /* > * 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 ); > > > /* > * checking routines for allocating and freeing memory > */ > char * slapi_ch_malloc( unsigned long size ); > char * slapi_ch_realloc( char *block, unsigned long size ); > char * slapi_ch_calloc( unsigned long nelem, unsigned long size );
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 457846
:
313410
|
313411
| 313466 |
313487
|
315142
|
315153
|
316473
|
317429
|
317534
|
317540
|
317614
|
317626
|
317628