use timegm() for krb5int_gmt_mktime() when available
authorTom Yu <tlyu@mit.edu>
Mon, 11 Jul 2011 17:53:25 +0000 (17:53 +0000)
committerTom Yu <tlyu@mit.edu>
Mon, 11 Jul 2011 17:53:25 +0000 (17:53 +0000)
Use timegm() if it is available, so that krb5int_gmt_mktime()
functions correctly on systems configured with a "right"
(leap-second-aware) time zone.  It is arguably an OS bug if a "right"
time zone can be configured on a system that lacks timegm().

Due to a current lack of evidence of affected systems, the additional
workaround of replacing gmtime() with a version that always ignores
leap seconds is deferred.

ticket: 6928

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25018 dc483132-0cff-0310-8789-dd5450dbe970

src/configure.in
src/util/support/gmt_mktime.c

index 641a0f364de2e6fcb47308a39c866bbb1ea26b68..8789de75b70bfc8dbbc5f1ca2b45f3907eab04b6 100644 (file)
@@ -201,7 +201,7 @@ AC_CONFIG_HEADERS(include/autoconf.h, [echo timestamp > include/autoconf.stamp])
 AC_PROG_LEX
 AC_C_CONST
 AC_HEADER_DIRENT
-AC_CHECK_FUNCS(strdup setvbuf inet_ntoa inet_aton seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror strerror_r)
+AC_CHECK_FUNCS(strdup setvbuf inet_ntoa inet_aton seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strftime strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror strerror_r timegm)
 
 AC_CHECK_FUNC(mkstemp,
 [MKSTEMP_ST_OBJ=
index 2047a8a01077595622be0798a65361251fa6e658..f7f717e9e2fc1d3a661498d76afee705a88caee3 100644 (file)
 
 #include "k5-gmt_mktime.h"
 
+/*
+ * Use the nonstandard timegm() (if available) to convert broken-down
+ * UTC times into time_t values.  Use our custom gmt_mktime() if
+ * timegm() is not available.
+ *
+ * We use gmtime() (or gmtime_r()) when encoding ASN.1 GeneralizedTime
+ * values.  On systems where a "right" (leap-second-aware) time zone
+ * is configured, gmtime() adjusts for the presence of accumulated
+ * leap seconds in the input time_t value.  POSIX requires that time_t
+ * values omit leap seconds; systems configured to include leap
+ * seconds in their time_t values are non-conforming and will have
+ * difficulties exchanging timestamp information with other systems.
+ *
+ * We use krb5int_gmt_mktime() for decoding ASN.1 GeneralizedTime
+ * values.  If timegm() is not available, krb5int_gmt_mktime() won't
+ * be the inverse of gmtime() on a system that counts leap seconds.  A
+ * system configured with a "right" time zone probably has timegm()
+ * available; without it, an application would have no reliable way of
+ * converting broken-down UTC times into time_t values.
+ */
+time_t
+krb5int_gmt_mktime(struct tm *t)
+{
+#if HAVE_TIMEGM
+    return timegm(t);
+#else
+    return gmt_mktime(t);
+#endif
+}
+
+#if !HAVE_TIMEGM || TEST_LEAP
+
 /* take a struct tm, return seconds from GMT epoch */
 /* like mktime, this ignores tm_wday and tm_yday. */
 /* unlike mktime, this does not set them... it only passes a return value. */
@@ -39,7 +71,8 @@ static const int days_in_month[12] = {
 
 #define hasleapday(year) (year%400?(year%100?(year%4?0:1):0):1)
 
-time_t krb5int_gmt_mktime(struct tm *t)
+static time_t
+gmt_mktime(struct tm *t)
 {
     time_t accum;
 
@@ -94,6 +127,7 @@ time_t krb5int_gmt_mktime(struct tm *t)
 
     return accum;
 }
+#endif /* !HAVE_TIMEGM || TEST_LEAP */
 
 #ifdef TEST_LEAP
 int