From 478addb5c6b8b0cdb2454614d5226a23e7b0b356 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Mon, 11 Jul 2011 17:53:25 +0000 Subject: [PATCH] use timegm() for krb5int_gmt_mktime() when available 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 | 2 +- src/util/support/gmt_mktime.c | 36 ++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/configure.in b/src/configure.in index 641a0f364..8789de75b 100644 --- a/src/configure.in +++ b/src/configure.in @@ -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= diff --git a/src/util/support/gmt_mktime.c b/src/util/support/gmt_mktime.c index 2047a8a01..f7f717e9e 100644 --- a/src/util/support/gmt_mktime.c +++ b/src/util/support/gmt_mktime.c @@ -18,6 +18,38 @@ #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 -- 2.26.2