diff options
author | J.W. Jagersma <jwjagersma@gmail.com> | 2022-09-26 20:35:46 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2022-09-29 12:00:30 +0200 |
commit | cffb65f2ff85f19418ed121275901674824e52ca (patch) | |
tree | f44f1e557bbe0a008d2eae61489835a9e3631a38 /crypto/asn1 | |
parent | 8ae74c5bc091e7388c082f090c1fde992c31320f (diff) |
djgpp: Set TZ=UTC to convert UTC timestamp to time_t
Since djgpp has neither a timezone variable or timegm(), this horrible
method must be used. It is the only one I could find that produces
accurate results, and is recommended as portable alternative to
timegm() by the GNU libc manual. Reference:
https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#index-timegm
Now, a much nicer alternative solution could be:
timestamp_local = mktime(timestamp_tm);
timestamp_utc = timestamp_local + timestamp_tm->tm_gmtoff
- (timestamp_tm->tm_isdst ? 3600 : 0);
This works due to the fact that mktime() populates the tm_gmtoff and
tm_isdst fields in the source timestamp. It is accurate everywhere in
the world, *except* on Lord Howe Island, Australia, where a 30 minute
DST offset is used.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19274)
Diffstat (limited to 'crypto/asn1')
-rw-r--r-- | crypto/asn1/a_time.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 23828b1e31..92be1109a2 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -605,7 +605,9 @@ time_t ossl_asn1_string_to_time_t(const char *asn1_string) { ASN1_TIME *timestamp_asn1 = NULL; struct tm *timestamp_tm = NULL; -#ifndef USE_TIMEGM +#if defined(__DJGPP__) + char *tz = NULL; +#elif !defined(USE_TIMEGM) time_t timestamp_local; #endif time_t timestamp_utc; @@ -627,17 +629,38 @@ time_t ossl_asn1_string_to_time_t(const char *asn1_string) ASN1_TIME_free(timestamp_asn1); return -1; } + ASN1_TIME_free(timestamp_asn1); + +#if defined(__DJGPP__) + /* + * This is NOT thread-safe. Do not use this method for platforms other + * than djgpp. + */ + tz = getenv("TZ"); + if (tz != NULL) { + tz = OPENSSL_strdup(tz); + if (tz == NULL) { + OPENSSL_free(timestamp_tm); + return -1; + } + } + setenv("TZ", "UTC", 1); + + timestamp_utc = mktime(timestamp_tm); -#ifdef USE_TIMEGM + if (tz != NULL) { + setenv("TZ", tz, 1); + OPENSSL_free(tz); + } else { + unsetenv("TZ"); + } +#elif defined(USE_TIMEGM) timestamp_utc = timegm(timestamp_tm); - OPENSSL_free(timestamp_tm); #else timestamp_local = mktime(timestamp_tm); - OPENSSL_free(timestamp_tm); - timestamp_utc = timestamp_local - timezone; #endif + OPENSSL_free(timestamp_tm); - ASN1_TIME_free(timestamp_asn1); return timestamp_utc; } |