New option '-subj arg' for 'openssl req' and 'openssl ca'. This
authorBodo Möller <bodo@openssl.org>
Mon, 5 Mar 2001 11:09:43 +0000 (11:09 +0000)
committerBodo Möller <bodo@openssl.org>
Mon, 5 Mar 2001 11:09:43 +0000 (11:09 +0000)
sets the subject name for a new request or supersedes the
subject name in a given request.

Add options '-batch' and '-verbose' to 'openssl req'.

Submitted by: Massimiliano Pala <madwolf@hackmasters.net>
Reviewed by: Bodo Moeller

CHANGES
apps/ca.c
apps/req.c
crypto/asn1/x_name.c
doc/apps/ca.pod
doc/apps/req.pod

diff --git a/CHANGES b/CHANGES
index 18c984c5c2ab4652137ebef04aea86ff5c971dac..ec67a937dad24a117195daf693e603aed7a27064 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,16 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) New option '-subj arg' for 'openssl req' and 'openssl ca'.  This
+     sets the subject name for a new request or supersedes the
+     subject name in a given request. Formats that can be parsed are
+          'CN=Some Name, OU=myOU, C=IT'
+     and
+          'CN=Some Name/OU=myOU/C=IT'.
+
+     Add options '-batch' and '-verbose' to 'openssl req'.
+     [Massimiliano Pala <madwolf@hackmasters.net>]
+
   *) Introduce the possibility to access global variables through
      functions on platform were that's the best way to handle exporting
      global variables in shared libraries.  To enable this functionality,
index d13b08f7e3581a26e9b4a4b532540d6dfbe4f561..f0ed07feb15fb92496a697c5515dd6b308f1481b 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -183,6 +183,7 @@ static char *ca_usage[]={
 " -batch          - Don't ask questions\n",
 " -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",
 " -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",
@@ -208,24 +209,25 @@ static BIGNUM *load_serial(char *serialfile);
 static int save_serial(char *serialfile, BIGNUM *serial);
 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
                   const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
-                  BIGNUM *serial, char *startdate,char *enddate, int days,
-                  int batch, char *ext_sect, LHASH *conf,int verbose);
+                  BIGNUM *serial, char *subj, char *startdate,char *enddate,
+                  int days, int batch, char *ext_sect, LHASH *conf,int verbose);
 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
                        const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
-                       TXT_DB *db, BIGNUM *serial,char *startdate,
+                       TXT_DB *db, BIGNUM *serial, char *subj, char *startdate,
                        char *enddate, int days, int batch, char *ext_sect,
                        LHASH *conf,int verbose);
 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
                         const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
-                        TXT_DB *db, BIGNUM *serial,char *startdate,
+                        TXT_DB *db, BIGNUM *serial,char *subj, char *startdate,
                         char *enddate, int days, char *ext_sect,LHASH *conf,
                                int verbose);
 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, TXT_DB *db, BIGNUM *serial,
+       STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,char *subj,
        char *startdate, char *enddate, int days, int batch, int verbose,
        X509_REQ *req, char *ext_sect, LHASH *conf);
+static X509_NAME *do_subject(char *subject);
 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
 static int get_certificate_status(const char *ser_status, TXT_DB *db);
 static int do_updatedb(TXT_DB *db);
@@ -280,6 +282,7 @@ int MAIN(int argc, char **argv)
        char *serialfile=NULL;
        char *extensions=NULL;
        char *extfile=NULL;
+       char *subj=NULL;
        char *crl_ext=NULL;
        int rev_type = REV_NONE;
        char *rev_arg = NULL;
@@ -343,6 +346,12 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        section= *(++argv);
                        }
+               else if (strcmp(*argv,"-subj") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       subj= *(++argv);
+                       /* preserve=1; */
+                       }
                else if (strcmp(*argv,"-startdate") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -719,7 +728,7 @@ bad:
                lookup_fail(section,ENV_CERTIFICATE);
                goto err;
                }
