diff --git a/MANIFEST b/MANIFEST index 1af7d38a5..cd7dd24ac 100644 --- a/MANIFEST +++ b/MANIFEST @@ -215,6 +215,7 @@ lib/util/getusershell.c lib/util/gidlist.c lib/util/glob.c lib/util/gmtime_r.c +lib/util/timegm.c lib/util/inet_ntop.c lib/util/inet_pton.c lib/util/isblank.c @@ -571,7 +572,6 @@ plugins/sudoers/gentime.c plugins/sudoers/getdate.c plugins/sudoers/getdate.y plugins/sudoers/getspwuid.c -plugins/sudoers/gmtoff.c plugins/sudoers/goodpath.c plugins/sudoers/gram.c plugins/sudoers/gram.h diff --git a/config.h.in b/config.h.in index 1bc16b479..8626973ac 100644 --- a/config.h.in +++ b/config.h.in @@ -964,6 +964,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the `timegm' function. */ +#undef HAVE_TIMEGM + /* Define to 1 if you have the `TLS_method' function. */ #undef HAVE_TLS_METHOD diff --git a/configure b/configure index bf09a9b6a..1a7342d70 100755 --- a/configure +++ b/configure @@ -21189,6 +21189,32 @@ esac done +fi + +done + + for ac_func in timegm +do : + ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm" +if test "x$ac_cv_func_timegm" = xyes +then : + printf "%s\n" "#define HAVE_TIMEGM 1" >>confdefs.h + +else $as_nop + + case " $LIBOBJS " in + *" timegm.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS timegm.$ac_objext" + ;; +esac + + + for _sym in sudo_timegm; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + + fi done diff --git a/configure.ac b/configure.ac index 7b41786cd..85efd8d5f 100644 --- a/configure.ac +++ b/configure.ac @@ -2591,6 +2591,10 @@ AC_CHECK_FUNCS([gmtime_r], [], [ AC_LIBOBJ(gmtime_r) SUDO_APPEND_COMPAT_EXP(sudo_gmtime_r) ]) +AC_CHECK_FUNCS([timegm], [], [ + AC_LIBOBJ(timegm) + SUDO_APPEND_COMPAT_EXP(sudo_timegm) +]) AC_CHECK_FUNCS([getgrouplist], [], [ case "$host_os" in aix*) diff --git a/include/sudo_compat.h b/include/sudo_compat.h index 06cf57371..6839fdbca 100644 --- a/include/sudo_compat.h +++ b/include/sudo_compat.h @@ -467,6 +467,9 @@ sudo_dso_public struct tm *sudo_localtime_r(const time_t *, struct tm *); # undef localtime_r # define localtime_r(_a, _b) sudo_localtime_r((_a), (_b)) #endif /* HAVE_LOCALTIME_R */ +#ifndef HAVE_TIMEGM +sudo_dso_public time_t sudo_timegm(struct tm *); +#endif /* HAVE_TIMEGM */ #ifndef HAVE_UTIMENSAT sudo_dso_public int sudo_utimensat(int fd, const char *file, const struct timespec *times, int flag); # undef utimensat diff --git a/plugins/sudoers/gmtoff.c b/lib/util/timegm.c similarity index 53% rename from plugins/sudoers/gmtoff.c rename to lib/util/timegm.c index 39c9b55a6..d87c4eaad 100644 --- a/plugins/sudoers/gmtoff.c +++ b/lib/util/timegm.c @@ -23,61 +23,76 @@ #include +#ifndef HAVE_TIMEGM + #include #include #include "sudo_compat.h" -#include "sudoers_debug.h" -#include "parse.h" +#include "sudo_debug.h" /* * Returns the offset from GMT in seconds (algorithm taken from sendmail). */ #ifdef HAVE_STRUCT_TM_TM_GMTOFF -long +static long get_gmtoff(time_t *when) { - struct tm local; + struct tm local; - if (localtime_r(when, &local) == NULL) - return 0; + if (localtime_r(when, &local) == NULL) + return 0; - /* Adjust for DST. */ - if (local.tm_isdst != 0) - local.tm_gmtoff -= local.tm_isdst * 3600; + /* Adjust for DST. */ + if (local.tm_isdst != 0) + local.tm_gmtoff -= local.tm_isdst * 3600; - return local.tm_gmtoff; + return local.tm_gmtoff; } #else -long +static long get_gmtoff(time_t *when) { - struct tm gmt, local; - long offset; + struct tm gmt, local; + long offset; - if (gmtime_r(when, &gmt) == NULL) - return 0; - if (localtime_r(when, &local) == NULL) - return 0; + if (gmtime_r(when, &gmt) == NULL) + return 0; + if (localtime_r(when, &local) == NULL) + return 0; - offset = (local.tm_sec - gmt.tm_sec) + - ((local.tm_min - gmt.tm_min) * 60) + - ((local.tm_hour - gmt.tm_hour) * 3600); + offset = (local.tm_sec - gmt.tm_sec) + + ((local.tm_min - gmt.tm_min) * 60) + + ((local.tm_hour - gmt.tm_hour) * 3600); - /* Timezone may cause year rollover to happen on a different day. */ - if (local.tm_year < gmt.tm_year) - offset -= 24 * 3600; - else if (local.tm_year > gmt.tm_year) - offset -= 24 * 3600; - else if (local.tm_yday < gmt.tm_yday) - offset -= 24 * 3600; - else if (local.tm_yday > gmt.tm_yday) - offset += 24 * 3600; + /* Timezone may cause year rollover to happen on a different day. */ + if (local.tm_year < gmt.tm_year) + offset -= 24 * 3600; + else if (local.tm_year > gmt.tm_year) + offset -= 24 * 3600; + else if (local.tm_yday < gmt.tm_yday) + offset -= 24 * 3600; + else if (local.tm_yday > gmt.tm_yday) + offset += 24 * 3600; - /* Adjust for DST. */ - if (local.tm_isdst != 0) - offset -= local.tm_isdst * 3600; + /* Adjust for DST. */ + if (local.tm_isdst != 0) + offset -= local.tm_isdst * 3600; - return offset; + return offset; } #endif /* HAVE_TM_GMTOFF */ + +time_t +sudo_timegm(struct tm *tm) +{ + time_t result; + + result = mktime(tm); + if (result != -1) + result += get_gmtoff(&result); + + return result; +} + +#endif /* HAVE_TIMEGM */ diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 7642d35bd..59eb7602b 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -172,7 +172,7 @@ FUZZ_RUNS = 8192 AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@ LIBPARSESUDOERS_OBJS = alias.lo b64_decode.lo defaults.lo digestname.lo \ - exptilde.lo filedigest.lo gentime.lo gmtoff.lo gram.lo \ + exptilde.lo filedigest.lo gentime.lo gram.lo \ hexchar.lo match.lo match_addr.lo match_command.lo \ match_digest.lo pwutil.lo pwutil_impl.lo \ redblack.lo strlist.lo sudoers_debug.lo timeout.lo \ @@ -233,7 +233,7 @@ CHECK_EXPTILDE_OBJS = check_exptilde.o exptilde.lo pwutil.lo pwutil_impl.lo redb CHECK_FILL_OBJS = check_fill.o hexchar.lo toke_util.lo sudoers_debug.lo -CHECK_GENTIME_OBJS = check_gentime.o gentime.lo gmtoff.lo sudoers_debug.lo +CHECK_GENTIME_OBJS = check_gentime.o gentime.lo sudoers_debug.lo CHECK_HEXCHAR_OBJS = check_hexchar.o hexchar.lo sudoers_debug.lo @@ -1901,18 +1901,6 @@ getspwuid.i: $(srcdir)/getspwuid.c $(devdir)/def_data.h \ $(CC) -E -o $@ $(CPPFLAGS) $< getspwuid.plog: getspwuid.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getspwuid.c --i-file $< --output-file $@ -gmtoff.lo: $(srcdir)/gmtoff.c $(incdir)/compat/stdbool.h \ - $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ - $(incdir)/sudo_queue.h $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \ - $(top_builddir)/config.h - $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/gmtoff.c -gmtoff.i: $(srcdir)/gmtoff.c $(incdir)/compat/stdbool.h \ - $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ - $(incdir)/sudo_queue.h $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \ - $(top_builddir)/config.h - $(CC) -E -o $@ $(CPPFLAGS) $< -gmtoff.plog: gmtoff.i - rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gmtoff.c --i-file $< --output-file $@ goodpath.lo: $(srcdir)/goodpath.c $(devdir)/def_data.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \ diff --git a/plugins/sudoers/gentime.c b/plugins/sudoers/gentime.c index eb6d08147..43ff16260 100644 --- a/plugins/sudoers/gentime.c +++ b/plugins/sudoers/gentime.c @@ -38,6 +38,11 @@ #include "sudoers_debug.h" #include "parse.h" +/* Since timegm() is only used in one place we keep the macro local. */ +#ifndef HAVE_TIMEGM +# define timegm(_t) sudo_timegm(_t) +#endif + /* * Parse a timestamp in Generalized Time format as per RFC4517. * E.g. yyyymmddHHMMSS.FZ or yyyymmddHHMMSS.F[+-]TZOFF @@ -152,11 +157,11 @@ parse_gentime(const char *timestr) tm.tm_year -= 1900; tm.tm_mon--; - result = mktime(&tm); - if (result != -1) { - if (!islocal) { - /* Not local time, convert to GMT */ - result += get_gmtoff(&result); + if (islocal) { + result = mktime(&tm); + } else { + result = timegm(&tm); + if (result != -1) { /* Adjust time based on supplied GMT offset. */ result -= tzoff; } diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 0b9338d19..b60c71dff 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -411,9 +411,6 @@ size_t base64_encode(const unsigned char *in, size_t in_len, char *out, size_t o /* timeout.c */ int parse_timeout(const char *timestr); -/* gmtoff.c */ -long get_gmtoff(time_t *clock); - /* gentime.c */ time_t parse_gentime(const char *expstr); diff --git a/scripts/mkdep.pl b/scripts/mkdep.pl index 0d99a2343..25624b4e3 100755 --- a/scripts/mkdep.pl +++ b/scripts/mkdep.pl @@ -116,7 +116,7 @@ sub mkdep { # XXX - fill in AUTH_OBJS from contents of the auth dir instead $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; $makefile =~ s:\@DIGEST\@:digest.lo digest_openssl.lo digest_gcrypt.lo:; - $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_buf.lo arc4random_uniform.lo cfmakeraw.lo closefrom.lo dup3.lo explicit_bzero.lo fchmodat.lo freezero.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo gmtime_r.lo inet_ntop_lo inet_pton.lo isblank.lo localtime_r.lo memrchr.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo openat.lo pipe2.lo pread.lo pwrite.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo unlinkat.lo utimens.lo:; + $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_buf.lo arc4random_uniform.lo cfmakeraw.lo closefrom.lo dup3.lo explicit_bzero.lo fchmodat.lo freezero.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo gmtime_r.lo inet_ntop_lo inet_pton.lo isblank.lo localtime_r.lo memrchr.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo openat.lo pipe2.lo pread.lo pwrite.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo timegm.lo unlinkat.lo utimens.lo:; # Parse OBJS lines my %objs;