diff options
-rw-r--r-- | configure.in | 16 | ||||
-rw-r--r-- | src/libstrongswan/asn1/asn1.c | 93 |
2 files changed, 39 insertions, 70 deletions
diff --git a/configure.in b/configure.in index a01d51aab..b9235350e 100644 --- a/configure.in +++ b/configure.in @@ -819,22 +819,6 @@ AC_TRY_COMPILE( AC_CHECK_FUNCS(backtrace) AC_CHECK_FUNCS(prctl) AC_CHECK_FUNCS(gethostbyname_r) -AC_CHECK_FUNCS(timegm) - -AC_MSG_CHECKING(for timezone variable) -AC_TRY_LINK( - [#include <time.h>], - [/* check for timezone function (e.g. FreeBSD) */ - return (int)timezone(0, 0);], - [AC_MSG_RESULT([no])], - [AC_TRY_LINK( - [#include <time.h>], - [/* check for global variable */ - return (int)timezone;], - [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_VAR_TIMEZONE])], - [AC_MSG_RESULT([no])] - )] -) AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h) diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index c4787d245..9657c88cf 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -301,26 +301,18 @@ u_int asn1_length(chunk_t *blob) #define TIME_MAX 0x7fffffff -#if !defined(HAVE_TIMEGM) && !defined(HAVE_VAR_TIMEZONE) -pthread_once_t utc_offset_once = PTHREAD_ONCE_INIT; -static time_t utc_offset; -static void init_utc_offset() -{ - time_t now; - struct tm utc; - now = time(NULL); - gmtime_r(&now, &utc); - utc_offset = mktime(&utc) - now; -} -#endif +static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; +static const int tm_leap_1970 = 477; /** * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time */ time_t asn1_to_time(const chunk_t *utctime, asn1_t type) { - struct tm t; - time_t tc, tz_offset; + int tm_year, tm_mon, tm_day, tm_days, tm_hour, tm_min, tm_sec; + int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap; + int tz_hour, tz_min, tz_offset; + time_t tm_secs; u_char *eot = NULL; if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL) @@ -329,15 +321,11 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type) } else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL) { - int tz_hour, tz_min; - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */ } else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL) { - int tz_hour, tz_min; - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */ } @@ -351,61 +339,58 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type) const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d": "%4d%2d%2d%2d%2d"; - sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, &t.tm_min); + sscanf(utctime->ptr, format, &tm_year, &tm_mon, &tm_day, &tm_hour, &tm_min); } /* is there a seconds field? */ if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14)) { - sscanf(eot-2, "%2d", &t.tm_sec); + sscanf(eot-2, "%2d", &tm_sec); } else { - t.tm_sec = 0; + tm_sec = 0; } - /* representation of year */ - if (t.tm_year >= 1900) + /* representation of two-digit years */ + if (type == ASN1_UTCTIME) { - t.tm_year -= 1900; + tm_year += (tm_year < 50) ? 2000 : 1900; } - else if (t.tm_year >= 100) + + /* prevent large 32 bit integer overflows */ + if (sizeof(time_t) == 8 && tm_year > 1938) { - return 0; + return TIME_MAX; } - else if (t.tm_year < 50) + + /* representation of months as 0..11*/ + if (tm_mon > 12) { - t.tm_year += 100; + return 0; /* error in time format */ } + tm_mon--; - /* representation of month 0..11*/ - t.tm_mon--; - - /* set daylight saving time to off */ - t.tm_isdst = 0; - - /* convert to time_t */ -#ifdef HAVE_TIMEGM - tc = timegm(&t); -#else - tc = mktime(&t); -#endif - if (tc == -1) + /* representation of days as 0..30 */ + tm_day--; + + /* number of leap years between last year and 1970? */ + tm_leap_4 = (tm_year - 1) / 4; + tm_leap_100 = tm_leap_4 / 25; + tm_leap_400 = tm_leap_100 / 4; + tm_leap = tm_leap_4 - tm_leap_100 + tm_leap_400 - tm_leap_1970; + + /* if date later then February, is the current year a leap year? */ + if ((tm_mon > 1 && 4*(tm_leap_4 + 1) == tm_year) && + (100*(tm_leap_100 + 1) != tm_year || 400*(tm_leap_400 + 1) == tm_year)) { - return TIME_MAX; - } + tm_leap++; + } + 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; - /* if no conversion overflow occurred, compensate timezone */ -#ifndef HAVE_TIMEGM -#ifdef HAVE_VAR_TIMEZONE - tz_offset += timezone; -#else - pthread_once(&utc_offset_once, init_utc_offset); - tz_offset += utc_offset; -#endif -#endif - return tc - tz_offset; + /* has a 32 bit overflow occurred? */ + return (tm_secs < 0) ? TIME_MAX : tm_secs; } /** |