-        if (BIO_read_filename(in,certfile) <= 0)
+       if (BIO_read_filename(in,certfile) <= 0)
                {
                perror(certfile);
                BIO_printf(bio_err,"trying to load CA certificate\n");
@@ -771,7 +780,7 @@ bad:
               C routines to convert the directory syntax to Unixly, and give
               that to access().  However, time's too short to do that just
               now.
-            */
+           */
                if (access(outdir,R_OK|W_OK|X_OK) != 0)
                        {
                        BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
@@ -902,9 +911,9 @@ bad:
                        {
                        BIO_printf(bio_err,"Malloc failure\n");
                        goto err;
-                       }
+                       }
                else if (i == 0)
-                       {
+                       {
                        if (verbose) BIO_printf(bio_err,
                                        "No entries found to mark expired\n"); 
                        }
@@ -987,7 +996,7 @@ bad:
                /* We can have sections in the ext file */
                if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
                        extensions = "default";
-                }
+               }
 
        /*****************************************************************/
        if (req || gencrl)
@@ -1138,7 +1147,7 @@ bad:
                        {
                        total++;
                        j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
-                               serial,startdate,enddate, days,extensions,conf,
+                               serial,subj,startdate,enddate, days,extensions,conf,
                                verbose);
                        if (j < 0) goto err;
                        if (j > 0)
@@ -1162,7 +1171,7 @@ bad:
                        {
                        total++;
                        j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
-                               db,serial,startdate,enddate,days,batch,
+                               db,serial,subj,startdate,enddate,days,batch,
                                extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
@@ -1181,7 +1190,7 @@ bad:
                        {
                        total++;
                        j=certify(&x,infile,pkey,x509,dgst,attribs,db,
-                               serial,startdate,enddate,days,batch,
+                               serial,subj,startdate,enddate,days,batch,
                                extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
@@ -1200,7 +1209,7 @@ bad:
                        {
                        total++;
                        j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
-                               serial,startdate,enddate,days,batch,
+                               serial,subj,startdate,enddate,days,batch,
                                extensions,conf,verbose);
                        if (j < 0) goto err;
                        if (j > 0)
@@ -1674,7 +1683,7 @@ err:
 
 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
             const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
-            BIGNUM *serial, char *startdate, char *enddate, int days,
+            BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
             int batch, char *ext_sect, LHASH *lconf, int verbose)
        {
        X509_REQ *req=NULL;
@@ -1722,7 +1731,7 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        else
                BIO_printf(bio_err,"Signature ok\n");
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
+       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate, enddate,
                days,batch,verbose,req,ext_sect,lconf);
 
 err:
@@ -1733,7 +1742,7 @@ err:
 
 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
             const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
-            BIGNUM *serial, char *startdate, char *enddate, int days,
+            BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
             int batch, char *ext_sect, LHASH *lconf, int verbose)
        {
        X509 *req=NULL;
@@ -1784,7 +1793,7 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
                goto err;
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
+       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,days,
                batch,verbose,rreq,ext_sect,lconf);
 
 err:
@@ -1795,7 +1804,7 @@ err:
        }
 
 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
-            STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
+            STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
             char *startdate, char *enddate, int days, int batch, int verbose,
             X509_REQ *req, char *ext_sect, LHASH *lconf)
        {
@@ -1824,7 +1833,21 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
        for (i=0; i<DB_NUMBER; i++)
                row[i]=NULL;
 
-       BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
+       if (subj)
+               {
+               X509_NAME *n = do_subject(subj);
+
+               if (!n)
+                       {
+                       ERR_print_errors(bio_err);
+                       goto err;
+                       }
+               X509_REQ_set_subject_name(req,n);
+               req->req_info->enc.modified = 1;
+               X509_NAME_free(n);
+               }
+
+       BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
        name=X509_REQ_get_subject_name(req);
        for (i=0; i<X509_NAME_entry_count(name); i++)
                {
@@ -2288,7 +2311,7 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
 
 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
             const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
-            BIGNUM *serial, char *startdate, char *enddate, int days,
+            BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
             char *ext_sect, LHASH *lconf, int verbose)
        {
        STACK_OF(CONF_VALUE) *sk=NULL;
@@ -2423,7 +2446,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
 
        X509_REQ_set_pubkey(req,pktmp);
        EVP_PKEY_free(pktmp);
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
+       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,
                   days,1,verbose,req,ext_sect,lconf);
 err:
        if (req != NULL) X509_REQ_free(req);
@@ -2973,3 +2996,62 @@ int make_revoked(X509_REVOKED *rev, char *str)
 
        return ret;
        }
