" -msie_hack - msie modifications to handle all those universal strings\n",
" -revoke file - Revoke a certificate (given in file)\n",
" -subj arg - Use arg instead of request's subject\n",
+" -multivalue-rdn - enable support for multivalued RDNs\n",
" -extensions .. - Extension section (override value in config file)\n",
" -extfile file - Configuration file with X509v3 extentions to add\n",
" -crlexts .. - CRL extension section (override value in config file)\n",
static void lookup_fail(char *name,char *tag);
static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate,
char *enddate, long days, int batch, char *ext_sect, CONF *conf,
int verbose, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign);
static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
- CA_DB *db, BIGNUM *serial, char *subj, int email_dn,
+ CA_DB *db, BIGNUM *serial, char *subj, int multirdn, int email_dn,
char *startdate, char *enddate, long days, int batch,
char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy,
ENGINE *e);
static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
- CA_DB *db, BIGNUM *serial,char *subj, int email_dn,
+ CA_DB *db, BIGNUM *serial,char *subj, int multirdn, int email_dn,
char *startdate, char *enddate, long days, char *ext_sect,
CONF *conf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy);
static int fix_data(int nid, int *type);
static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
- STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj, int multirdn,
int email_dn, char *startdate, char *enddate, long days, int batch,
int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
unsigned long certopt, unsigned long nameopt, int default_op,
char *extensions=NULL;
char *extfile=NULL;
char *subj=NULL;
+ int multirdn = 0;
char *tmp_email_dn=NULL;
char *crl_ext=NULL;
int rev_type = REV_NONE;
subj= *(++argv);
/* preserve=1; */
}
+ else if (strcmp(*argv,"-multivalue-rdn") == 0)
+ multirdn=1;
else if (strcmp(*argv,"-startdate") == 0)
{
if (--argc < 1) goto bad;
{
total++;
j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
- serial,subj,email_dn,startdate,enddate,days,extensions,
+ serial,subj,multirdn,email_dn,startdate,enddate,days,extensions,
conf,verbose,certopt,nameopt,default_op,ext_copy);
if (j < 0) goto err;
if (j > 0)
{
total++;
j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
- db,serial,subj,email_dn,startdate,enddate,days,batch,
+ db,serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, e);
if (j < 0) goto err;
{
total++;
j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
- serial,subj,email_dn,startdate,enddate,days,batch,
+ serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, selfsign);
if (j < 0) goto err;
{
total++;
j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
- serial,subj,email_dn,startdate,enddate,days,batch,
+ serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, selfsign);
if (j < 0) goto err;
static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
long days, int batch, char *ext_sect, CONF *lconf, int verbose,
unsigned long certopt, unsigned long nameopt, int default_op,
int ext_copy, int selfsign)
else
BIO_printf(bio_err,"Signature ok\n");
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, multirdn, email_dn,
startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
certopt, nameopt, default_op, ext_copy, selfsign);
static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
long days, int batch, char *ext_sect, CONF *lconf, int verbose,
unsigned long certopt, unsigned long nameopt, int default_op,
int ext_copy, ENGINE *e)
if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
goto err;
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,multirdn,email_dn,startdate,enddate,
days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
ext_copy, 0);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
+ int multirdn,
int email_dn, char *startdate, char *enddate, long days, int batch,
int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
unsigned long certopt, unsigned long nameopt, int default_op,
if (subj)
{
- X509_NAME *n = do_subject(subj, MBSTRING_ASC);
+ X509_NAME *n = do_subject(subj, MBSTRING_ASC, multirdn);
if (!n)
{
static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy)
{
X509_REQ_set_pubkey(req,pktmp);
EVP_PKEY_free(pktmp);
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,multirdn,email_dn,startdate,enddate,
days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
ext_copy, 0);
err:
* subject is expected to be in the format /type0=value0/type1=value1/type2=...
* where characters may be escaped by \
*/
-X509_NAME *do_subject(char *subject, long chtype)
+X509_NAME *do_subject(char *subject, long chtype, int multirdn)
{
size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
char *buf = OPENSSL_malloc(buflen);
size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
+ int *mval = OPENSSL_malloc (max_ne * sizeof (int));
char *sp = subject, *bp = buf;
int i, ne_num = 0;
}
sp++; /* skip leading / */
+ /* no multivalued RDN by default */
+ mval[ne_num] = 0;
+
while (*sp)
{
/* collect type */
else if (*sp == '/')
{
sp++;
+ /* no multivalued RDN by default */
+ mval[ne_num+1] = 0;
+ break;
+ }
+ else if (*sp == '+' && multirdn)
+ {
+ /* a not escaped + signals a mutlivalued RDN */
+ sp++;
+ mval[ne_num+1] = -1;
break;
}
else
continue;
}
- if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
+ if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
goto error;
}
* require. This format is wrong
*/
-static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs,
- unsigned long chtype);
-static int build_subject(X509_REQ *req, char *subj, unsigned long chtype);
+static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int mutlirdn,
+ int attribs,unsigned long chtype);
+static int build_subject(X509_REQ *req, char *subj, unsigned long chtype,
+ int multirdn);
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs,
char *passin = NULL, *passout = NULL;
char *p;
char *subj = NULL;
+ int multirdn = 0;
const EVP_MD *md_alg=NULL,*digest=EVP_md5();
unsigned long chtype = MBSTRING_ASC;
#ifndef MONOLITH
if (--argc < 1) goto bad;
subj= *(++argv);
}
+ else if (strcmp(*argv,"-multivalue-rdn") == 0)
+ multirdn=1;
else if (strcmp(*argv,"-days") == 0)
{
if (--argc < 1) goto bad;
BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2, md4)\n");
BIO_printf(bio_err," -config file request template file.\n");
BIO_printf(bio_err," -subj arg set or modify request subject\n");
+ BIO_printf(bio_err," -multivalue-rdn enable support for multivalued RDNs\n");
BIO_printf(bio_err," -new new request.\n");
BIO_printf(bio_err," -batch do not ask anything during request generation\n");
BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n");
goto end;
}
- i=make_REQ(req,pkey,subj,!x509, chtype);
+ i=make_REQ(req,pkey,subj,multirdn,!x509, chtype);
subj=NULL; /* done processing '-subj' option */
if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
{
print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
}
- if (build_subject(req, subj, chtype) == 0)
+ if (build_subject(req, subj, chtype, multirdn) == 0)
{
BIO_printf(bio_err, "ERROR: cannot modify subject\n");
ex=1;
OPENSSL_EXIT(ex);
}
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs,
- unsigned long chtype)
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
+ int attribs, unsigned long chtype)
{
int ret=0,i;
char no_prompt = 0;
else
{
if (subj)
- i = build_subject(req, subj, chtype);
+ i = build_subject(req, subj, chtype, multirdn);
else
i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
}
* subject is expected to be in the format /type0=value0/type1=value1/type2=...
* where characters may be escaped by \
*/
-static int build_subject(X509_REQ *req, char *subject, unsigned long chtype)
+static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn)
{
X509_NAME *n;
- if (!(n = do_subject(subject, chtype)))
+ if (!(n = do_subject(subject, chtype, multirdn)))
return 0;
if (!X509_REQ_set_subject_name(req, n))