Handle UTC vs specified-timezone for certificate extractors. Bug 1541
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 10 Nov 2014 16:41:12 +0000 (16:41 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 11 Nov 2014 23:28:58 +0000 (23:28 +0000)
12 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/os.c
src/src/tls.c
src/src/tlscert-gnu.c
src/src/tlscert-openssl.c
test/confs/2002
test/confs/2102
test/confs/5750
test/confs/5760
test/log/2102
test/log/5760

index 20bfb406ca04be42956d391bb3033a240ac38ef1..8b1a17b26f91fc2339bde898e3c56b403180817c 100644 (file)
@@ -8939,8 +8939,10 @@ a right angle-bracket followed immediately by the new separator.
 Recognised RDN type labels include "CN", "O", "OU" and "DC".
 
 The field selectors marked as "time" above
 Recognised RDN type labels include "CN", "O", "OU" and "DC".
 
 The field selectors marked as "time" above
-may output a number of seconds since epoch
-if the modifier "int" is used.
+take an optional modifier of "int"
+for which the result is the number of seconds since epoch.
+Otherwise the result is a human-readable string
+in the timezone selected by the main "timezone" option.
 
 The field selectors marked as "list" above return a list,
 newline-separated by default,
 
 The field selectors marked as "list" above return a list,
 newline-separated by default,
index 997a459c80fa35adbce2f5f6550299b0af5ba4c5..ae7a06a2054d0c319d307f0dd5991da31e4fe03c 100644 (file)
@@ -67,6 +67,10 @@ JH/09 When compiled with OpenSSL and EXPERIMENTAL_CERTNAMES, the checks on
       "tls_verify_cert_hostname" now do not permit multi-component wildcard
       matches.
 
       "tls_verify_cert_hostname" now do not permit multi-component wildcard
       matches.
 
+JH/10 Time-related extraction expansions from certificates now use the main
+      option "timezone" setting for output formatting, and are consistent
+      between OpenSSL and GnuTLS compilations.  Bug 1541.
+
 
 Exim version 4.84
 -----------------
 
 Exim version 4.84
 -----------------
index 2b6f79c3fab66a24e121bb734e4194b0a5047d81..6e02b8fe298099e96323d39d435ab63107f3c189 100644 (file)
@@ -836,39 +836,6 @@ os_get_dns_resolver_res(void)
 
 /* ----------------------------------------------------------------------- */
 
 
 /* ----------------------------------------------------------------------- */
 
-/***********************************************************
-*                 Time-related functions                   *
-***********************************************************/
-
-/* At least Solaris, and probably others, don't have this */
-
-#ifndef _BSD_SOURCE
-
-# include <time.h>
-# include <stdlib.h>
-
-time_t
-timegm(struct tm * tm)
-{
-time_t ret;
-char *tz;
-
-tz = getenv("TZ");
-setenv("TZ", "", 1);
-tzset();
-ret = mktime(tm);
-if (tz)
-  setenv("TZ", tz, 1);
-else
-  unsetenv("TZ");
-tzset();
-return ret;
-}
-
-#endif
-
-/* ----------------------------------------------------------------------- */
-
 
 
 
 
 
 
index f2ab56706201a8bbc267ea0a031b71366438604a..305eaa410c9b7e91901012b380b2f532dce2ac9b 100644 (file)
@@ -80,6 +80,28 @@ return TRUE;
 }
 
 
 }
 
 
+/*************************************************
+*        Timezone environment flipping           *
+*************************************************/
+
+static uschar *
+to_tz(uschar * tz)
+{
+  uschar * old = US getenv("TZ");
+  setenv("TZ", CS tz, 1);
+  tzset(); 
+  return old;
+}
+static void
+restore_tz(uschar * tz)
+{
+  if (tz)
+    setenv("TZ", CS tz, 1);
+  else
+    unsetenv("TZ");
+  tzset(); 
+}
+
 /*************************************************
 *        Many functions are package-specific     *
 *************************************************/
 /*************************************************
 *        Many functions are package-specific     *
 *************************************************/