+
+static X509_NAME *do_subject(char *subject)
+       {
+       X509_NAME *n = NULL;
+
+       int i, nid, ne_num=0;
+
+       char *ne_name = NULL;
+       char *ne_value = NULL;
+
+       char *tmp = NULL;
+       char *p[2];
+
+       char *str_list[256];
+       
+       p[0] = ",/";
+       p[1] = "=";
+
+       n = X509_NAME_new();
+
+       tmp = strtok(subject, p[0]);
+       while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
+               {
+               char *token = tmp;
+
+               while (token[0] == ' ')
+                       token++;
+               str_list[ne_num] = token;
+
+               tmp = strtok(NULL, p[0]);
+               ne_num++;
+               }
+
+       for (i = 0; i < ne_num; i++)
+               {
+               ne_name  = strtok(str_list[i], p[1]);
+               ne_value = strtok(NULL, p[1]);
+
+               if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
+                       {
+                       BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
+                       continue;
+                       }
+
+               if (ne_value == NULL)
+                       {
+                       BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
+                       continue;
+                       }
+
+               if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
+                       {
+                       X509_NAME_free(n);
+                       return NULL;
+                       }
+               }
+
+       return n;
+       }
index e75d7abf09b790ba7160adec04351a89fdf7ea76..5246bbfdeea5febbfa701bca0a00d0cdfc3472f9 100644 (file)
  *               require.  This format is wrong
  */
 
-static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,int attribs);
+static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs);
+static int build_subject(X509_REQ *req, char *subj);
 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);
@@ -132,6 +133,7 @@ static char *default_config_file=NULL;
 static LHASH *config=NULL;
 #endif
 static LHASH *req_conf=NULL;
+static int batch=0;
 
 #define TYPE_RSA       1
 #define TYPE_DSA       2
@@ -150,7 +152,7 @@ int MAIN(int argc, char **argv)
        X509 *x509ss=NULL;
        X509_REQ *req=NULL;
        EVP_PKEY *pkey=NULL;
-       int i,badops=0,newreq=0,newkey= -1,pkey_type=TYPE_RSA;
+       int i,badops=0,newreq=0,newkey= -1,verbose=0,pkey_type=TYPE_RSA;
        BIO *in=NULL,*out=NULL;
        int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
        int nodes=0,kludge=0,newhdr=0,subject=0;
@@ -165,6 +167,7 @@ int MAIN(int argc, char **argv)
        char *passargin = NULL, *passargout = NULL;
        char *passin = NULL, *passout = NULL;
        char *p;
+       char *subj = NULL;
        const EVP_MD *md_alg=NULL,*digest=EVP_md5();
 #ifndef MONOLITH
        MS_STATIC char config_name[256];
@@ -321,6 +324,8 @@ int MAIN(int argc, char **argv)
 
                        newreq=1;
                        }
+               else if (strcmp(*argv,"-batch") == 0)
+                       batch=1;
                else if (strcmp(*argv,"-newhdr") == 0)
                        newhdr=1;
                else if (strcmp(*argv,"-modulus") == 0)
@@ -331,6 +336,8 @@ int MAIN(int argc, char **argv)
                        nodes=1;
                else if (strcmp(*argv,"-noout") == 0)
                        noout=1;
