[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Thu Dec 28 15:08:05 UTC 2017


The branch master has been updated
       via  bfa470a4f64313651a35571883e235d3335054eb (commit)
      from  8175af50cc208c09f92b30358d30dd86c798b60e (commit)


- Log -----------------------------------------------------------------
commit bfa470a4f64313651a35571883e235d3335054eb
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Dec 27 18:29:36 2017 +0100

    Add 'openssl req' option to specify extension values on command line
    
    The idea is to be able to add extension value lines directly on the
    command line instead of through the config file, for example:
    
        openssl req -new -extension 'subjectAltName = DNS:dom.ain, DNS:oth.er' \
                         -extension 'certificatePolicies = 1.2.3.4'
    
    Fixes #3311
    
    Thank you Jacob Hoffman-Andrews for the inspiration
    
    Reviewed-by: Andy Polyakov <appro at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4986)

-----------------------------------------------------------------------

Summary of changes:
 apps/apps.c      | 21 +++++++++++++--------
 apps/apps.h      |  1 +
 apps/req.c       | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 doc/man1/req.pod | 17 +++++++++++++++++
 4 files changed, 75 insertions(+), 10 deletions(-)

diff --git a/apps/apps.c b/apps/apps.c
index 3040566..834cedd 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -442,7 +442,7 @@ static char *app_get_pass(const char *arg, int keepbio)
     return OPENSSL_strdup(tpass);
 }
 
-static CONF *app_load_config_(BIO *in, const char *filename)
+CONF *app_load_config_bio(BIO *in, const char *filename)
 {
     long errorline = -1;
     CONF *conf;
@@ -453,12 +453,17 @@ static CONF *app_load_config_(BIO *in, const char *filename)
     if (i > 0)
         return conf;
 
-    if (errorline <= 0)
-        BIO_printf(bio_err, "%s: Can't load config file \"%s\"\n",
-                   opt_getprog(), filename);
+    if (errorline <= 0) {
+        BIO_printf(bio_err, "%s: Can't load ", opt_getprog());
+    } else {
+        BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(),
+                   errorline);
+    }
+    if (filename != NULL)
+        BIO_printf(bio_err, "config file \"%s\"\n", filename);
     else
-        BIO_printf(bio_err, "%s: Error on line %ld of config file \"%s\"\n",
-                   opt_getprog(), errorline, filename);
+        BIO_printf(bio_err, "config input");
+
     NCONF_free(conf);
     return NULL;
 }
@@ -472,7 +477,7 @@ CONF *app_load_config(const char *filename)
     if (in == NULL)
         return NULL;
 
-    conf = app_load_config_(in, filename);
+    conf = app_load_config_bio(in, filename);
     BIO_free(in);
     return conf;
 }
@@ -486,7 +491,7 @@ CONF *app_load_config_quiet(const char *filename)
     if (in == NULL)
         return NULL;
 
-    conf = app_load_config_(in, filename);
+    conf = app_load_config_bio(in, filename);
     BIO_free(in);
     return conf;
 }
diff --git a/apps/apps.h b/apps/apps.h
index 321f644..6d0d701 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -52,6 +52,7 @@ BIO *dup_bio_err(int format);
 BIO *bio_open_owner(const char *filename, int format, int private);
 BIO *bio_open_default(const char *filename, char mode, int format);
 BIO *bio_open_default_quiet(const char *filename, char mode, int format);
+CONF *app_load_config_bio(BIO *in, const char *filename);
 CONF *app_load_config(const char *filename);
 CONF *app_load_config_quiet(const char *filename);
 int app_load_modules(const CONF *config);
diff --git a/apps/req.c b/apps/req.c
index 989a6ad..dca6038 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -70,6 +70,7 @@ static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
                                     int *pkey_type, long *pkeylen,
                                     char **palgnam, ENGINE *keygen_engine);
 static CONF *req_conf = NULL;