index 3261c4e8d3075a5f1280cb782fec74d0a5a4189b..c0ca7c935f76610d58a960ae42fd4796e63a6881 100644 (file)
@@ -98,15 +98,20 @@ static uschar *
 time_copy(time_t t, uschar * mod)
 {
 uschar * cp;
 time_copy(time_t t, uschar * mod)
 {
 uschar * cp;
-struct tm * tp;
-size_t len;
+size_t len = 32;
 
 if (mod && Ustrcmp(mod, "int") == 0)
   return string_sprintf("%u", (unsigned)t);
 
 
 if (mod && Ustrcmp(mod, "int") == 0)
   return string_sprintf("%u", (unsigned)t);
 
-cp = store_get(32);
-tp = gmtime(&t);
-len = strftime(CS cp, 32, "%b %e %T %Y %Z", tp);
+cp = store_get(len);
+if (timestamps_utc)
+  {
+  char * tz = to_tz("GMT0");
+  len = strftime(CS cp, len, "%b %e %T %Y %Z", gmtime(&t));
+  restore_tz(tz);
+  }
+else
+  len = strftime(CS cp, len, "%b %e %T %Y %Z", localtime(&t));
 return len > 0 ? cp : NULL;
 }
 
 return len > 0 ? cp : NULL;
 }
 
index 9444b6d7ca07652544c10cb6b47369503fc680da..8f0fb4d918fc3a246d6c2e6ed7f32968f560763f 100644 (file)
@@ -103,30 +103,65 @@ return cp;
 }
 
 static uschar *
 }
 
 static uschar *
-bio_string_time_to_int(BIO * bp, int len)
-{
-uschar * cp = US"";
-struct tm t;
-len = len > 0 ? (int) BIO_get_mem_data(bp, &cp) : 0;
-/*XXX %Z might be glibc-specific? */
-(void) strptime(CS cp, "%b%t%e%t%T%t%Y%t%Z", &t);
-BIO_free(bp);
-/*XXX timegm might not be portable? */
-return string_sprintf("%u", (unsigned) timegm(&t));
-}
-
-static uschar *
-asn1_time_copy(const ASN1_TIME * time, uschar * mod)
+asn1_time_copy(const ASN1_TIME * asntime, uschar * mod)
 {
 {
+uschar * s = NULL;
 BIO * bp = BIO_new(BIO_s_mem());
 int len;
 
 BIO * bp = BIO_new(BIO_s_mem());
 int len;
 
-if (!bp) return badalloc();
+if (!bp)
+  return badalloc();
+len = ASN1_TIME_print(bp, asntime);
+len = len > 0 ? (int) BIO_get_mem_data(bp, &s) : 0;
 
 
-len = ASN1_TIME_print(bp, time);
-return mod &&  Ustrcmp(mod, "int") == 0
-  ? bio_string_time_to_int(bp, len)
-  : bio_string_copy(bp, len);
+if (mod && Ustrcmp(mod, "raw") == 0)           /* native ASN */
+  s = string_copyn(s, len);
+else
+  {
+  struct tm tm;
+  struct tm * tm_p = &tm;
+  BOOL mod_tz;
+  char * tz = to_tz("GMT0");   /* need to call strptime with baseline TZ */
+
+  /* Parse OpenSSL ASN1_TIME_print output.  A shame there seems to
+  be no other interface for the times.
+  */
+
+  /*XXX %Z might be glibc-specific?  Solaris has it, at least*/
+  /*XXX should we switch to POSIX locale for this? */
+  tm.tm_isdst = 0;
+  if (!strptime(CCS s, "%b %e %T %Y %Z", &tm))
+    expand_string_message = US"failed time conversion";
+
+  else
+    {
+    time_t t = mktime(&tm);    /* make the tm self-consistent */
+
+    if (mod && Ustrcmp(mod, "int") == 0)       /* seconds since epoch */
+      s = string_sprintf("%u", t);
+
+    else
+      {
+      if (!timestamps_utc)     /* decoded string in local TZ */
+       {                               /* shift to local TZ */
+       restore_tz(tz);
+       mod_tz = FALSE;
+       tm_p = localtime(&t);
+       }
+      /* "utc" is default, and rfc5280 says cert times should be Zulu */
+
+      /* convert to string in our format */
+      len = 32;
+      s = store_get(len);
+      strftime(CS s, (size_t)len, "%b %e %T %Y %z", tm_p);
+      }
+    }
+
+  if (mod_tz);
+    restore_tz(tz);
+  }
+BIO_free(bp);
+return s;
 }
 
 static uschar *
 }
 
 static uschar *
