aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2009-05-08 15:21:31 +0200
committerTobias Brunner <tobias@strongswan.org>2009-05-08 15:23:50 +0200
commit65ea37abcd3c9deeb3cc63a5f8c1abc11a878ce4 (patch)
tree24351fc57da746d8bbf8d5c6677066fbc0527d85
parent9d737ecfc5660875f0b8c591a9279116364698b0 (diff)
downloadstrongswan-65ea37abcd3c9deeb3cc63a5f8c1abc11a878ce4.tar.bz2
strongswan-65ea37abcd3c9deeb3cc63a5f8c1abc11a878ce4.tar.xz
fixed timezone compensation when parsing ASN.1 dates
-rw-r--r--configure.in24
-rw-r--r--src/libstrongswan/asn1/asn1.c35
2 files changed, 49 insertions, 10 deletions
diff --git a/configure.in b/configure.in
index fe60e63b4..95635b740 100644
--- a/configure.in
+++ b/configure.in
@@ -774,10 +774,6 @@ AC_SEARCH_LIBS(dlopen, dl, [DLLIB=$LIBS])
LIBS=$saved_LIBS
AC_SUBST(DLLIB)
-AC_CHECK_FUNCS(backtrace)
-AC_CHECK_FUNCS(prctl)
-AC_CHECK_FUNCS(gethostbyname_r)
-
AC_MSG_CHECKING(for dladdr)
AC_TRY_COMPILE(
[#define _GNU_SOURCE
@@ -788,6 +784,26 @@ AC_TRY_COMPILE(
[AC_MSG_RESULT([no])]
)
+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)
AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [],
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 5ca7e28f0..c4787d245 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
+#include <pthread.h>
#include <utils.h>
#include <debug.h>
@@ -300,13 +301,26 @@ 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
+
/**
* Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
*/
time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
{
- struct tm t, local;
- time_t tc, tz_offset, now;
+ struct tm t;
+ time_t tc, tz_offset;
u_char *eot = NULL;
if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
@@ -372,17 +386,26 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
t.tm_isdst = 0;
/* convert to time_t */
+#ifdef HAVE_TIMEGM
+ tc = timegm(&t);
+#else
tc = mktime(&t);
-
+#endif
if (tc == -1)
{
return TIME_MAX;
}
/* if no conversion overflow occurred, compensate timezone */
- now = time(NULL);
- localtime_r(&now, &local);
- return tc - local.tm_gmtoff - tz_offset;
+#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;
}
/**