Continued multibyte character support.

Add a bunch of functions to simplify the creation of X509_NAME structures.

Change the X509_NAME_entry_add stuff in req/ca so it no longer uses
X509_NAME_entry_count(): passing -1 has the same effect.
diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c
index 2fe658e..9e7c7c3 100644
--- a/crypto/asn1/a_mbstr.c
+++ b/crypto/asn1/a_mbstr.c
@@ -91,6 +91,35 @@
 	return dirstring_mask;
 }
 
+/* This function sets the default to various "flavours" of configuration.
+ * based on an ASCII string. Currently this is:
+ * MASK:XXXX : a numerical mask value.
+ * nobmp : Don't use BMPStrings (just Printable, T61).
+ * pkix : PKIX recommendation in RFC2459.
+ * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
+ * default:   the default value, Printable, T61, BMP.
+ */
+
+int ASN1_STRING_set_default_mask_asc(char *p)
+{
+	unsigned long mask;
+	char *end;
+	if(!strncmp(p, "MASK:", 5)) {
+		if(!p[5]) return 0;
+		mask = strtoul(p + 5, &end, 0);
+		if(*end) return 0;
+	} else if(!strcmp(p, "nobmp"))
+			 mask = B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING;
+	else if(!strcmp(p, "pkix"))
+			mask = B_ASN1_PRINTABLESTRING | B_ASN1_BMPSTRING;
+	else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
+	else if(!strcmp(p, "default"))
+	    mask = B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING;
+	else return 0;
+	ASN1_STRING_set_default_mask(mask);
+	return 1;
+}
+
 /* These functions take a string in UTF8, ASCII or multibyte form and
  * a mask of permissible ASN1 string types. It then works out the minimal
  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
index 520b118..cb37024 100644
--- a/crypto/asn1/a_strnid.c
+++ b/crypto/asn1/a_strnid.c
@@ -85,7 +85,7 @@
 					tbl->minsize, tbl->maxsize);
 	else ret = ASN1_mbstring_copy(out, in, inlen, inform, 0);
 	if(ret <= 0) return NULL;
-	return str;
+	return *out;
 }
 
 /* Now the tables and helper functions for the string table:
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index 2a7da6b..8c42101 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -744,6 +744,7 @@
 ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(char *p);
 unsigned long ASN1_STRING_get_default_mask(void);
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
 					int inform, unsigned long mask);
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 64b07e4..6091ffd 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -859,8 +859,16 @@
 X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
 int 		X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
 			int loc, int set);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+			unsigned char *bytes, int len, int loc, int set);
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+			unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+		char *field, int type, unsigned char *bytes, int len);
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
 			int type,unsigned char *bytes, int len);
+int X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, int type,
+			unsigned char *bytes, int len, int loc, int set);
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
 			ASN1_OBJECT *obj, int type,unsigned char *bytes,
 			int len);
@@ -979,6 +987,7 @@
 #define X509_F_X509_LOAD_CRL_FILE			 112
 #define X509_F_X509_NAME_ADD_ENTRY			 113
 #define X509_F_X509_NAME_ENTRY_CREATE_BY_NID		 114
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT		 131
 #define X509_F_X509_NAME_ENTRY_SET_OBJECT		 115
 #define X509_F_X509_NAME_ONELINE			 116
 #define X509_F_X509_NAME_PRINT				 117
@@ -1000,6 +1009,7 @@
 #define X509_R_CERT_ALREADY_IN_HASH_TABLE		 101
 #define X509_R_ERR_ASN1_LIB				 102
 #define X509_R_INVALID_DIRECTORY			 113
+#define X509_R_INVALID_FIELD_NAME			 119
 #define X509_R_KEY_TYPE_MISMATCH			 115
 #define X509_R_KEY_VALUES_MISMATCH			 116
 #define X509_R_LOADING_CERT_DIR				 103
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index a2a0f11..0a0b704 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -80,6 +80,7 @@
 {ERR_PACK(0,X509_F_X509_LOAD_CRL_FILE,0),	"X509_load_crl_file"},
 {ERR_PACK(0,X509_F_X509_NAME_ADD_ENTRY,0),	"X509_NAME_add_entry"},
 {ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_NID,0),	"X509_NAME_ENTRY_create_by_NID"},
+{ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,0),	"X509_NAME_ENTRY_create_by_txt"},
 {ERR_PACK(0,X509_F_X509_NAME_ENTRY_SET_OBJECT,0),	"X509_NAME_ENTRY_set_object"},
 {ERR_PACK(0,X509_F_X509_NAME_ONELINE,0),	"X509_NAME_oneline"},
 {ERR_PACK(0,X509_F_X509_NAME_PRINT,0),	"X509_NAME_print"},
@@ -104,6 +105,7 @@
 {X509_R_CERT_ALREADY_IN_HASH_TABLE       ,"cert already in hash table"},
 {X509_R_ERR_ASN1_LIB                     ,"err asn1 lib"},
 {X509_R_INVALID_DIRECTORY                ,"invalid directory"},
+{X509_R_INVALID_FIELD_NAME               ,"invalid field name"},
 {X509_R_KEY_TYPE_MISMATCH                ,"key type mismatch"},
 {X509_R_KEY_VALUES_MISMATCH              ,"key values mismatch"},
 {X509_R_LOADING_CERT_DIR                 ,"loading cert dir"},
diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c
index 64c1315..bd7b985 100644
--- a/crypto/x509/x509name.c
+++ b/crypto/x509/x509name.c
@@ -171,6 +171,33 @@
 	return(ret);
 	}
 
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+			unsigned char *bytes, int len, int loc, int set)
+{
+	X509_NAME_ENTRY *ne;
+	ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
+	if(!ne) return 0;
+	return X509_NAME_add_entry(name, ne, loc, set);
+}
+
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+			unsigned char *bytes, int len, int loc, int set)
+{
+	X509_NAME_ENTRY *ne;
+	ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+	if(!ne) return 0;
+	return X509_NAME_add_entry(name, ne, loc, set);
+}
+
+int X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, int type,
+			unsigned char *bytes, int len, int loc, int set)
+{
+	X509_NAME_ENTRY *ne;
+	ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
+	if(!ne) return 0;
+	return X509_NAME_add_entry(name, ne, loc, set);
+}
+
 /* if set is -1, append to previous set, 0 'a new one', and 1,
  * prepend to the guy we are about to stomp on. */
 int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
@@ -236,6 +263,21 @@
 	return(0);
 	}
 
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+		char *field, int type, unsigned char *bytes, int len)
+	{
+	ASN1_OBJECT *obj;
+
+	obj=OBJ_txt2obj(field, 0);
+	if (obj == NULL)
+		{
+		X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
+						X509_R_INVALID_FIELD_NAME);
+		return(NULL);
+		}
+	return(X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len));
+	}
+
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
 	     int type, unsigned char *bytes, int len)
 	{