index 9f664e8f7e00aa156d827e16da20ac92c012d0ae..69fc749ff3d10409264e947f7a829453df8f9c02 100644 (file)
@@ -8,6 +8,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
 log_file_path = DIR/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+timezone = UTC
 
 # ----- Main settings -----
 
 
 # ----- Main settings -----
 
index 7d5d13a5a733e3c1b3a310da86cd86dd7ff7c6de..88453ed662fb1d4bf0b1cbeced297f7a6449c2e5 100644 (file)
@@ -8,6 +8,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
 log_file_path = DIR/spool/log/%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+timezone = UTC
 
 # ----- Main settings -----
 
 
 # ----- Main settings -----
 
@@ -53,7 +54,8 @@ check_recipient:
          logwrite =  SN  <${certextract {subject}      {$tls_in_peercert}}>
           logwrite =  IN  <${certextract {issuer}      {$tls_in_peercert}}>
           logwrite =  IN/O <${certextract {issuer,O}   {$tls_in_peercert}}>
          logwrite =  SN  <${certextract {subject}      {$tls_in_peercert}}>
           logwrite =  IN  <${certextract {issuer}      {$tls_in_peercert}}>
           logwrite =  IN/O <${certextract {issuer,O}   {$tls_in_peercert}}>
-          logwrite =  NB  <${certextract {notbefore}   {$tls_in_peercert}}>
+          logwrite =  NB/r <${certextract {notbefore,raw}      {$tls_in_peercert}}>
+          logwrite =  NB   <${certextract {notbefore}  {$tls_in_peercert}}>
           logwrite =  NB/i <${certextract {notbefore,int}{$tls_in_peercert}}>
           logwrite =  NA  <${certextract {notafter}    {$tls_in_peercert}}>
           logwrite =  SA  <${certextract {sig_algorithm}{$tls_in_peercert}}>
           logwrite =  NB/i <${certextract {notbefore,int}{$tls_in_peercert}}>
           logwrite =  NA  <${certextract {notafter}    {$tls_in_peercert}}>
           logwrite =  SA  <${certextract {sig_algorithm}{$tls_in_peercert}}>
index 3898530b435893d77493de4cffd209d1a6f54606..a0bce0282bd8346992066104b0c6ec70047f16ec 100644 (file)
@@ -11,6 +11,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/SERVER%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
 log_file_path = DIR/spool/log/SERVER%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+timezone = UTC
 
 # ----- Main settings -----
 
 
 # ----- Main settings -----
 
index d07aa8d9046db2c51733c5a72a586e71d024eb11..3417a2d3285f476b9122065ccf31b8de84fa2d4d 100644 (file)
@@ -11,6 +11,7 @@ spool_directory = DIR/spool
 log_file_path = DIR/spool/log/SERVER%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
 log_file_path = DIR/spool/log/SERVER%slog
 gecos_pattern = ""
 gecos_name = CALLER_NAME
+timezone = UTC
 
 # ----- Main settings -----
 
 
 # ----- Main settings -----
 
index 68a21bb2754c3b5d6676a4fad69132d84d078e0a..da79a816507eef238e3ed8a0fefa11968a83baef 100644 (file)
 1999-03-02 09:44:33 SN  <CN=server2.example.com>
 1999-03-02 09:44:33 IN  <CN=clica Signing Cert,O=example.com>
 1999-03-02 09:44:33 IN/O <example.com>
 1999-03-02 09:44:33 SN  <CN=server2.example.com>
 1999-03-02 09:44:33 IN  <CN=clica Signing Cert,O=example.com>
 1999-03-02 09:44:33 IN/O <example.com>
-1999-03-02 09:44:33 NB  <Nov  1 12:34:06 2012 GMT>
+1999-03-02 09:44:33 NB/r <Nov  1 12:34:06 2012 GMT>
+1999-03-02 09:44:33 NB   <Nov  1 12:34:06 2012 +0000>
 1999-03-02 09:44:33 NB/i <1351773246>
 1999-03-02 09:44:33 NB/i <1351773246>
