summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2015-02-10 12:59:02 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2015-02-10 12:59:02 +0000
commit8b91fc494fbb92372195cdbf61ed2ebfcab2d0db (patch)
tree18a015cc9b061a7d82bf39d520ea4960c1b19d3f
parent8d47a8a1cc7b9abeff742775d954906c76a2a164 (diff)
Sanity check TZ environment variable; backport from sudo 1.8.12
-rw-r--r--usr.bin/sudo/INSTALL10
-rw-r--r--usr.bin/sudo/aclocal.m420
-rw-r--r--usr.bin/sudo/configure.in7
-rw-r--r--usr.bin/sudo/env.c57
-rw-r--r--usr.bin/sudo/pathnames.h4
-rw-r--r--usr.bin/sudo/pathnames.h.in4
-rw-r--r--usr.bin/sudo/sudoers.mdoc.in30
7 files changed, 128 insertions, 4 deletions
diff --git a/usr.bin/sudo/INSTALL b/usr.bin/sudo/INSTALL
index b58852b9876..244fd3d647d 100644
--- a/usr.bin/sudo/INSTALL
+++ b/usr.bin/sudo/INSTALL
@@ -104,6 +104,16 @@ Directory and file names:
--srcdir=DIR
Find the sources in DIR [configure dir or ..]
+ --with-tzdir=DIR
+ Set the directory to the system's time zone data files. This
+ is only used when sanitizing the TZ environment variable to
+ allow for fully-qualified paths in TZ.
+ By default, configure will look for an existing "zoneinfo"
+ directory in the following locations:
+ /usr/share /usr/share/lib /usr/lib /etc
+ If no zoneinfo directory is found, the TZ variable may not
+ contain a fully-qualified path.
+
Special features/options:
--with-CC=PATH
Specifies path to C compiler you wish to use.
diff --git a/usr.bin/sudo/aclocal.m4 b/usr.bin/sudo/aclocal.m4
index d8b55c0467b..c181d91567e 100644
--- a/usr.bin/sudo/aclocal.m4
+++ b/usr.bin/sudo/aclocal.m4
@@ -203,6 +203,26 @@ AC_DEFUN(SUDO_TYPE_INO_T,
[SUDO_CHECK_TYPE(ino_t, unsigned int)])
dnl
+dnl Detect time zone file directory, if any.
+dnl
+AC_DEFUN([SUDO_TZDIR], [AC_MSG_CHECKING(time zone data directory)
+tzdir="$with_tzdir"
+if test -z "$tzdir"; then
+ tzdir=no
+ for d in /usr/share /usr/share/lib /usr/lib /etc; do
+ if test -d "$d/zoneinfo"; then
+ tzdir="$d/zoneinfo"
+ break
+ fi
+ done
+fi
+AC_MSG_RESULT([$tzdir])
+if test "${tzdir}" != "no"; then
+ SUDO_DEFINE_UNQUOTED(_PATH_ZONEINFO, "$tzdir")
+fi
+])dnl
+
+dnl
dnl check for working fnmatch(3)
dnl
AC_DEFUN(SUDO_FUNC_FNMATCH,
diff --git a/usr.bin/sudo/configure.in b/usr.bin/sudo/configure.in
index 5846de66985..d619a07678d 100644
--- a/usr.bin/sudo/configure.in
+++ b/usr.bin/sudo/configure.in
@@ -694,6 +694,12 @@ AC_ARG_WITH(timedir, [AS_HELP_STRING([--with-timedir], [path to the sudo timesta
;;
esac])
+AC_ARG_WITH(tzdir, [AS_HELP_STRING([--with-tzdir=DIR], [path to the time zone data directory])],
+[case $with_tzdir in
+ yes) AC_MSG_ERROR(["must give --with-tzdir an argument."])
+ ;;
+esac])
+
AC_ARG_WITH(sendmail, [AS_HELP_STRING([--with-sendmail], [set path to sendmail])
AS_HELP_STRING([--without-sendmail], [do not send mail at all])],
[case $with_sendmail in
@@ -2560,6 +2566,7 @@ dnl Check for log file and timestamp locations
dnl
SUDO_LOGFILE
SUDO_TIMEDIR
+SUDO_TZDIR
dnl
dnl Use passwd (and secureware) auth modules?
diff --git a/usr.bin/sudo/env.c b/usr.bin/sudo/env.c
index ef2785d95bf..dc37afd5b24 100644
--- a/usr.bin/sudo/env.c
+++ b/usr.bin/sudo/env.c
@@ -186,6 +186,7 @@ static const char *initial_checkenv_table[] = {
"LC_*",
"LINGUAS",
"TERM",
+ "TZ",
NULL
};
@@ -203,7 +204,6 @@ static const char *initial_keepenv_table[] = {
"PATH",
"PS1",
"PS2",
- "TZ",
"XAUTHORITY",
"XAUTHORIZATION",
NULL
@@ -513,6 +513,54 @@ matches_env_delete(var)
}
/*
+ * Sanity-check the TZ environment variable.
+ * On many systems it is possible to set this to a pathname.
+ */
+static int
+tz_is_sane(tzval)
+ const char *tzval;
+{
+ const char *cp;
+ char lastch;
+
+ /* tzcode treats a value beginning with a ':' as a path. */
+ if (tzval[0] == ':')
+ tzval++;
+
+ /* Reject fully-qualified TZ that doesn't being with the zoneinfo dir. */
+ if (tzval[0] == '/') {
+#ifdef _PATH_ZONEINFO
+ if (strncmp(tzval, _PATH_ZONEINFO, sizeof(_PATH_ZONEINFO) - 1) != 0 ||
+ tzval[sizeof(_PATH_ZONEINFO) - 1] != '/')
+ return FALSE;
+#else
+ /* Assume the worst. */
+ return FALSE;
+#endif
+ }
+
+ /*
+ * Make sure TZ only contains printable non-space characters
+ * and does not contain a '..' path element.
+ */
+ lastch = '/';
+ for (cp = tzval; *cp != '\0'; cp++) {
+ if (isspace((unsigned char)*cp) || !isprint((unsigned char)*cp))
+ return FALSE;
+ if (lastch == '/' && cp[0] == '.' && cp[1] == '.' &&
+ (cp[2] == '/' || cp[2] == '\0'))
+ return FALSE;
+ lastch = *cp;
+ }
+
+ /* Reject extra long TZ values (even if not a path). */
+ if ((size_t)(cp - tzval) >= PATH_MAX)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
* Apply the env_check list.
* Returns TRUE if the variable is allowed, FALSE if denied
* or -1 if no match.
@@ -535,7 +583,12 @@ matches_env_check(var)
iswild = FALSE;
if (strncmp(cur->value, var, len) == 0 &&
(iswild || var[len] == '=')) {
- keepit = !strpbrk(var, "/%");
+ if (strncmp(var, "TZ=", 3) == 0) {
+ /* Special case for TZ */
+ keepit = tz_is_sane(var + 3);
+ } else {
+ keepit = !strpbrk(var, "/%");
+ }
break;
}
}
diff --git a/usr.bin/sudo/pathnames.h b/usr.bin/sudo/pathnames.h
index 31baa082b49..bcb0cb65039 100644
--- a/usr.bin/sudo/pathnames.h
+++ b/usr.bin/sudo/pathnames.h
@@ -132,3 +132,7 @@
#ifndef _PATH_NETSVC_CONF
/* #undef _PATH_NETSVC_CONF */
#endif /* _PATH_NETSVC_CONF */
+
+#ifndef _PATH_ZONEINFO
+#define _PATH_ZONEINFO "/usr/share/zoneinfo"
+#endif /* _PATH_ZONEINFO */
diff --git a/usr.bin/sudo/pathnames.h.in b/usr.bin/sudo/pathnames.h.in
index aec34eb69d3..8b6f3ca1aa1 100644
--- a/usr.bin/sudo/pathnames.h.in
+++ b/usr.bin/sudo/pathnames.h.in
@@ -129,3 +129,7 @@
#ifndef _PATH_NETSVC_CONF
#undef _PATH_NETSVC_CONF
#endif /* _PATH_NETSVC_CONF */
+
+#ifndef _PATH_ZONEINFO
+#undef _PATH_ZONEINFO
+#endif /* _PATH_ZONEINFO */
diff --git a/usr.bin/sudo/sudoers.mdoc.in b/usr.bin/sudo/sudoers.mdoc.in
index c21ac2f1da4..642611c0dcd 100644
--- a/usr.bin/sudo/sudoers.mdoc.in
+++ b/usr.bin/sudo/sudoers.mdoc.in
@@ -19,7 +19,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
-.Dd $Mdocdate: February 15 2014 $
+.Dd $Mdocdate: February 10 2015 $
.Dt SUDOERS @mansectform@
.Os
.Sh NAME
@@ -2143,7 +2143,13 @@ The default value is
.Sy Lists that can be used in a boolean context :
.Bl -tag -width 16n
.It env_check
-Environment variables to be removed from the user's environment if
+Environment variables to be removed from the user's environment
+unless they are considered
+.Dq safe .
+For all variables except
+Li TZ ,
+.Dq safe
+means that the variable's value does not contain any
the variable's value contains
.Ql %
or
@@ -2151,6 +2157,26 @@ or
characters.
This can be used to guard against printf-style format vulnerabilities
in poorly-written programs.
+The
+.Li TZ
+variable is considerd unsafe if any of the following are true:
+.Bl -bullet
+.It
+It consists of a fully-qualified path name that does not match
+the location of the
+.Pa zoneinfo
+directory.
+.It
+It contains a
+.Pa ..
+path element.
+.It
+It contains white space or non-printable characters.
+.It
+It is longer than the value of
+.Li PATH_MAX .
+.El
+.Pp
The argument may be a double-quoted, space-separated list or a
single value without double-quotes.
The list can be replaced, added to, deleted from, or disabled by using