Fix #946 Add -preserve_dates to x509 app
authorTodd Short <tshort@akamai.com>
Fri, 20 Feb 2015 20:00:28 +0000 (15:00 -0500)
committerMatt Caswell <matt@openssl.org>
Fri, 14 Jul 2017 09:05:09 +0000 (10:05 +0100)
Add the -preserve_dates dates option to preserve dates when signing
a certificate.
Prevent -days and -preserve_dates being used simultaneously
Fixes #946

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/946)

apps/x509.c
doc/man1/x509.pod

index 840e127..6a24da2 100644 (file)
 
 static int callb(int ok, X509_STORE_CTX *ctx);
 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
 
 static int callb(int ok, X509_STORE_CTX *ctx);
 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
-                const EVP_MD *digest, CONF *conf, const char *section);
+                const EVP_MD *digest, CONF *conf, const char *section,
+                int preserve_dates);
 static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
                         X509 *x, X509 *xca, EVP_PKEY *pkey,
                         STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile,
                         int create, int days, int clrext, CONF *conf,
 static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
                         X509 *x, X509 *xca, EVP_PKEY *pkey,
                         STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile,
                         int create, int days, int clrext, CONF *conf,
-                        const char *section, ASN1_INTEGER *sno, int reqfile);
+                        const char *section, ASN1_INTEGER *sno, int reqfile,
+                        int preserve_dates);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 
 typedef enum OPTION_choice {
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 
 typedef enum OPTION_choice {
@@ -56,7 +58,7 @@ typedef enum OPTION_choice {
     OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
     OPT_SUBJECT_HASH_OLD,
     OPT_ISSUER_HASH_OLD,
     OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
     OPT_SUBJECT_HASH_OLD,
     OPT_ISSUER_HASH_OLD,
-    OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT
+    OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES
 } OPTION_CHOICE;
 
 const OPTIONS x509_options[] = {
 } OPTION_CHOICE;
 
 const OPTIONS x509_options[] = {
@@ -140,6 +142,7 @@ const OPTIONS x509_options[] = {
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
+    {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"},
     {NULL}
 };
 
     {NULL}
 };
 
@@ -173,6 +176,7 @@ int x509_main(int argc, char **argv)
     int enddate = 0;
     time_t checkoffset = 0;
     unsigned long certflag = 0;
     int enddate = 0;
     time_t checkoffset = 0;
     unsigned long certflag = 0;
+    int preserve_dates = 0;
     OPTION_CHOICE o;
     ENGINE *e = NULL;
 #ifndef OPENSSL_NO_MD5
     OPTION_CHOICE o;
     ENGINE *e = NULL;
 #ifndef OPENSSL_NO_MD5
@@ -233,6 +237,8 @@ int x509_main(int argc, char **argv)
                 goto opthelp;
             break;
         case OPT_DAYS:
                 goto opthelp;
             break;
         case OPT_DAYS:
+            if (preserve_dates)
+                goto opthelp;
             days = atoi(opt_arg());
             break;
         case OPT_PASSIN:
             days = atoi(opt_arg());
             break;
         case OPT_PASSIN:
@@ -433,6 +439,11 @@ int x509_main(int argc, char **argv)
         case OPT_CHECKIP:
             checkip = opt_arg();
             break;
         case OPT_CHECKIP:
             checkip = opt_arg();
             break;
+        case OPT_PRESERVE_DATES:
+            if (days != DEF_DAYS)
+                goto opthelp;
+            preserve_dates = 1;
+            break;
         case OPT_MD:
             if (!opt_md(opt_unknown(), &digest))
                 goto opthelp;
         case OPT_MD:
             if (!opt_md(opt_unknown(), &digest))
                 goto opthelp;
@@ -783,7 +794,7 @@ int x509_main(int argc, char **argv)
                 }
 
                 assert(need_rand);
                 }
 
                 assert(need_rand);
-                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
+                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates))
                     goto end;
             } else if (CA_flag == i) {
                 BIO_printf(bio_err, "Getting CA Private Key\n");
                     goto end;
             } else if (CA_flag == i) {
                 BIO_printf(bio_err, "Getting CA Private Key\n");
@@ -798,7 +809,7 @@ int x509_main(int argc, char **argv)
                 if (!x509_certify(ctx, CAfile, digest, x, xca,
                                   CApkey, sigopts,
                                   CAserial, CA_createserial, days, clrext,
                 if (!x509_certify(ctx, CAfile, digest, x, xca,
                                   CApkey, sigopts,
                                   CAserial, CA_createserial, days, clrext,
-                                  extconf, extsect, sno, reqfile))
+                                  extconf, extsect, sno, reqfile, preserve_dates))
                     goto end;
             } else if (x509req == i) {
                 EVP_PKEY *pk;
                     goto end;
             } else if (x509req == i) {
                 EVP_PKEY *pk;
@@ -933,7 +944,7 @@ static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *diges
                         STACK_OF(OPENSSL_STRING) *sigopts,
                         const char *serialfile, int create,
                         int days, int clrext, CONF *conf, const char *section,
                         STACK_OF(OPENSSL_STRING) *sigopts,
                         const char *serialfile, int create,
                         int days, int clrext, CONF *conf, const char *section,
-                        ASN1_INTEGER *sno, int reqfile)
+                        ASN1_INTEGER *sno, int reqfile, int preserve_dates)
 {
     int ret = 0;
     ASN1_INTEGER *bs = NULL;
 {
     int ret = 0;
     ASN1_INTEGER *bs = NULL;
@@ -977,7 +988,7 @@ static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *diges
     if (!X509_set_serialNumber(x, bs))
         goto end;
 
     if (!X509_set_serialNumber(x, bs))
         goto end;
 
-    if (!set_cert_times(x, NULL, NULL, days))
+    if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
         goto end;
 
     if (clrext) {
         goto end;
 
     if (clrext) {
@@ -1041,12 +1052,13 @@ static int callb(int ok, X509_STORE_CTX *ctx)
 
 /* self sign */
 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
 
 /* self sign */
 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
-                const EVP_MD *digest, CONF *conf, const char *section)
+                const EVP_MD *digest, CONF *conf, const char *section,
+                int preserve_dates)
 {
 
     if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
         goto err;
 {
 
     if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
         goto err;
-    if (!set_cert_times(x, NULL, NULL, days))
+    if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
         goto err;
     if (!X509_set_pubkey(x, pkey))
         goto err;
         goto err;
     if (!X509_set_pubkey(x, pkey))
         goto err;
index fccfd6c..b769829 100644 (file)
@@ -60,6 +60,7 @@ B<openssl> B<x509>
 [B<-extfile filename>]
 [B<-extensions section>]
 [B<-engine id>]
 [B<-extfile filename>]
 [B<-extensions section>]
 [B<-engine id>]
+[B<-preserve_dates>]
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -121,6 +122,11 @@ to attempt to obtain a functional reference to the specified engine,
 thus initialising it if needed. The engine will then be set as the default
 for all available algorithms.
 
 thus initialising it if needed. The engine will then be set as the default
 for all available algorithms.
 
+=item B<-preserve_dates>
+
+When signing a certificate, preserve the "notBefore" and "notAfter" dates instead
+of adjusting them to current time and duration. Cannot be used with the B<-days> option.
+
 =back
 
 =head2 Display Options
 =back
 
 =head2 Display Options
@@ -355,7 +361,7 @@ B<-signkey> option.
 =item B<-days arg>
 
 Specifies the number of days to make a certificate valid for. The default
 =item B<-days arg>
 
 Specifies the number of days to make a certificate valid for. The default
-is 30 days.
+is 30 days. Cannot be used with the B<-preserve_dates> option.
 
 =item B<-x509toreq>
 
 
 =item B<-x509toreq>