X509_NAME_cmp() now compares PrintableString and emailAddress with a value of type
ia5String correctly.
PR: 244
diff --git a/CHANGES b/CHANGES
index a16d78d..43565ec 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1997,6 +1997,11 @@
 
  Changes between 0.9.6g and 0.9.6h  [xx XXX xxxx]
 
+  *) Change X509_NAME_cmp() so it applies the special rules on handling
+     DN values that are of type PrintableString, as well as RDNs of type
+     emailAddress where the value has the type ia5String.
+     [stefank@valicert.com via Richard Levitte]
+
   *) Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half
      the job SSL_SESS_CACHE_NO_INTERNAL_LOOKUP was inconsistently
      doing, define a new flag (SSL_SESS_CACHE_NO_INTERNAL) to be
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 415e5f3..474f6de 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -159,6 +159,99 @@
 }
 #endif
 
+
+/* Case insensitive string comparision */
+static int nocase_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
+{
+	int i;
+
+	if (a->length != b->length)
+		return (a->length - b->length);
+
+	for (i=0; i<a->length; i++)
+	{
+		int ca, cb;
+
+		ca = tolower(a->data[i]);
+		cb = tolower(b->data[i]);
+
+		if (ca != cb)
+			return(ca-cb);
+	}
+	return 0;
+}
+
+/* Case insensitive string comparision with space normalization 
+ * Space normalization - ignore leading, trailing spaces, 
+ *       multiple spaces between characters are replaced by single space  
+ */
+static int nocase_spacenorm_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
+{
+	unsigned char *pa = NULL, *pb = NULL;
+	int la, lb;
+	
+	la = a->length;
+	lb = b->length;
+	pa = a->data;
+	pb = b->data;
+
+	/* skip leading spaces */
+	while (la > 0 && isspace(*pa))
+	{
+		la--;
+		pa++;
+	}
+	while (lb > 0 && isspace(*pb))
+	{
+		lb--;
+		pb++;
+	}
+
+	/* skip trailing spaces */
+	while (la > 0 && isspace(pa[la-1]))
+		la--;
+	while (lb > 0 && isspace(pb[lb-1]))
+		lb--;
+
+	/* compare strings with space normalization */
+	while (la > 0 && lb > 0)
+	{
+		int ca, cb;
+
+		/* compare character */
+		ca = tolower(*pa);
+		cb = tolower(*pb);
+		if (ca != cb)
+			return (ca - cb);
+
+		pa++; pb++;
+		la--; lb--;
+
+		if (la <= 0 || lb <= 0)
+			break;
+
+		/* is white space next character ? */
+		if (isspace(*pa) && isspace(*pb))
+		{
+			/* skip remaining white spaces */
+			while (la > 0 && isspace(*pa))
+			{
+				la--;
+				pa++;
+			}
+			while (lb > 0 && isspace(*pb))
+			{
+				lb--;
+				pb++;
+			}
+		}
+	}
+	if (la > 0 || lb > 0)
+		return la - lb;
+
+	return 0;
+}
+
 int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
 	{
 	int i,j;
@@ -172,10 +265,20 @@
 		{
 		na=sk_X509_NAME_ENTRY_value(a->entries,i);
 		nb=sk_X509_NAME_ENTRY_value(b->entries,i);
-		j=na->value->length-nb->value->length;
+		j=na->value->type-nb->value->type;
 		if (j) return(j);
-		j=memcmp(na->value->data,nb->value->data,
-			na->value->length);
+		if (na->value->type == V_ASN1_PRINTABLESTRING)
+			j=nocase_spacenorm_cmp(na->value, nb->value);
+		else if (na->value->type == V_ASN1_IA5STRING
+			&& OBJ_obj2nid(na->object) == NID_pkcs9_emailAddress)
+			j=nocase_cmp(na->value, nb->value);
+		else
+			{
+			j=na->value->length-nb->value->length;
+			if (j) return(j);
+			j=memcmp(na->value->data,nb->value->data,
+				na->value->length);
+			}
 		if (j) return(j);
 		j=na->set-nb->set;
 		if (j) return(j);