+               else if (strcmp(*argv,"-verbose") == 0)
+                       verbose=1;
                else if (strcmp(*argv,"-nameopt") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -346,6 +353,11 @@ int MAIN(int argc, char **argv)
                        kludge=1;
                else if (strcmp(*argv,"-no-asn1-kludge") == 0)
                        kludge=0;
+               else if (strcmp(*argv,"-subj") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       subj= *(++argv);
+                       }
                else if (strcmp(*argv,"-days") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -397,8 +409,10 @@ bad:
                BIO_printf(bio_err," -verify        verify signature on REQ\n");
                BIO_printf(bio_err," -modulus       RSA modulus\n");
                BIO_printf(bio_err," -nodes         don't encrypt the output key\n");
-               BIO_printf(bio_err," -engine e      use engine e, possibly a hardware device.\n");
-               BIO_printf(bio_err," -key file  use the private key contained in file\n");
+               BIO_printf(bio_err," -engine e      use engine e, possibly a hardware device\n");
+               BIO_printf(bio_err," -subject       output the request's subject\n");
+               BIO_printf(bio_err," -passin        private key password source\n");
+               BIO_printf(bio_err," -key file      use the private key contained in file\n");
                BIO_printf(bio_err," -keyform arg   key file format\n");
                BIO_printf(bio_err," -keyout arg    file to send the key to\n");
                BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
@@ -406,10 +420,11 @@ bad:
                BIO_printf(bio_err,"                the random number generator\n");
                BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
                BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
-
                BIO_printf(bio_err," -[digest]      Digest to sign with (md5, sha1, md2, mdc2)\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," -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");
                BIO_printf(bio_err," -days          number of days a certificate generated by -x509 is valid for.\n");
                BIO_printf(bio_err," -set_serial    serial number to use for a certificate generated by -x509.\n");
@@ -627,13 +642,13 @@ bad:
                        BIO_printf(bio_err,"unable to load Private key\n");
                        goto end;
                        }
-                if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
+               if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
                        {
                        char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
                        if (randfile == NULL)
                                ERR_clear_error();
                        app_RAND_load_file(randfile, bio_err, 0);
-                       }
+                       }
                }
 
        if (newreq && (pkey == NULL))
@@ -795,7 +810,8 @@ loop:
                                goto end;
                                }
 
-                       i=make_REQ(req,pkey,!x509);
+                       i=make_REQ(req,pkey,subj,!x509);
+                       subj=NULL; /* done processing '-subj' option */
                        if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
                                {
                                sk_X509_ATTRIBUTE_free(req->req_info->attributes);
@@ -839,13 +855,13 @@ loop:
                        /* Add extensions */
                        if(extensions && !X509V3_EXT_add_conf(req_conf, 
                                        &ext_ctx, extensions, x509ss))
-                           {
-                           BIO_printf(bio_err,
-                                      "Error Loading extension section %s\n",
-                                      extensions);
-                           goto end;
-                           }
-
+                               {
+                               BIO_printf(bio_err,
+                                       "Error Loading extension section %s\n",
+                                       extensions);
+                               goto end;
+                               }
+                       
                        if (!(i=X509_sign(x509ss,pkey,digest)))
                                goto end;
                        }
@@ -861,17 +877,46 @@ loop:
                        /* Add extensions */
                        if(req_exts && !X509V3_EXT_REQ_add_conf(req_conf, 
                                        &ext_ctx, req_exts, req))
-                           {
-                           BIO_printf(bio_err,
-                                      "Error Loading extension section %s\n",
-                                      req_exts);
-                           goto end;
-                           }
+                               {
+                               BIO_printf(bio_err,
+                                       "Error Loading extension section %s\n",
+                                       req_exts);
+                               goto end;
+                               }
                        if (!(i=X509_REQ_sign(req,pkey,digest)))
                                goto end;
                        }
                }
 