-1999-03-02 09:44:33 NA  <Jan  1 12:34:06 2038 GMT>
+1999-03-02 09:44:33 NA  <Jan  1 12:34:06 2038 +0000>
 1999-03-02 09:44:33 SA  <sha1WithRSAEncryption>
 1999-03-02 09:44:33 SG  <         6c:37:41:26:4d:5d:f4:b5:31:10:67:ca:fb:64:b6:22:98:62:\n         f7:1e:95:7b:6c:e6:74:47:21:f4:5e:89:36:3e:b9:9c:8a:c5:\n         52:bb:c4:af:12:93:26:3b:d7:3d:e0:56:71:1e:1d:21:20:02:\n         ed:f0:4e:d5:5e:45:42:fd:3c:38:41:54:83:86:0b:3b:bf:c5:\n         47:39:ff:15:ea:93:dc:fd:c7:3d:18:58:59:ca:dd:2a:d8:b9:\n         f9:2f:b9:76:93:f4:ae:e3:91:56:80:2f:8c:04:2f:ad:57:ef:\n         d2:51:19:f4:b4:ef:32:9c:ac:3a:7c:0d:b8:39:db:b1:e3:30:\n         73:1a\n>
 1999-03-02 09:44:33 SAN <DNS=server2.example.com>
 1999-03-02 09:44:33 SA  <sha1WithRSAEncryption>
 1999-03-02 09:44:33 SG  <         6c:37:41:26:4d:5d:f4:b5:31:10:67:ca:fb:64:b6:22:98:62:\n         f7:1e:95:7b:6c:e6:74:47:21:f4:5e:89:36:3e:b9:9c:8a:c5:\n         52:bb:c4:af:12:93:26:3b:d7:3d:e0:56:71:1e:1d:21:20:02:\n         ed:f0:4e:d5:5e:45:42:fd:3c:38:41:54:83:86:0b:3b:bf:c5:\n         47:39:ff:15:ea:93:dc:fd:c7:3d:18:58:59:ca:dd:2a:d8:b9:\n         f9:2f:b9:76:93:f4:ae:e3:91:56:80:2f:8c:04:2f:ad:57:ef:\n         d2:51:19:f4:b4:ef:32:9c:ac:3a:7c:0d:b8:39:db:b1:e3:30:\n         73:1a\n>
 1999-03-02 09:44:33 SAN <DNS=server2.example.com>
index 691ccdae733177d232ff4787299391342bf7cfc2..37757791b056401607f52c8dc9404b8bfeb8e202 100644 (file)
@@ -9,8 +9,8 @@
 1999-03-02 09:44:33 10HmaX-0005vi-00 ver <2>
 1999-03-02 09:44:33 10HmaX-0005vi-00 SN  <CN=clica CA,O=example.com>
 1999-03-02 09:44:33 10HmaX-0005vi-00 IN  <CN=clica CA,O=example.com>
 1999-03-02 09:44:33 10HmaX-0005vi-00 ver <2>
 1999-03-02 09:44:33 10HmaX-0005vi-00 SN  <CN=clica CA,O=example.com>
 1999-03-02 09:44:33 10HmaX-0005vi-00 IN  <CN=clica CA,O=example.com>
-1999-03-02 09:44:33 10HmaX-0005vi-00 NB  <Nov  1 12:34:04 2012 GMT>
-1999-03-02 09:44:33 10HmaX-0005vi-00 NA  <Jan  1 12:34:04 2038 GMT>
+1999-03-02 09:44:33 10HmaX-0005vi-00 NB  <Nov  1 12:34:04 2012 +0000>
+1999-03-02 09:44:33 10HmaX-0005vi-00 NA  <Jan  1 12:34:04 2038 +0000>
 1999-03-02 09:44:33 10HmaX-0005vi-00 SA  <sha1WithRSAEncryption>
 1999-03-02 09:44:33 10HmaX-0005vi-00 SG  <         89:fd:fb:cb:b2:42:d6:aa:f2:c0:44:a2:14:e5:ab:22:50:41:\n         e6:64:e7:1c:5a:20:b6:0f:fe:b0:88:c5:cf:b3:e5:f8:0e:87:\n         eb:ac:07:d6:9d:6a:20:f6:dd:13:ee:b8:3f:cf:d9:cd:d4:a8:\n         72:50:5a:a2:14:4e:ee:3a:78:e2:a7:f4:ae:d7:ee:77:48:1f:\n         75:a7:68:2f:ee:e2:7c:ac:2f:e4:88:02:e8:3b:db:f9:35:04:\n         05:46:35:0b:f2:35:03:21:b6:1e:82:7d:94:e0:63:4b:60:71:\n         2d:19:45:21:f2:85:b4:c3:d0:77:a2:24:32:36:f3:50:68:38:\n         98:e6\n>
 1999-03-02 09:44:33 10HmaX-0005vi-00 (no SAN)
 1999-03-02 09:44:33 10HmaX-0005vi-00 SA  <sha1WithRSAEncryption>
 1999-03-02 09:44:33 10HmaX-0005vi-00 SG  <         89:fd:fb:cb:b2:42:d6:aa:f2:c0:44:a2:14:e5:ab:22:50:41:\n         e6:64:e7:1c:5a:20:b6:0f:fe:b0:88:c5:cf:b3:e5:f8:0e:87:\n         eb:ac:07:d6:9d:6a:20:f6:dd:13:ee:b8:3f:cf:d9:cd:d4:a8:\n         72:50:5a:a2:14:4e:ee:3a:78:e2:a7:f4:ae:d7:ee:77:48:1f:\n         75:a7:68:2f:ee:e2:7c:ac:2f:e4:88:02:e8:3b:db:f9:35:04:\n         05:46:35:0b:f2:35:03:21:b6:1e:82:7d:94:e0:63:4b:60:71:\n         2d:19:45:21:f2:85:b4:c3:d0:77:a2:24:32:36:f3:50:68:38:\n         98:e6\n>
 1999-03-02 09:44:33 10HmaX-0005vi-00 (no SAN)
