summaryrefslogtreecommitdiffstats
path: root/ldap
diff options
context:
space:
mode:
authorDavid Boreham <dboreham@redhat.com>2005-04-14 16:58:10 +0000
committerDavid Boreham <dboreham@redhat.com>2005-04-14 16:58:10 +0000
commit5fae88759d82d2c36adcc4c18db412e3fe4d9541 (patch)
tree0c09fa9f284fb223419231581e721d7dddc51f75 /ldap
parent4679cdaa34172bb7e5a3eea6644271f25bfba4b6 (diff)
downloadds-5fae88759d82d2c36adcc4c18db412e3fe4d9541.tar.gz
ds-5fae88759d82d2c36adcc4c18db412e3fe4d9541.tar.xz
ds-5fae88759d82d2c36adcc4c18db412e3fe4d9541.zip
Fixes for windows sync for NT4
Diffstat (limited to 'ldap')
-rw-r--r--ldap/servers/plugins/replication/repl5_ruv.c19
-rw-r--r--ldap/servers/plugins/replication/repl5_ruv.h1
-rw-r--r--ldap/servers/plugins/replication/windows_connection.c16
-rw-r--r--ldap/servers/plugins/replication/windows_inc_protocol.c4
-rw-r--r--ldap/servers/plugins/replication/windows_private.c45
-rw-r--r--ldap/servers/plugins/replication/windows_protocol_util.c279
-rw-r--r--ldap/servers/plugins/replication/windowsrepl.h3
7 files changed, 289 insertions, 78 deletions
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index a8891833..fa37865a 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -1876,6 +1876,25 @@ ruv_is_newer (Object *sruvobj, Object *cruvobj)
return is_newer;
}
+void
+force_csn_update (RUV *ruv, CSN *csn)
+{
+ CSN *max;
+
+ if (ruv != NULL)
+ {
+
+ ruv_get_max_csn(ruv, &max);
+
+ if (csn_compare(max, csn))
+ ruv_set_max_csn(ruv, csn, NULL);
+
+ csn_free(&max);
+ }
+
+
+}
+
#ifdef TESTING /* Some unit tests for code in this file */
static void
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index 29d87000..60ac1902 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -81,6 +81,7 @@ int ruv_local_contains_supplier(RUV *ruv, ReplicaId rid);
whether or not an RUV is empty */
PRBool ruv_has_csns(const RUV *ruv);
PRBool ruv_is_newer (Object *sruv, Object *cruv);
+void force_csn_update (RUV *ruv, CSN *csn);
#ifdef __cplusplus
}
#endif
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index 96593e84..d8c3c9d6 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -1149,8 +1149,20 @@ windows_conn_connect(Repl_Connection *conn)
conn->state = STATE_CONNECTED;
return_value = CONN_OPERATION_SUCCESS;
}
-
- windows_conn_replica_supports_dirsync(conn);
+
+ {
+ ConnResult supports = 0;
+ supports = windows_conn_replica_supports_dirsync(conn);
+ if (CONN_DOES_NOT_SUPPORT_DIRSYNC == supports)
+ {
+ /* We assume that a server that doesn't support dirsync is our NT4 LDAP service */
+ windows_private_set_isnt4(conn->agmt,1);
+ LDAPDebug( LDAP_DEBUG_REPL, "windows_conn_connect : detected NT4 peer\n", 0, 0, 0 );
+ } else
+ {
+ windows_private_set_isnt4(conn->agmt,0);
+ }
+ }
ber_bvfree(creds);
creds = NULL;
diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c
index f588d6ba..b80e48bd 100644
--- a/ldap/servers/plugins/replication/windows_inc_protocol.c
+++ b/ldap/servers/plugins/replication/windows_inc_protocol.c
@@ -468,7 +468,7 @@ windows_inc_run(Private_Repl_Protocol *prp)
object_acquire(prp->replica_object);
replica = object_get_data(prp->replica_object);
- rc = windows_acquire_replica(prp, &ruv , 1 /* yes, check the consumer RUV for incremental */);
+ rc = windows_acquire_replica(prp, &ruv , (run_dirsync == 0) /* yes, check the consumer RUV for incremental, but not if we're going to dirsync afterwards */);
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
"windows_acquire_replica returned %s (%d)\n",
@@ -1295,7 +1295,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
agmt_inc_last_update_changecount (prp->agmt, csn_get_replicaid(entry.op->csn), 0 /*replayed*/);
/* bring the consumers (AD) RUV up to date */
- /* DBDB removed because it breaks server startup ruv_set_max_csn(remote_update_vector,entry.op->csn, NULL ); */
+ force_csn_update(remote_update_vector, entry.op->csn);
}
break;
case CL5_BAD_DATA:
diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c
index 001e57bb..cdeb9845 100644
--- a/ldap/servers/plugins/replication/windows_private.c
+++ b/ldap/servers/plugins/replication/windows_private.c
@@ -27,6 +27,7 @@ struct windowsprivate {
PRBool create_users_from_dirsync;
PRBool create_groups_from_dirsync;
char *windows_domain;
+ int isnt4;
};
void
@@ -64,6 +65,18 @@ windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e)
}
}
+const char* windows_private_get_purl(const Repl_Agmt *ra)
+{
+ const char* windows_purl;
+ char *hostname;
+
+ hostname = agmt_get_hostname(ra);
+ windows_purl = slapi_ch_smprintf("ldap://%s:%d", hostname, agmt_get_port(ra));
+ slapi_ch_free_string(&hostname);
+
+ return windows_purl;
+}
+
Dirsync_Private* windows_private_new()
{
Dirsync_Private *dp;
@@ -96,6 +109,38 @@ void windows_agreement_delete(Repl_Agmt *ra)
}
+int windows_private_get_isnt4(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_isnt4\n", 0, 0, 0 );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_isnt4\n", 0, 0, 0 );
+
+ return dp->isnt4;
+}
+
+void windows_private_set_isnt4(const Repl_Agmt *ra, int isit)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_isnt4\n", 0, 0, 0 );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ dp->isnt4 = isit;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_isnt4\n", 0, 0, 0 );
+}
+
/* Returns a copy of the Slapi_DN pointer, no need to free it */
const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra)
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index a5956c5e..55f1bd88 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -32,12 +32,13 @@ static int is_subject_of_agreemeent_local(const Slapi_Entry *local_entry,const R
static int windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_entry, Slapi_DN *remote_sdn, Slapi_Entry **remote_entry, char** password);
static int windows_get_local_entry(const Slapi_DN* local_dn,Slapi_Entry **local_entry);
static int windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry);
-static int map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry);
+static int map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry, int want_guid);
static char* extract_ntuserdomainid_from_entry(Slapi_Entry *e);
static int windows_get_remote_entry (Private_Repl_Protocol *prp, Slapi_DN* remote_dn,Slapi_Entry **remote_entry);
static const char* op2string (int op);
static int is_subject_of_agreemeent_remote(Slapi_Entry *e, const Repl_Agmt *ra);
static int map_entry_dn_inbound(Slapi_Entry *e, const Slapi_DN **dn, const Repl_Agmt *ra);
+static int windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry);
/* Controls the direction of flow for mapped attributes */
@@ -73,6 +74,7 @@ typedef struct _windows_attribute_map
/* List of attributes that are common to AD and LDAP, so we simply copy them over in both directions */
static char* windows_user_matching_attributes[] =
{
+ "description",
"destinationIndicator",
"facsimileTelephoneNumber",
"givenName",
@@ -81,7 +83,6 @@ static char* windows_user_matching_attributes[] =
"initials",
"l",
"mail",
- "manager",
"mobile",
"o",
"ou",
@@ -90,7 +91,6 @@ static char* windows_user_matching_attributes[] =
"postOfficeBox",
"postalAddress",
"postalCode",
- "preferredDeliveryMethod",
"registeredAddress",
"seeAlso",
"sn",
@@ -144,8 +144,15 @@ static windows_attribute_map user_attribute_map[] =
{
{ "homeDirectory", "ntUserHomeDir", bidirectional, always, normal},
{ "scriptPath", "ntUserScriptPath", bidirectional, always, normal},
- { "lastLogon", "ntUserLastLogon", bidirectional, always, normal},
- { "lastLogoff", "ntUserLastLogoff", bidirectional, always, normal},
+ { "lastLogon", "ntUserLastLogon", fromwindowsonly, always, normal},
+ { "lastLogoff", "ntUserLastLogoff", fromwindowsonly, always, normal},
+ { "accountExpires", "ntUserAcctExpires", bidirectional, always, normal},
+ { "codePage", "ntUserCodePage", bidirectional, always, normal},
+ { "logonHours", "ntUserLogonHours", bidirectional, always, normal},
+ { "maxStorage", "ntUserMaxStorage", bidirectional, always, normal},
+ { "profilePath", "ntUserParms", bidirectional, always, normal},
+ { "userParameters", "ntUserProfile", bidirectional, always, normal},
+ { "userWorkstations", "ntUserWorkstations", bidirectional, always, normal},
{ "sAMAccountName", "ntUserDomainId", bidirectional, createonly, normal},
/* cn is a naming attribute in AD, so we don't want to change it after entry creation */
{ "cn", "cn", towindowsonly, createonly, normal},
@@ -153,17 +160,31 @@ static windows_attribute_map user_attribute_map[] =
{ "name", "cn", fromwindowsonly, always, normal},
{ "manager", "manager", bidirectional, always, dnmap},
{ "secretary", "secretary", bidirectional, always, dnmap},
+ { "seealso", "seealso", bidirectional, always, dnmap},
{NULL, NULL, -1}
};
static windows_attribute_map group_attribute_map[] =
{
- { "ntGroupType", "groupType", bidirectional, createonly, normal},
+ { "groupType", "ntGroupType", bidirectional, createonly, normal},
{ "sAMAccountName", "ntUserDomainId", bidirectional, createonly, normal},
{ "member", "uniquemember", bidirectional, always, dnmap},
{NULL, NULL, -1}
};
+/*
+ * Notes on differences for NT4:
+ * 1. NT4 returns the SID value in the objectGUID attribute value.
+ * The SID has variable length and does not match the length of a GUID.
+ * 2. NT4 currently never generates tombstones. If it did, we'd need to parse the
+ * different form of the GUID in the tombstone DNs.
+ * 3. NT4 Does not implement the dirsync control. We always get all users and groups.
+ * 4. NT4 generates and expects DNs with samaccountname as the RDN, not cn.
+ * 5. NT4 handles the DN=<GUID> (remember that the '<' '>' characters are included!) DN form
+ * for modifies and deletes, provided we use the value it gave us in the objectGUID attribute (which is actually the SID).
+ * 6. NT4 has less and different schema from AD. For example users in NT4 have no firstname/lastname, only an optional 'description'.
+ */
+
static const char*
op2string(int op)
{
@@ -185,17 +206,19 @@ op2string(int op)
return "unknown";
}
-
static void
windows_dump_entry(const char *string, Slapi_Entry *e)
{
int length = 0;
char *buffer = NULL;
- buffer = slapi_entry2str(e,&length);
- slapi_log_error(SLAPI_LOG_REPL, NULL, "Windows sync entry: %s %s\n", string, buffer);
- if (buffer)
+ if (slapi_is_loglevel_set(SLAPI_LOG_REPL))
{
- slapi_ch_free((void**)&buffer);
+ buffer = slapi_entry2str(e,&length);
+ slapi_log_error(SLAPI_LOG_REPL, NULL, "Windows sync entry: %s %s\n", string, buffer);
+ if (buffer)
+ {
+ slapi_ch_free((void**)&buffer);
+ }
}
}
@@ -234,7 +257,7 @@ map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_
is_ours = is_subject_of_agreemeent_local(local_entry,prp->agmt);
if (is_ours)
{
- map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry);
+ map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 0 /* don't want GUID form here */);
if (remote_dn)
{
if (!missing_entry)
@@ -682,11 +705,6 @@ delete_remote_entry_allowed(Slapi_Entry *e)
}
static void
-windows_make_mods_for_add_retry(Slapi_Entry *local_entry, Slapi_Entry *remote_entry, LDAPMod ***result_mods, int is_user)
-{
-}
-
-static void
windows_log_add_entry_remote(const Slapi_DN *local_dn,const Slapi_DN *remote_dn)
{
const char* local_dn_string = slapi_sdn_get_dn(local_dn);
@@ -743,27 +761,16 @@ process_replay_add(Private_Repl_Protocol *prp, slapi_operation_parameters *op, S
}
} else
{
- /* Need to re-play this as a mod */
- LDAPMod **mapped_mods = NULL;
+
Slapi_Entry *remote_entry = NULL;
/* Fetch the remote entry */
rc = windows_get_remote_entry(prp, remote_dn,&remote_entry);
if (0 == rc && remote_entry) {
- windows_make_mods_for_add_retry(op->p.p_add.target_entry, remote_entry, &mapped_mods, is_user);
- /* 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
- {
- return_value = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(remote_dn),mapped_mods, NULL,NULL);
- }
- if (mapped_mods)
- {
- ldap_mods_free(mapped_mods,1);
- mapped_mods = NULL;
- }
+ return_value = windows_update_remote_entry(prp,remote_entry,local_entry);
+ }
+ if (remote_entry)
+ {
slapi_entry_free(remote_entry);
}
}
@@ -811,7 +818,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
windows_is_local_entry_user_or_group(local_entry,&is_user,&is_group);
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "%s: windows_replay_update: Looking at %s operation dn=\"%s\" (%s,%s,%s)\n",
+ "%s: windows_replay_update: Looking at %s operation local dn=\"%s\" (%s,%s,%s)\n",
agmt_get_long_name(prp->agmt),
op2string(op->operation_type), op->target_address.dn, is_ours ? "ours" : "not ours",
is_user ? "user" : "not user", is_group ? "group" : "not group");
@@ -819,7 +826,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
if (is_ours && (is_user || is_group) ) {
int missing_entry = 0;
/* Make the entry's DN */
- rc = map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry);
+ rc = map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry, 1);
if (rc || NULL == remote_dn)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
@@ -828,6 +835,10 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
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 */
case SLAPI_OPERATION_ADD:
@@ -988,7 +999,8 @@ windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_ent
Slapi_Entry *new_entry = NULL;
Slapi_PBlock* pb = NULL;
int rc = 0;
- int is_user = 1; /* DBDB need to add code to test for group here */
+ int is_user = 0;
+ int is_group = 0;
Slapi_Attr *attr = NULL;
char *username = NULL;
const char *dn_string = NULL;
@@ -1012,7 +1024,7 @@ windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_ent
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_create_remote_entry\n", 0, 0, 0 );
- remote_entry_template = is_user ? remote_user_entry_template : remote_group_entry_template;
+ windows_is_local_entry_user_or_group(original_entry,&is_user,&is_group);
/* Create a new entry */
/* Give it its DN and samaccountname */
@@ -1023,7 +1035,13 @@ windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_ent
}
fqusername = PR_smprintf("%s@%s",username,domain_name);
dn_string = slapi_sdn_get_dn(remote_sdn);
- entry_string = slapi_ch_smprintf(remote_entry_template, dn_string, fqusername);
+ if (is_user)
+ {
+ entry_string = slapi_ch_smprintf(remote_user_entry_template, dn_string, fqusername);
+ } else
+ {
+ entry_string = slapi_ch_smprintf(remote_group_entry_template, dn_string);
+ }
PR_smprintf_free(fqusername);
if (NULL == entry_string)
{
@@ -1102,7 +1120,10 @@ error:
{
slapi_ch_free((void**)&username);
}
- windows_dump_entry("Created new remote entry:\n",new_entry);
+ if (new_entry)
+ {
+ windows_dump_entry("Created new remote entry:\n",new_entry);
+ }
LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_create_remote_entry: %d\n", retval, 0, 0 );
return retval;
}
@@ -1526,7 +1547,7 @@ convert_to_hex(Slapi_Value *val)
}
static char*
-extract_guid_from_entry(Slapi_Entry *e)
+extract_guid_from_entry(Slapi_Entry *e, int is_nt4)
{
char *guid = NULL;
Slapi_Value *val = NULL;
@@ -1537,7 +1558,13 @@ extract_guid_from_entry(Slapi_Entry *e)
{
slapi_attr_first_value(attr, &val);
if (val) {
- guid = convert_to_hex(val);
+ if (is_nt4)
+ {
+ guid = slapi_ch_strdup(slapi_value_get_string(val));
+ } else
+ {
+ guid = convert_to_hex(val);
+ }
}
}
return guid;
@@ -1575,14 +1602,20 @@ extract_ntuserdomainid_from_entry(Slapi_Entry *e)
return uid;
}
-static Slapi_DN *make_dn_from_guid(char *guid)
+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();
- dn_string = PR_smprintf("<GUID=%s>",guid);
+ 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);
PR_smprintf_free(dn_string);
}
@@ -1592,11 +1625,13 @@ static Slapi_DN *make_dn_from_guid(char *guid)
/* Given a non-tombstone entry, return the DN of its peer in AD (whether present or not) */
static int
-map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry)
+map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry, int guid_form)
{
int retval = 0;
char *guid = NULL;
Slapi_DN *new_dn = NULL;
+ int is_nt4 = windows_private_get_isnt4(prp->agmt);
+ const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
/* To find the DN of the peer entry we first look for an ntUniqueId attribute
* on the local entry. If that's present, we generate a GUID-form DN.
* If there's no GUID, then we look for an ntUserDomainId attribute
@@ -1610,9 +1645,9 @@ map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol
*missing_entry = 0;
guid = slapi_entry_attr_get_charptr(e,"ntUniqueId");
- if (guid)
+ if (guid && guid_form)
{
- new_dn = make_dn_from_guid(guid);
+ new_dn = make_dn_from_guid(guid, is_nt4, suffix);
slapi_ch_free((void**)&guid);
} else
{
@@ -1629,7 +1664,6 @@ map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol
} else {
if (0 == retval)
{
- const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
char *new_dn_string = NULL;
char *cn_string = NULL;
@@ -1647,7 +1681,11 @@ map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol
}
if (cn_string)
{
- new_dn_string = PR_smprintf("cn=%s,%s",cn_string,suffix);
+ char *rdnstr = NULL;
+
+ rdnstr = is_nt4 ? "samaccountname=%s,%s" : "cn=%s,%s";
+
+ new_dn_string = PR_smprintf(rdnstr,cn_string,suffix);
if (new_dn_string)
{
new_dn = slapi_sdn_new_dn_byval(new_dn_string);
@@ -1748,6 +1786,7 @@ map_entry_dn_inbound(Slapi_Entry *e, const Slapi_DN **dn, const Repl_Agmt *ra)
Slapi_Entry *matching_entry = NULL;
int is_user = 0;
int is_group = 0;
+ int is_nt4 = windows_private_get_isnt4(ra);
/* To map a non-tombstone's DN we need to first try to look it up by GUID.
* If we do not find it, then we need to generate the DN that it would have if added as a new entry.
@@ -1756,7 +1795,7 @@ map_entry_dn_inbound(Slapi_Entry *e, const Slapi_DN **dn, const Repl_Agmt *ra)
windows_is_remote_entry_user_or_group(e,&is_user,&is_group);
- guid = extract_guid_from_entry(e);
+ guid = extract_guid_from_entry(e, is_nt4);
if (guid)
{
retval = find_entry_by_guid(guid,&matching_entry,ra);
@@ -1935,14 +1974,27 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
int is_user = 0;
int is_group = 0;
char *local_entry_template = NULL;
+ char *user_entry_template = NULL;
char *username = extract_username_from_entry(remote_entry);
Slapi_Attr *attr = NULL;
int rc = 0;
char *guid_str = NULL;
+ int is_nt4 = windows_private_get_isnt4(prp->agmt);
char *local_user_entry_template =
"dn: %s\n"
"objectclass:top\n"
+ "objectclass:person\n"
+ "objectclass:organizationalperson\n"
+ "objectclass:inetOrgPerson\n"
+ "objectclass:ntUser\n"
+ "ntUserDeleteAccount:true\n"
+ "uid:%s\n";
+
+ char *local_nt4_user_entry_template =
+ "dn: %s\n"
+ "objectclass:top\n"
+ "objectclass:person\n"
"objectclass:organizationalperson\n"
"objectclass:inetOrgPerson\n"
"objectclass:ntUser\n"
@@ -1961,7 +2013,8 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_create_local_entry\n", 0, 0, 0 );
windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
- local_entry_template = is_user ? local_user_entry_template : local_group_entry_template;
+ user_entry_template = is_nt4 ? local_nt4_user_entry_template : local_user_entry_template;
+ local_entry_template = is_user ? user_entry_template : local_group_entry_template;
/* Create a new entry */
/* Give it its DN and username */
entry_string = slapi_ch_smprintf(local_entry_template,slapi_sdn_get_dn(local_sdn),username, username);
@@ -2022,7 +2075,7 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
}
}
/* Copy over the GUID */
- guid_str = extract_guid_from_entry(remote_entry);
+ guid_str = extract_guid_from_entry(remote_entry, is_nt4);
if (guid_str)
{
slapi_entry_add_string(local_entry,"ntUniqueId",guid_str);
@@ -2033,6 +2086,11 @@ windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
/* Fatal error : need the guid */
goto error;
}
+ /* Hack for NT4, which has no surname */
+ if (is_nt4)
+ {
+ slapi_entry_add_string(local_entry,"sn",username);
+ }
/* Store it */
windows_dump_entry("Adding new local entry",local_entry);
pb = slapi_pblock_new();
@@ -2058,22 +2116,26 @@ error:
}
static int
-windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
+windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry, int to_windows, Slapi_Mods *smods, int *do_modify)
{
int retval = 0;
- Slapi_Mods smods = {0};
Slapi_Attr *attr = NULL;
- int do_modify = 0;
int is_user = 0;
int is_group = 0;
int rc = 0;
- Slapi_PBlock *pb = NULL;
+ int is_nt4 = windows_private_get_isnt4(prp->agmt);
/* Iterate over the attributes on the remote entry, updating the local entry where appropriate */
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_update_local_entry\n", 0, 0, 0 );
- windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
+ *do_modify = 0;
+ if (to_windows)
+ {
+ windows_is_local_entry_user_or_group(remote_entry,&is_user,&is_group);
+ } else
+ {
+ windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
+ }
- slapi_mods_init (&smods, 0);
for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0;
rc = slapi_entry_next_attr(remote_entry, attr, &attr))
{
@@ -2092,7 +2154,7 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
/* First determine what we will do with this attr */
/* If it's a GUID, we need to take special action */
- if (0 == slapi_attr_type_cmp(type,"objectGuid",SLAPI_TYPE_CMP_SUBTYPE))
+ if (0 == slapi_attr_type_cmp(type,"objectGuid",SLAPI_TYPE_CMP_SUBTYPE) && !to_windows)
{
is_guid = 1;
local_type = slapi_ch_strdup("ntUniqueId");
@@ -2101,7 +2163,7 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
if ( is_straight_mapped_attr(type,is_user) ) {
local_type = slapi_ch_strdup(type);
} else {
- windows_map_attr_name(type , 0 /* from windows */, is_user, 0 /* not create */, &local_type, &mapdn);
+ windows_map_attr_name(type , to_windows, is_user, 0 /* not create */, &local_type, &mapdn);
}
is_guid = 0;
}
@@ -2127,18 +2189,18 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
if (mapdn)
{
Slapi_ValueSet *mapped_values = NULL;
- map_dn_values(prp,vs,&mapped_values, 1 /* to windows */);
+ map_dn_values(prp,vs,&mapped_values, to_windows);
if (mapped_values)
{
- slapi_mods_add_mod_values(&smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(mapped_values));
+ slapi_mods_add_mod_values(smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(mapped_values));
slapi_valueset_free(mapped_values);
mapped_values = NULL;
}
} else
{
- slapi_mods_add_mod_values(&smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(vs));
+ slapi_mods_add_mod_values(smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(vs));
}
- do_modify = 1;
+ *do_modify = 1;
} else
{
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
@@ -2152,17 +2214,31 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
if (is_guid)
{
/* Translate the guid value */
- char *guid = extract_guid_from_entry(remote_entry);
+ char *guid = extract_guid_from_entry(remote_entry, is_nt4);
if (guid)
{
- slapi_mods_add_string(&smods,LDAP_MOD_ADD,local_type,guid);
+ slapi_mods_add_string(smods,LDAP_MOD_ADD,local_type,guid);
slapi_ch_free((void**)&guid);
}
} else
{
- slapi_mods_add_mod_values(&smods,LDAP_MOD_ADD,local_type,valueset_get_valuearray(vs));
+ /* Handle DN valued attributes here */
+ if (mapdn)
+ {
+ Slapi_ValueSet *mapped_values = NULL;
+ map_dn_values(prp,vs,&mapped_values, to_windows);
+ if (mapped_values)
+ {
+ slapi_mods_add_mod_values(smods,LDAP_MOD_ADD,local_type,valueset_get_valuearray(mapped_values));
+ slapi_valueset_free(mapped_values);
+ mapped_values = NULL;
+ }
+ } else
+ {
+ slapi_mods_add_mod_values(smods,LDAP_MOD_ADD,local_type,valueset_get_valuearray(vs));
+ }
}
- do_modify = 1;
+ *do_modify = 1;
}
}
if (vs)
@@ -2176,8 +2252,49 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
local_type = NULL;
}
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_update_local_entry: %d\n", retval, 0, 0 );
+ return retval;
+}
+
+static int
+windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
+{
+ Slapi_Mods smods = {0};
+ int retval = 0;
+ int do_modify = 0;
+
+ slapi_mods_init (&smods, 0);
+ retval = windows_generate_update_mods(prp,local_entry,remote_entry,1,&smods,&do_modify);
+ /* Now perform the modify if we need to */
+ if (0 == retval && do_modify)
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "windows_update_remote_entry: modifying entry %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(remote_entry)));
+
+ retval = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(slapi_entry_get_sdn_const(remote_entry)),slapi_mods_get_ldapmods_byref(&smods), NULL,NULL);
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "no mods generated for entry: %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(remote_entry)));
+ }
+ slapi_mods_done(&smods);
+ return retval;
+}
+
+static int
+windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
+{
+ Slapi_Mods smods = {0};
+ int retval = 0;
+ int rc = 0;
+ Slapi_PBlock *pb = NULL;
+ int do_modify = 0;
+
+ slapi_mods_init (&smods, 0);
+
+ retval = windows_generate_update_mods(prp,remote_entry,local_entry,0,&smods,&do_modify);
/* Now perform the modify if we need to */
- if (do_modify)
+ if (0 == retval && do_modify)
{
int rc = 0;
pb = slapi_pblock_new();
@@ -2207,12 +2324,11 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
"no mods generated for entry: %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(remote_entry)));
}
slapi_mods_done(&smods);
- LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_update_local_entry: %d\n", retval, 0, 0 );
return retval;
}
static int
-windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* remote_dn)
+windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* remote_dn, int missing_entry)
{
int retval = 0;
LDAPMod **entryattrs = NULL;
@@ -2221,6 +2337,7 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r
const Slapi_DN* local_dn = NULL;
/* 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);
/* Convert entry to mods */
if (0 == retval && mapped_entry)
@@ -2245,7 +2362,21 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r
ldap_mods_free(entryattrs, 1);
entryattrs = NULL;
}
- }
+ } else
+ {
+ /* Entry already exists, need to mod it instead */
+ Slapi_Entry *remote_entry = NULL;
+ /* Get the remote entry */
+ retval = windows_get_remote_entry(prp, remote_dn,&remote_entry);
+ if (0 == retval && remote_entry)
+ {
+ retval = windows_update_remote_entry(prp,remote_entry,e);
+ }
+ if (remote_entry)
+ {
+ slapi_entry_free(remote_entry);
+ }
+ }
return retval;
}
@@ -2276,7 +2407,7 @@ int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e)
agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), is_ours ? "ours" : "not ours");
if (is_ours)
{
- retval = map_entry_dn_outbound(e,&remote_dn,prp,&missing_entry);
+ retval = map_entry_dn_outbound(e,&remote_dn,prp,&missing_entry,1 /* want GUID */);
if (retval || NULL == remote_dn)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
@@ -2290,7 +2421,7 @@ int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e)
retval = windows_process_total_delete(prp,e,remote_dn);
} else
{
- retval = windows_process_total_add(prp,e,remote_dn);
+ retval = windows_process_total_add(prp,e,remote_dn,missing_entry);
}
}
if (remote_dn)
@@ -2391,7 +2522,7 @@ windows_process_dirsync_entry(Private_Repl_Protocol *prp,Slapi_Entry *e, int is_
slapi_sdn_free(&local_sdn);
} else
{
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to map tombstone dn.\n",agmt_get_long_name(prp->agmt));
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to map tombstone dn.\n",agmt_get_long_name(prp->agmt));
}
} else
{
diff --git a/ldap/servers/plugins/replication/windowsrepl.h b/ldap/servers/plugins/replication/windowsrepl.h
index 8379dc6c..a1f05a18 100644
--- a/ldap/servers/plugins/replication/windowsrepl.h
+++ b/ldap/servers/plugins/replication/windowsrepl.h
@@ -24,6 +24,9 @@ void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value);
PRBool windows_private_create_users(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);
+const char* windows_private_get_purl(const Repl_Agmt *ra);
/* in windows_connection.c */
ConnResult windows_conn_connect(Repl_Connection *conn);