2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-31 14:25:15 +00:00

Sanity check the TZ environment variable by special casing it in

env_check.  The --with-tzdir configure option can be used to
specify the zoneinfo directory if configure doesn't find it.
This commit is contained in:
Todd C. Miller
2015-02-06 11:01:05 -07:00
parent de11816198
commit c3c28773f5
10 changed files with 224 additions and 21 deletions

View File

@@ -187,6 +187,7 @@ static const char *initial_checkenv_table[] = {
"LC_*",
"LINGUAS",
"TERM",
"TZ",
NULL
};
@@ -202,7 +203,6 @@ static const char *initial_keepenv_table[] = {
"PATH",
"PS1",
"PS2",
"TZ",
"XAUTHORITY",
"XAUTHORIZATION",
NULL
@@ -587,6 +587,54 @@ matches_env_delete(const char *var)
debug_return_bool(matches_env_list(var, &def_env_delete, &full_match));
}
/*
* Sanity-check the TZ environment variable.
* On many systems it is possible to set this to a pathname.
*/
static bool
tz_is_sane(const char *tzval)
{
const char *cp;
char lastch;
debug_decl(tz_is_sane, SUDOERS_DEBUG_ENV)
/* 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] != '/')
debug_return_bool(false);
#else
/* Assume the worst. */
debug_return_bool(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))
debug_return_bool(false);
if (lastch == '/' && cp[0] == '.' && cp[1] == '.' &&
(cp[2] == '/' || cp[2] == '\0'))
debug_return_bool(false);
lastch = *cp;
}
/* Reject extra long TZ values (even if not a path). */
if ((size_t)(cp - tzval) >= PATH_MAX)
debug_return_bool(false);
debug_return_bool(true);
}
/*
* Apply the env_check list.
* Returns true if the variable is allowed, false if denied
@@ -600,9 +648,14 @@ matches_env_check(const char *var, bool *full_match)
/* Skip anything listed in env_check that includes '/' or '%'. */
if (matches_env_list(var, &def_env_check, full_match)) {
const char *val = strchr(var, '=');
if (val != NULL)
keepit = !strpbrk(++val, "/%");
if (strncmp(var, "TZ=", 3) == 0) {
/* Special case for TZ */
keepit = tz_is_sane(var + 3);
} else {
const char *val = strchr(var, '=');
if (val != NULL)
keepit = !strpbrk(++val, "/%");
}
}
debug_return_bool(keepit);
}