summaryrefslogtreecommitdiffstats
path: root/crypto/asn1
diff options
context:
space:
mode:
authorJ.W. Jagersma <jwjagersma@gmail.com>2022-09-26 20:35:46 +0200
committerTomas Mraz <tomas@openssl.org>2022-09-29 12:00:30 +0200
commitcffb65f2ff85f19418ed121275901674824e52ca (patch)
treef44f1e557bbe0a008d2eae61489835a9e3631a38 /crypto/asn1
parent8ae74c5bc091e7388c082f090c1fde992c31320f (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.c35
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;
}