From e9477a08d2d1f528b1f127f1d563d77e2cf24a22 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 10 Nov 2014 16:41:12 +0000 Subject: Handle UTC vs specified-timezone for certificate extractors. Bug 1541 --- doc/doc-docbook/spec.xfpt | 6 ++-- doc/doc-txt/ChangeLog | 4 +++ src/src/os.c | 33 --------------------- src/src/tls.c | 22 ++++++++++++++ src/src/tlscert-gnu.c | 15 ++++++---- src/src/tlscert-openssl.c | 73 +++++++++++++++++++++++++++++++++++------------ test/confs/2002 | 1 + test/confs/2102 | 4 ++- test/confs/5750 | 1 + test/confs/5760 | 1 + test/log/2102 | 5 ++-- test/log/5760 | 8 +++--- 12 files changed, 107 insertions(+), 66 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 20bfb406c..8b1a17b26 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -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 -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, diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 997a459c8..ae7a06a20 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -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. +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 ----------------- diff --git a/src/src/os.c b/src/src/os.c index 2b6f79c3f..6e02b8fe2 100644 --- a/src/src/os.c +++ b/src/src/os.c @@ -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 -# include - -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 - -/* ----------------------------------------------------------------------- */ - diff --git a/src/src/tls.c b/src/src/tls.c index f2ab56706..305eaa410 100644 --- a/src/src/tls.c +++ b/src/src/tls.c @@ -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 * *************************************************/ diff --git a/src/src/tlscert-gnu.c b/src/src/tlscert-gnu.c index 3261c4e8d..c0ca7c935 100644 --- a/src/src/tlscert-gnu.c +++ b/src/src/tlscert-gnu.c @@ -98,15 +98,20 @@ static uschar * 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); -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; } diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c index 9444b6d7c..8f0fb4d91 100644 --- a/src/src/tlscert-openssl.c +++ b/src/src/tlscert-openssl.c @@ -103,30 +103,65 @@ return cp; } 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; -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 * diff --git a/test/confs/2002 b/test/confs/2002 index 9f664e8f7..69fc749ff 100644 --- a/test/confs/2002 +++ b/test/confs/2002 @@ -8,6 +8,7 @@ spool_directory = DIR/spool log_file_path = DIR/spool/log/%slog gecos_pattern = "" gecos_name = CALLER_NAME +timezone = UTC # ----- Main settings ----- diff --git a/test/confs/2102 b/test/confs/2102 index 7d5d13a5a..88453ed66 100644 --- a/test/confs/2102 +++ b/test/confs/2102 @@ -8,6 +8,7 @@ spool_directory = DIR/spool log_file_path = DIR/spool/log/%slog gecos_pattern = "" gecos_name = CALLER_NAME +timezone = UTC # ----- 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 = 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}}> diff --git a/test/confs/5750 b/test/confs/5750 index 3898530b4..a0bce0282 100644 --- a/test/confs/5750 +++ b/test/confs/5750 @@ -11,6 +11,7 @@ spool_directory = DIR/spool log_file_path = DIR/spool/log/SERVER%slog gecos_pattern = "" gecos_name = CALLER_NAME +timezone = UTC # ----- Main settings ----- diff --git a/test/confs/5760 b/test/confs/5760 index d07aa8d90..3417a2d32 100644 --- a/test/confs/5760 +++ b/test/confs/5760 @@ -11,6 +11,7 @@ spool_directory = DIR/spool log_file_path = DIR/spool/log/SERVER%slog gecos_pattern = "" gecos_name = CALLER_NAME +timezone = UTC # ----- Main settings ----- diff --git a/test/log/2102 b/test/log/2102 index 68a21bb27..da79a8165 100644 --- a/test/log/2102 +++ b/test/log/2102 @@ -14,9 +14,10 @@ 1999-03-02 09:44:33 SN 1999-03-02 09:44:33 IN 1999-03-02 09:44:33 IN/O -1999-03-02 09:44:33 NB +1999-03-02 09:44:33 NB/r +1999-03-02 09:44:33 NB 1999-03-02 09:44:33 NB/i <1351773246> -1999-03-02 09:44:33 NA +1999-03-02 09:44:33 NA 1999-03-02 09:44:33 SA 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 diff --git a/test/log/5760 b/test/log/5760 index 691ccdae7..37757791b 100644 --- a/test/log/5760 +++ b/test/log/5760 @@ -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 1999-03-02 09:44:33 10HmaX-0005vi-00 IN -1999-03-02 09:44:33 10HmaX-0005vi-00 NB -1999-03-02 09:44:33 10HmaX-0005vi-00 NA +1999-03-02 09:44:33 10HmaX-0005vi-00 NB +1999-03-02 09:44:33 10HmaX-0005vi-00 NA 1999-03-02 09:44:33 10HmaX-0005vi-00 SA 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 1999-03-02 09:44:33 10HmaY-0005vi-00 IN -1999-03-02 09:44:33 10HmaY-0005vi-00 NB -1999-03-02 09:44:33 10HmaY-0005vi-00 NA +1999-03-02 09:44:33 10HmaY-0005vi-00 NB +1999-03-02 09:44:33 10HmaY-0005vi-00 NA 1999-03-02 09:44:33 10HmaY-0005vi-00 SA 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 -- cgit v1.2.3