From: Tobias Brunner Date: Wed, 5 Feb 2014 17:06:15 +0000 (+0100) Subject: asn1: Support dates before 1970-01-01 (i.e. when time_t gets negative) X-Git-Tag: 5.1.2rc1~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ebc665be4d3dfc6aab71caedb052e635d590c674;p=thirdparty%2Fstrongswan.git asn1: Support dates before 1970-01-01 (i.e. when time_t gets negative) On x86 we allow "overflows" around 1969/1970 but not for other dates. Fixes #509. --- diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index 21cf1e9e6d..38a6ad6883 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -393,8 +393,8 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type) tm_year += (tm_year < 50) ? 2000 : 1900; } - /* prevent large 32 bit integer overflows */ - if (sizeof(time_t) == 4 && tm_year > 2038) + /* prevent obvious 32 bit integer overflows */ + if (sizeof(time_t) == 4 && (tm_year > 2038 || tm_year < 1901)) { return TIME_32_BIT_SIGNED_MAX; } @@ -435,8 +435,20 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type) tm_days = 365 * (tm_year - 1970) + days[tm_mon] + tm_day + tm_leap; tm_secs = 60 * (60 * (24 * tm_days + tm_hour) + tm_min) + tm_sec - tz_offset; - /* has a 32 bit signed integer overflow occurred? */ - return (tm_secs < 0) ? TIME_32_BIT_SIGNED_MAX : tm_secs; + if (sizeof(time_t) == 4) + { /* has a 32 bit signed integer overflow occurred? */ + if (tm_year > 1970 && tm_secs < 0) + { /* depending on the time zone, the first days in 1970 may result in + * a negative value, but dates after 1970 never will */ + return TIME_32_BIT_SIGNED_MAX; + } + if (tm_year < 1969 && tm_secs > 0) + { /* similarly, tm_secs is not positive for dates before 1970, except + * for the last days in 1969, depending on the time zone */ + return TIME_32_BIT_SIGNED_MAX; + } + } + return tm_secs; } /** diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h index a1d6253803..7a48292af8 100644 --- a/src/libstrongswan/asn1/asn1.h +++ b/src/libstrongswan/asn1/asn1.h @@ -191,6 +191,13 @@ void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private); /** * Converts an ASN.1 UTCTIME or GENERALIZEDTIME string to time_t * + * On systems where sizeof(time_t) == 4 there will be an overflow + * for dates + * > Tue, 19 Jan 2038 03:14:07 UTC (0x7fffffff) + * and + * < Fri, 13 Dec 1901 20:45:52 UTC (0x80000000) + * in both cases TIME_32_BIT_SIGNED_MAX is returned. + * * @param utctime body of an ASN.1 coded time object * @param type ASN1_UTCTIME or ASN1_GENERALIZEDTIME * @return time_t in UTC diff --git a/src/libstrongswan/tests/suites/test_asn1.c b/src/libstrongswan/tests/suites/test_asn1.c index 099dbcd812..d0cd7e6e40 100644 --- a/src/libstrongswan/tests/suites/test_asn1.c +++ b/src/libstrongswan/tests/suites/test_asn1.c @@ -490,6 +490,12 @@ START_TEST(test_asn1_to_time) { 0, 0x17, "7001010260Z" }, { 0, 0x17, "7001010203-1Z" }, { 0, 0x17, "700101020361Z" }, + { -631152000, 0x17, "500101000000Z" }, /* UTCTime min */ + { 59, 0x17, "691231235959-0001" }, + { -1, 0x17, "691231235959Z" }, + { 0, 0x17, "700101000000Z" }, + { -60, 0x17, "700101000000+0001" }, + { 2524607999UL, 0x17, "491231235959Z" }, /* UTCTime max */ { 5097600, 0x17, "7003010000Z" }, { 68256000, 0x17, "7203010000Z" }, { 951868800, 0x17, "0003010000Z" },