+       if (subj && x509)
+               {
+               BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
+               goto end;
+               }
+
+       if (subj && !x509)
+               {
+               if (verbose)
+                       {
+                       BIO_printf(bio_err, "Modifying Request's Subject\n");
+                       print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
+                       }
+
+               if (build_subject(req, subj) == 0)
+                       {
+                       BIO_printf(bio_err, "ERROR: cannot modify subject\n");
+                       ex=1;
+                       goto end;
+                       }
+
+               req->req_info->enc.modified = 1;
+
+               if (verbose)
+                       {
+                       print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag);
+                       }
+               }
+
        if (verify && !x509)
                {
                int tmp=0;
@@ -1024,7 +1069,7 @@ end:
        EXIT(ex);
        }
 
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs)
        {
        int ret=0,i;
        char no_prompt = 0;
@@ -1069,8 +1114,15 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
        /* setup version number */
        if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
 
-       if(no_prompt) i = auto_info(req, dn_sk, attr_sk, attribs);
-       else i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
+       if (no_prompt) 
+               i = auto_info(req, dn_sk, attr_sk, attribs);
+       else 
+               {
+               if (subj)
+                       i = build_subject(req, subj);
+               else
+                       i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
+               }
        if(!i) goto err;
 
        X509_REQ_set_pubkey(req,pkey);
@@ -1080,6 +1132,68 @@ err:
        return(ret);
        }
 
+static int build_subject(X509_REQ *req, char *subject)
+       {
+       X509_NAME *n = NULL;
+
+       int i, nid, ne_num=0;
+
+       char *ne_name = NULL;
+       char *ne_value = NULL;
+
+       char *tmp = NULL;
+       char *p[2];
+
+       char *str_list[256];
+       
+       p[0] = ",/";
+        p[1] = "=";
+
+       n = X509_NAME_new();
+
+       tmp = strtok(subject, p[0]);
+       while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
+               {
+               char *token = tmp;
+
+               while (token[0] == ' ')
+                       token++;
+               str_list[ne_num] = token;
+
+               tmp = strtok(NULL, p[0]);
+               ne_num++;
+               }
+
+       for(i = 0; i < ne_num; i++)
+               {
+               ne_name  = strtok(str_list[i], p[1]);
+               ne_value = strtok(NULL, p[1]);
+
+               if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
+                       {
+                       BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
+                       continue;
+                       }
+
+               if (ne_value == NULL)
+                       {
+                       BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
+                       continue;
+                       }
+
+               if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
+                       {
+                       X509_NAME_free(n);
+                       return 0;
+                       }
+               }
+
+       if (!X509_REQ_set_subject_name(req, n))
+               return 0;
+       X509_NAME_free(n);
+       return 1;
+}
+
 
 static int prompt_info(X509_REQ *req,
                STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
@@ -1093,13 +1207,17 @@ static int prompt_info(X509_REQ *req,
        CONF_VALUE *v;
        X509_NAME *subj;
        subj = X509_REQ_get_subject_name(req);
-       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,"There are quite a few fields but you can leave some blank\n");
-       BIO_printf(bio_err,"For some fields there will be a default value,\n");
-       BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
-       BIO_printf(bio_err,"-----\n");
+
+       if(!batch)
+               {
+               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,"There are quite a few fields but you can leave some blank\n");
+               BIO_printf(bio_err,"For some fields there will be a default value,\n");
+               BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
+               BIO_printf(bio_err,"-----\n");
+               }
 
 
        if (sk_CONF_VALUE_num(dn_sk))
