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.
Changes between 0.9.4 and 0.9.5 [xx XXX 1999]
+ *) Add a bunch of functions that should simplify the creation of
+ X509_NAME structures. Now you should be able to do:
+ X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0);
+ and have it automatically work out the correct field type and fill in
+ the structures. The more adventurous can try:
+ X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0);
+ and it will (hopefully) work out the correct multibyte encoding.
+ [Steve Henson]
+
+ *) Change the 'req' utility to use the new field handling and multibyte
+ copy routines. Before the DN field creation was handled in an ad hoc
+ way in req, ca, and x509 which was rather broken and didn't support
+ BMPStrings or UTF8Strings. Since some software doesn't implement
+ BMPStrings or UTF8Strings yet, they can be enabled using the config file
+ using the dirstring_type option. See the new comment in the default
+ openssl.cnf for more info.
+ [Steve Henson]
+
*) Make crypto/rand/md_rand.c more robust:
- Assure unique random numbers after fork().
- Make sure that concurrent threads access the global counter and
if (push != NULL)
{
- if (!X509_NAME_add_entry(subject,push,
- X509_NAME_entry_count(subject),0))
+ if (!X509_NAME_add_entry(subject,push, -1, 0))
{
if (push != NULL)
X509_NAME_ENTRY_free(push);
strlen(buf))) == NULL)
goto err;
- if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
- goto err;
+ if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
}
if (spki == NULL)
{
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
+# This sets the permitted types in a DirectoryString. There are several
+# options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nobmp : PrintableString, T61String (no BMPStrings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+dirstring_type = nobmp
+
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
#define ATTRIBUTES "attributes"
#define V3_EXTENSIONS "x509_extensions"
#define REQ_EXTENSIONS "req_extensions"
+#define DIRSTRING_TYPE "dirstring_type"
#define DEFAULT_KEY_LENGTH 512
#define MIN_KEY_LENGTH 384
}
}
+ p = CONF_get_string(req_conf, SECTION, DIRSTRING_TYPE);
+
+ if(p && !ASN1_STRING_set_default_mask_asc(p)) {
+ BIO_printf(bio_err, "Invalid DiretoryString setting %s", p);
+ goto end;
+ }
+
if(!req_exts)
req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
if(req_exts) {
ri=req->req_info;
+ /* setup version number */
+ if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
+
BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
BIO_printf(bio_err,"into your certificate request.\n");
BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
BIO_printf(bio_err,"-----\n");
- /* setup version number */
- if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
if (sk_CONF_VALUE_num(sk))
{
static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
int nid, int min, int max)
{
- int i,j,ret=0;
- X509_NAME_ENTRY *ne=NULL;
+ int i,ret=0;
MS_STATIC char buf[1024];
BIO_printf(bio_err,"%s [%s]:",text,def);
}
buf[--i]='\0';
- j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
- if (req_fix_data(nid,&j,i,min,max) == 0)
- goto err;
#ifdef CHARSET_EBCDIC
ebcdic2ascii(buf, buf, i);
#endif
- if ((ne=X509_NAME_ENTRY_create_by_NID(NULL,nid,j,(unsigned char *)buf,
- strlen(buf)))
- == NULL) goto err;
- if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
- goto err;
-
+ if (!X509_NAME_add_entry_by_NID(n,nid, MBSTRING_ASC,
+ (unsigned char *) buf, -1,-1,0)) goto err;
ret=1;
err:
- if (ne != NULL) X509_NAME_ENTRY_free(ne);
return(ret);
}
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)
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:
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);
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);
#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
#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
{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"},
{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"},
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,
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)
{
EVP_PKEY_get_DH 2018
EVP_PKEY_get_DSA 2019
X509_PURPOSE_cleanup 2020
+ASN1_STRING_set_default_mask_asc 2021
+X509_NAME_add_entry_by_txt 2022
+X509_NAME_add_entry_by_NID 2023
+X509_NAME_add_entry_by_OBJ 2024
+X509_NAME_ENTRY_create_by_txt 2025