asn1: Support dates before 1970-01-01 (i.e. when time_t gets negative)
authorTobias Brunner <tobias@strongswan.org>
Wed, 5 Feb 2014 17:06:15 +0000 (18:06 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 12 Feb 2014 12:54:05 +0000 (13:54 +0100)
On x86 we allow "overflows" around 1969/1970 but not for other dates.

Fixes #509.

src/libstrongswan/asn1/asn1.c
src/libstrongswan/asn1/asn1.h
src/libstrongswan/tests/suites/test_asn1.c

index 21cf1e9..38a6ad6 100644 (file)
@@ -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;
 }
 
 /**
index a1d6253..7a48292 100644 (file)
@@ -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
index 099dbcd..d0cd7e6 100644 (file)
@@ -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" },