summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2014-11-10 16:41:12 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2014-11-11 23:28:58 +0000
commite9477a08d2d1f528b1f127f1d563d77e2cf24a22 (patch)
tree9e2c278792c869e0b3b5a9e4c81a1afa1b8e2ab4 /src
parenta163908a12546834f355c40c87b6cb859302b1c6 (diff)
Handle UTC vs specified-timezone for certificate extractors. Bug 1541
Diffstat (limited to 'src')
-rw-r--r--src/src/os.c33
-rw-r--r--src/src/tls.c22
-rw-r--r--src/src/tlscert-gnu.c15
-rw-r--r--src/src/tlscert-openssl.c73
4 files changed, 86 insertions, 57 deletions
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 <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
-
-/* ----------------------------------------------------------------------- */
-
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
@@ -81,6 +81,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 *