瀏覽代碼

Resolves: 243221
Summary: Trim initials attribute value when sync'ing to AD.

Nathan Kinder 18 年之前
父節點
當前提交
a4118d7929
共有 2 個文件被更改,包括 78 次插入15 次删除
  1. 76 15
      ldap/servers/plugins/replication/windows_protocol_util.c
  2. 2 0
      ldap/servers/plugins/replication/windowsrepl.h

+ 76 - 15
ldap/servers/plugins/replication/windows_protocol_util.c

@@ -1315,6 +1315,33 @@ windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_ent
 
 		if ( is_straight_mapped_attr(type,is_user,is_nt4) )
 		{
+			/* The initials attribute is a special case.  AD has a constraint
+                         * that limits the value length.  If we're sending a change to
+                         * the initials attribute to AD, we trim if neccessary.
+                         */
+                         if (0 == slapi_attr_type_cmp(type, "initials", SLAPI_TYPE_CMP_SUBTYPE)) {
+				int i = 0;
+				const char *initials_value = NULL;
+                                Slapi_Value *value = NULL;
+
+                                i = slapi_valueset_first_value(vs,&value);
+				while (i >= 0) {
+                                	initials_value = slapi_value_get_string(value);
+
+					/* If > AD_INITIALS_LENGTH, trim the value */
+					if (strlen(initials_value) > AD_INITIALS_LENGTH) {
+						char *new_initials = PL_strndup(initials_value, AD_INITIALS_LENGTH);
+						/* the below hands off memory */
+						slapi_value_set_string_passin(value, new_initials);
+						slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+							"%s: windows_create_remote_entry: "
+							"Trimming initials attribute to %d characters.\n",
+							agmt_get_long_name(prp->agmt), AD_INITIALS_LENGTH);
+					}
+
+					i = slapi_valueset_next_value(vs, i, &value);
+				}
+			}
 			/* copy over the attr values */
 			slapi_entry_add_valueset(new_entry,type,vs);
 		} else 
@@ -1461,7 +1488,26 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
 
 		/* Check to see if this attribute is passed through */
 		if (is_straight_mapped_attr(attr_type,is_user,is_nt4)) {
-			/* If so then just copy over the mod */
+			/* The initials attribute is a special case.  AD has a constraint
+			 * that limits the value length.  If we're sending a change to
+			 * the initials attribute to AD, we trim if neccessary.
+			 */
+			if (0 == slapi_attr_type_cmp(attr_type, "initials", SLAPI_TYPE_CMP_SUBTYPE)) {
+				int i;
+				for (i = 0; mod->mod_bvalues[i] != NULL; i++) {
+					/* If > AD_INITIALS_LENGTH, trim the value */
+					if (mod->mod_bvalues[i]->bv_len > AD_INITIALS_LENGTH) {
+						mod->mod_bvalues[i]->bv_val[AD_INITIALS_LENGTH] = '\0';
+						mod->mod_bvalues[i]->bv_len = AD_INITIALS_LENGTH;
+						slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+							"%s: windows_map_mods_for_replay: "
+							"Trimming initials attribute to %d characters.\n",
+							agmt_get_long_name(prp->agmt), AD_INITIALS_LENGTH);
+					}
+				}
+			}
+
+			/* copy over the mod */
 			slapi_mods_add_modbvps(&mapped_smods,mod->mod_op,attr_type,mod->mod_bvalues);
 		} else 
 		{
@@ -1521,9 +1567,12 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods,
 	LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_map_mods_for_replay\n", 0, 0, 0 );
 }
 
-/* Returns non-zero if the attribute value sets are identical */
-static int 
-attr_compare_equal(Slapi_Attr *a, Slapi_Attr *b)
+
+/* Returns non-zero if the attribute value sets are identical. If you want to
+ * compare the entire attribute value, set n to 0.  You can compare only the
+ * first n characters of the values by passing in the legth as n. */
+static int
+attr_compare_equal(Slapi_Attr *a, Slapi_Attr *b, int n)
 {
 	/* For now only handle single values */
 	Slapi_Value *va = NULL;
@@ -1535,23 +1584,25 @@ attr_compare_equal(Slapi_Attr *a, Slapi_Attr *b)
 	slapi_attr_get_numvalues(a,&num_a);
 	slapi_attr_get_numvalues(b,&num_b);
 
-	if (num_a == num_b) 
-	{
+	if (num_a == num_b) {
 		slapi_attr_first_value(a, &va);
 		slapi_attr_first_value(b, &vb);
 
-		if (va->bv.bv_len == vb->bv.bv_len) 
-		{
-			if (0 != memcmp(va->bv.bv_val,vb->bv.bv_val,va->bv.bv_len))
-			{
+		/* If either val is less than n, then check if the length, then values are
+		 * equal.  If both are n or greater, then only compare the first n chars. 
+		 * If n is 0, then just compare the entire attribute. */
+		if ((va->bv.bv_len < n) || (vb->bv.bv_len < n) || (n == 0)) {
+			if (va->bv.bv_len == vb->bv.bv_len) {
+				if (0 != memcmp(va->bv.bv_val, vb->bv.bv_val, va->bv.bv_len)) {
+					match = 0;
+				}
+			} else {
 				match = 0;
 			}
-		} else
-		{
+		} else if (0 != memcmp(va->bv.bv_val, vb->bv.bv_val, n)) {
 			match = 0;
 		}
-	} else
-	{
+	} else {
 		match = 0;
 	}
 	return match;
@@ -2554,7 +2605,17 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
 		{
 			if (!mapdn)
 			{
-				int values_equal = attr_compare_equal(attr,local_attr);
+				int values_equal = 0;
+
+                                /* AD has a legth contraint on the initials attribute,
+                                 * so treat is as a special case. */
+				if (0 == slapi_attr_type_cmp(type,"initials",SLAPI_TYPE_CMP_SUBTYPE) && !to_windows) {
+					values_equal = attr_compare_equal(attr, local_attr, AD_INITIALS_LENGTH);
+				} else {
+					/* Compare the entire attribute values */
+					values_equal = attr_compare_equal(attr, local_attr, 0);
+				}
+
 				/* If it is then we need to replace the local values with the remote values if they are different */
 				if (!values_equal)
 				{

+ 2 - 0
ldap/servers/plugins/replication/windowsrepl.h

@@ -97,4 +97,6 @@ void windows_conn_set_agmt_changed(Repl_Connection *conn);
 
 /* Used to work around a schema incompatibility between Microsoft and the IETF */
 #define FAKE_STREET_ATTR_NAME "in#place#of#streetaddress"
+/* Used to work around contrained attribute legth for initials on AD */
+#define AD_INITIALS_LENGTH 6