@@ -32,8 +32,8 @@
 1999-03-02 09:44:33 10HmaY-0005vi-00 ver <2>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SN  <CN=server1.example.com>
 1999-03-02 09:44:33 10HmaY-0005vi-00 IN  <CN=clica Signing Cert,O=example.com>
 1999-03-02 09:44:33 10HmaY-0005vi-00 ver <2>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SN  <CN=server1.example.com>
 1999-03-02 09:44:33 10HmaY-0005vi-00 IN  <CN=clica Signing Cert,O=example.com>
-1999-03-02 09:44:33 10HmaY-0005vi-00 NB  <Nov  1 12:34:05 2012 GMT>
-1999-03-02 09:44:33 10HmaY-0005vi-00 NA  <Jan  1 12:34:05 2038 GMT>
+1999-03-02 09:44:33 10HmaY-0005vi-00 NB  <Nov  1 12:34:05 2012 +0000>
+1999-03-02 09:44:33 10HmaY-0005vi-00 NA  <Jan  1 12:34:05 2038 +0000>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SA  <sha1WithRSAEncryption>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SG  <         56:3a:a4:3c:cb:eb:b8:27:c2:90:08:74:13:88:dc:48:c6:b5:\n         2c:e5:26:be:5b:91:d4:67:e7:3c:49:12:d7:47:30:df:98:db:\n         58:ed:18:a8:7d:4b:db:97:48:f5:5c:7f:70:b9:37:63:33:f1:\n         24:62:72:92:60:f5:6e:da:b6:bc:73:c8:c2:dc:d6:95:9a:bd:\n         16:16:a2:ef:0a:f1:d7:41:68:f6:ad:98:5a:d0:ff:d9:1b:51:\n         9f:59:ce:2f:3d:84:d0:ee:e8:2b:eb:9b:32:1a:0e:02:3e:cc:\n         30:89:44:09:2a:75:81:46:a7:b6:ed:7d:41:eb:5a:63:fa:9c:\n         58:ef\n>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SAN <DNS=server1.example.com;DNS=alternatename2.server1.example.com;DNS=alternatename.server1.example.com>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SA  <sha1WithRSAEncryption>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SG  <         56:3a:a4:3c:cb:eb:b8:27:c2:90:08:74:13:88:dc:48:c6:b5:\n         2c:e5:26:be:5b:91:d4:67:e7:3c:49:12:d7:47:30:df:98:db:\n         58:ed:18:a8:7d:4b:db:97:48:f5:5c:7f:70:b9:37:63:33:f1:\n         24:62:72:92:60:f5:6e:da:b6:bc:73:c8:c2:dc:d6:95:9a:bd:\n         16:16:a2:ef:0a:f1:d7:41:68:f6:ad:98:5a:d0:ff:d9:1b:51:\n         9f:59:ce:2f:3d:84:d0:ee:e8:2b:eb:9b:32:1a:0e:02:3e:cc:\n         30:89:44:09:2a:75:81:46:a7:b6:ed:7d:41:eb:5a:63:fa:9c:\n         58:ef\n>
 1999-03-02 09:44:33 10HmaY-0005vi-00 SAN <DNS=server1.example.com;DNS=alternatename2.server1.example.com;DNS=alternatename.server1.example.com>