+static CONF *addext_conf = NULL;
 static int batch = 0;
 
 typedef enum OPTION_choice {
@@ -80,7 +81,7 @@ typedef enum OPTION_choice {
     OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
     OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
     OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
-    OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_EXTENSIONS,
+    OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS,
     OPT_REQEXTS, OPT_PRECERT, OPT_MD,
     OPT_R_ENUM
 } OPTION_CHOICE;
@@ -124,6 +125,8 @@ const OPTIONS req_options[] = {
      "Enable support for multivalued RDNs"},
     {"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
     {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
+    {"addext", OPT_ADDEXT, 's',
+     "Additional cert extension key=value pair (may be given more than once)"},
     {"extensions", OPT_EXTENSIONS, 's',
      "Cert extension section (override value in config file)"},
     {"reqexts", OPT_REQEXTS, 's',
@@ -150,6 +153,7 @@ int req_main(int argc, char **argv)
     X509_REQ *req = NULL;
     const EVP_CIPHER *cipher = NULL;
     const EVP_MD *md_alg = NULL, *digest = NULL;
+    BIO *addext_bio = NULL;
     char *extensions = NULL, *infile = NULL;
     char *outfile = NULL, *keyfile = NULL;
     char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL;
@@ -313,6 +317,14 @@ int req_main(int argc, char **argv)
         case OPT_MULTIVALUE_RDN:
             multirdn = 1;
             break;
+        case OPT_ADDEXT:
+            if (addext_bio == NULL) {
+                addext_bio = BIO_new(BIO_s_mem());
+            }
+            if (addext_bio == NULL
+                || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
+                goto end;
+            break;
         case OPT_EXTENSIONS:
             extensions = opt_arg();
             break;
@@ -349,6 +361,12 @@ int req_main(int argc, char **argv)
     if (verbose)
         BIO_printf(bio_err, "Using configuration from %s\n", template);
     req_conf = app_load_config(template);
+    if (addext_bio) {
+        if (verbose)
+            BIO_printf(bio_err,
+                       "Using additional configuraton from command line\n");
+        addext_conf = app_load_config_bio(addext_bio, NULL);
+    }
     if (template != default_config_file && !app_load_modules(req_conf))
         goto end;
 
@@ -401,6 +419,16 @@ int req_main(int argc, char **argv)
             goto end;
         }
     }
+    if (addext_conf != NULL) {
+        /* Check syntax of command line extensions */
+        X509V3_CTX ctx;
+        X509V3_set_ctx_test(&ctx);
+        X509V3_set_nconf(&ctx, addext_conf);
+        if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
+            BIO_printf(bio_err, "Error Loading command line extensions\n");
+            goto end;
+        }
+    }
 
     if (passin == NULL) {
         passin = nofree_passin =
@@ -605,7 +633,8 @@ int req_main(int argc, char **argv)
                 goto end;
 
             /* Set version to V3 */
-            if (extensions != NULL && !X509_set_version(x509ss, 2))
+            if ((extensions != NULL || addext_conf != NULL)
+                && !X509_set_version(x509ss, 2))
                 goto end;
             if (serial != NULL) {
                 if (!X509_set_serialNumber(x509ss, serial))
@@ -643,6 +672,12 @@ int req_main(int argc, char **argv)
                            extensions);
                 goto end;
             }
+            if (addext_conf != NULL
+                && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default",
+                                         x509ss)) {
+                BIO_printf(bio_err, "Error Loading command line extensions\n");
+                goto end;
+            }
 
             /* If a pre-cert was requested, we need to add a poison extension */
             if (precert) {
@@ -674,6 +709,12 @@ int req_main(int argc, char **argv)
                            req_exts);
                 goto end;
             }
+            if (addext_conf != NULL
+                && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default",
+                                             req)) {
+                BIO_printf(bio_err, "Error Loading command line extensions\n");
+                goto end;
+            }
             i = do_X509_REQ_sign(req, pkey, digest, sigopts);
             if (!i) {
                 ERR_print_errors(bio_err);
@@ -817,6 +858,7 @@ int req_main(int argc, char **argv)
         ERR_print_errors(bio_err);
     }
     NCONF_free(req_conf);
+    BIO_free(addext_bio);
     BIO_free(in);
     BIO_free_all(out);
     EVP_PKEY_free(pkey);
diff --git a/doc/man1/req.pod b/doc/man1/req.pod
index 5ed90ad..db467bb 100644
--- a/doc/man1/req.pod
+++ b/doc/man1/req.pod
@@ -37,6 +37,7 @@ B<openssl> B<req>
 [B<-days n>]
 [B<-set_serial n>]
 [B<-newhdr>]
+[B<-addext ext>]
 [B<-extensions section>]
 [B<-reqexts section>]
 [B<-precert>]
@@ -255,6 +256,14 @@ be a positive integer. The default is 30 days.
 Serial number to use when outputting a self signed certificate. This
 may be specified as a decimal value or a hex value if preceded by B<0x>.
 
+=item B<-addext ext>
+
+Add a specific extension to the certificate (if the B<-x509> option is
+present) or certificate request.  The argument must have the form of
+a key=value pair as it would appear in a config file.
+
+This option can be given multiple times.
+
 =item B<-extensions section>
 
 =item B<-reqexts section>
@@ -591,6 +600,14 @@ Sample configuration containing all field values:
  [ req_attributes ]
  challengePassword              = A challenge password
 
+Example of giving the most common attributes (subject and extensions)
+on the command line:
+
+ openssl req -new -subj "/C=GB/CN=foo" \
+                  -addext "subjectAltName = DNS:foo.co.uk" \
+                  -addext "certificatePolicies = 1.2.3.4" \
+                  -newkey rsa:2048 -keyout key.pem -out req.pem
+
 
 =head1 NOTES
 


More information about the openssl-commits mailing list