parse_gentime: use timegm() to generate time since the epoch

The timegm() function is non-standard but widely available.
Provide an implementation for those systems that lack it.
Bug #1006
This commit is contained in:
Todd C. Miller
2021-10-31 09:27:34 -06:00
parent b506497fe4
commit 4eebd53bce
10 changed files with 98 additions and 57 deletions

View File

@@ -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

View File

@@ -964,6 +964,9 @@
/* Define to 1 if you have the <sys/types.h> 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

26
configure vendored
View File

@@ -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

View File

@@ -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*)

View File

@@ -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

View File

@@ -23,61 +23,76 @@
#include <config.h>
#ifndef HAVE_TIMEGM
#include <stdio.h>
#include <time.h>
#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 */

View File

@@ -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 \

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;