@@ -1160,7 +1278,7 @@ start:            for (;;)
 
                if (attribs)
                        {
-                       if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0))
+                       if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch))
                                {
                                BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
                                BIO_printf(bio_err,"to be sent with your certificate request\n");
@@ -1276,9 +1394,9 @@ static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
        int i,ret=0;
        MS_STATIC char buf[1024];
 start:
-       BIO_printf(bio_err,"%s [%s]:",text,def);
+       if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
        (void)BIO_flush(bio_err);
-       if (value != NULL)
+       if(value != NULL)
                {
                strcpy(buf,value);
                strcat(buf,"\n");
@@ -1287,7 +1405,15 @@ start:
        else
                {
                buf[0]='\0';
-               fgets(buf,1024,stdin);
+               if (!batch)
+                       {
+                       fgets(buf,1024,stdin);
+                       }
+               else
+                       {
+                       buf[0] = '\n';
+                       buf[1] = '\0';
+                       }
                }
 
        if (buf[0] == '\0') return(0);
@@ -1307,7 +1433,6 @@ start:
                return(0);
                }
        buf[--i]='\0';
-
 #ifdef CHARSET_EBCDIC
        ebcdic2ascii(buf, buf, i);
 #endif
@@ -1327,7 +1452,7 @@ static int add_attribute_object(X509_REQ *req, char *text,
        static char buf[1024];
 
 start:
-       BIO_printf(bio_err,"%s [%s]:",text,def);
+       if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
        (void)BIO_flush(bio_err);
        if (value != NULL)
                {
@@ -1338,7 +1463,15 @@ start:
        else
                {
                buf[0]='\0';
-               fgets(buf,1024,stdin);
+               if (!batch)
+                       {
+                       fgets(buf,1024,stdin);
+                       }
+               else
+                       {
+                       buf[0] = '\n';
+                       buf[1] = '\0';
+                       }
                }
 
        if (buf[0] == '\0') return(0);
index 34f4e4c3f6e21c13abd8b426d6827700b2656f3b..9a111a3d05ffa0bb7d0edeb6d7c40d6000547bfc 100644 (file)
@@ -119,8 +119,15 @@ static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
        ret->modified=1;
        *val = (ASN1_VALUE *)ret;
        return 1;
-       memerr:
+
+ memerr:
        ASN1err(ASN1_F_X509_NAME_NEW, ERR_R_MALLOC_FAILURE);
+       if (ret)
+               {
+               if (ret->entries)
+                       sk_X509_NAME_ENTRY_free(ret->entries);
+               OPENSSL_free(ret);
+               }
        return 0;
 }
 
index 8121886ebbade4b6da61152fba4f3671369b9c12..5adf805a94854cfa164f89ca4cfd3cb209c62838 100644 (file)
@@ -13,6 +13,7 @@ B<openssl> B<ca>
 [B<-name section>]
 [B<-gencrl>]
 [B<-revoke file>]
+[B<-subj arg>]
 [B<-crldays days>]
 [B<-crlhours hours>]
 [B<-crlexts section>]
@@ -105,6 +106,7 @@ the 'ps' utility) this option should be used with caution.
 
 the key password source. For more information about the format of B<arg>
 see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)|openssl(1)>.
+
 =item B<-verbose>
 
 this prints extra details about the operations being performed.
@@ -197,6 +199,10 @@ the number of hours before the next CRL is due.
 
 a filename containing a certificate to revoke.
 
+=item B<-subj arg>
+
+supersedes subject name given in the request
+
 =item B<-crlexts section>
 
 the section of the configuration file containing CRL extensions to
index a3f54f45a30dd7f2cf792292d9f4e97fb7195c95..c486c2be74ffdc0442a04479d5281afe33c74514 100644 (file)
@@ -28,12 +28,15 @@ B<openssl> B<req>
 [B<-keyout filename>]
 [B<-[md5|sha1|md2|mdc2]>]
 [B<-config filename>]
+[B<-subj arg>]
 [B<-x509>]
 [B<-days n>]
 [B<-asn1-kludge>]
 [B<-newhdr>]
 [B<-extensions section>]
 [B<-reqexts section>]
+[B<-batch>]
+[B<-verbose>]
 
 =head1 DESCRIPTION
 
@@ -154,6 +157,11 @@ this allows an alternative configuration file to be specified,
 this overrides the compile time filename or any specified in
 the B<OPENSSL_CONF> environment variable.
 
+=item B<-subj arg>
+
+sets subject name for new request or supersedes the subject name
+when processing a request.
+
 =item B<-x509>
 
 this option outputs a self signed certificate instead of a certificate
@@ -196,6 +204,14 @@ It should be noted that very few CAs still require the use of this option.
 Adds the word B<NEW> to the PEM file header and footer lines on the outputed
 request. Some software (Netscape certificate server) and some CAs need this.
 
+=item B<-batch>
+
+non-interactive mode.
+
+=item B<-verbose>
+
+print extra details about the operations being performed.
+
 =back
 
 =head1 CONFIGURATION FILE FORMAT