From b11e6b59e802f9fab0675126018529db7f2259e0 Mon Sep 17 00:00:00 2001
From: Todd Short <tshort@akamai.com>
Date: Fri, 20 Feb 2015 15:00:28 -0500
Subject: [PATCH 7/9] Add --preserve-dates to x509 app

Patch: x509_preserve_dates.diff
---
 apps/x509.c       |   53 +++++++++++++++++++++++++++++++++--------------------
 doc/apps/x509.pod |    6 ++++++
 2 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/apps/x509.c b/apps/x509.c
index 4b08c18..3811d10 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -150,17 +150,19 @@ static const char *x509_usage[] = {
     " -checkhost host - check certificate matches \"host\"\n",
     " -checkemail email - check certificate matches \"email\"\n",
     " -checkip ipaddr - check certificate matches \"ipaddr\"\n",
+    " -preserve_dates - preserve existing dates when signing\n",
     NULL
 };
 
 static int callb(int ok, X509_STORE_CTX *ctx);
-static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
+static int sign(X509 *x, EVP_PKEY *pkey,int days,int clrext, int preserve_dates,
                 const EVP_MD *digest, CONF *conf, char *section);
 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                         X509 *x, X509 *xca, EVP_PKEY *pkey,
                         STACK_OF(OPENSSL_STRING) *sigopts, char *serial,
-                        int create, int days, int clrext, CONF *conf,
-                        char *section, ASN1_INTEGER *sno);
+                        int create, int days, int clrext,
+                        int preserve_dates, CONF *conf, char *section,
+                        ASN1_INTEGER *sno);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 static int reqfile = 0;
 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
@@ -218,6 +220,7 @@ int MAIN(int argc, char **argv)
 #ifndef OPENSSL_NO_ENGINE
     char *engine = NULL;
 #endif
+    int preserve_dates = 0;
 
     reqfile = 0;
 
@@ -471,6 +474,8 @@ int MAIN(int argc, char **argv)
             clrext = 1;
         else if (strcmp(*argv, "-ocspid") == 0)
             ocspid = ++num;
+        else if (strcmp(*argv, "-preserve_dates") == 0)
+            preserve_dates = 1;
         else if (strcmp(*argv, "-badsig") == 0)
             badsig = 1;
         else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
@@ -903,7 +908,8 @@ int MAIN(int argc, char **argv)
                 }
 
                 assert(need_rand);
-                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
+                if (!sign(x, Upkey, days, clrext, preserve_dates,
+                          digest, extconf, extsect))
                     goto end;
             } else if (CA_flag == i) {
                 BIO_printf(bio_err, "Getting CA Private Key\n");
@@ -919,7 +925,7 @@ int MAIN(int argc, char **argv)
                 if (!x509_certify(ctx, CAfile, digest, x, xca,
                                   CApkey, sigopts,
                                   CAserial, CA_createserial, days, clrext,
-                                  extconf, extsect, sno))
+                                  preserve_dates, extconf, extsect, sno))
                     goto end;
             } else if (x509req == i) {
                 EVP_PKEY *pk;
@@ -1081,7 +1087,8 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                         X509 *x, X509 *xca, EVP_PKEY *pkey,
                         STACK_OF(OPENSSL_STRING) *sigopts,
                         char *serialfile, int create,
-                        int days, int clrext, CONF *conf, char *section,
+                        int days, int clrext, int preserve_dates,
+                        CONF *conf, char *section,
                         ASN1_INTEGER *sno)
 {
     int ret = 0;
@@ -1124,12 +1131,14 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
     if (!X509_set_serialNumber(x, bs))
         goto end;
 
-    if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
-        goto end;
+    if (!preserve_dates) {
+        if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
+            goto end;
 
-    /* hardwired expired */
-    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
-        goto end;
+        /* hardwired expired */
+        if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
+            goto end;
+    }
 
     if (clrext) {
         while (X509_get_ext_count(x) > 0)
@@ -1196,7 +1205,8 @@ static int callb(int ok, X509_STORE_CTX *ctx)
 
 /* self sign */
 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
-                const EVP_MD *digest, CONF *conf, char *section)
+                int preserve_dates, const EVP_MD *digest, CONF *conf,
+                char *section)
 {
 
     EVP_PKEY *pktmp;
@@ -1208,16 +1218,19 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
 
     if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
         goto err;
-    if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
-        goto err;
 
-    /* Lets just make it 12:00am GMT, Jan 1 1970 */
-    /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
-    /* 28 days to be certified */
+    if (!preserve_dates) {
+        if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
+            goto err;
 
-    if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
-        NULL)
-        goto err;
+        /* Lets just make it 12:00am GMT, Jan 1 1970 */
+        /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
+        /* 28 days to be certified */
+
+        if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
+            NULL)
+            goto err;
+    }
 
     if (!X509_set_pubkey(x, pkey))
         goto err;
diff --git a/doc/apps/x509.pod b/doc/apps/x509.pod
index a1326ed..9a5f5f7 100644
--- a/doc/apps/x509.pod
+++ b/doc/apps/x509.pod
@@ -60,6 +60,7 @@ B<openssl> B<x509>
 [B<-extfile filename>]
 [B<-extensions section>]
 [B<-engine id>]
+[B<-preserve_dates>]
 
 =head1 DESCRIPTION
 
@@ -115,6 +116,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.
 
+=item B<-preserve_dates>
+
+When signing a certificate, preserve the "notBefore" and "notAfter" dates instead
+of adjusting them to current time and duration.
+
 =back
 
 =head2 DISPLAY OPTIONS
-- 
1.7.9.5

