Allow the user to specify a list of environment variables to preserve.

This adds an option paramter to the --preserve-env option, a
comma-separated list of variable names.
This commit is contained in:
Todd C. Miller
2017-08-03 07:32:24 -06:00
parent 63d954d1fc
commit c18dde2350
5 changed files with 121 additions and 28 deletions

3
NEWS
View File

@@ -56,6 +56,9 @@ What's new in Sudo 1.8.21
the time stamp to commands run by the same process, usually the shell.
Bug #793
* The --preserve-env command line option has been extended to accept
a comma-separated list of environment variables to preserve.
What's new in Sudo 1.8.20p2
* Fixed a bug parsing /proc/pid/stat on Linux when the process

View File

@@ -107,6 +107,13 @@ DDEESSCCRRIIPPTTIIOONN
policy may return an error if the user does not have
permission to preserve the environment.
----pprreesseerrvvee--eennvv==lliisstt
Indicates to the security policy that the user wishes to add
the comma-separated list of environment variables to those
preserved from the user's environment. The security policy
may return an error if the user does not have permission to
preserve the environment.
--ee, ----eeddiitt Edit one or more files instead of running a command. In lieu
of a path name, the string "sudoedit" is used when consulting
the security policy. If the user is authorized by the
@@ -631,4 +638,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or https://www.sudo.ws/license.html for
complete details.
Sudo 1.8.21 July 21, 2017 Sudo 1.8.21
Sudo 1.8.21 Auguest 2, 2017 Sudo 1.8.21

View File

@@ -21,7 +21,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.TH "SUDO" "8" "July 21, 2017" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.TH "SUDO" "8" "Auguest 2, 2017" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"
@@ -260,6 +260,13 @@ preserve their existing environment variables.
The security policy may return an error if the user does not have
permission to preserve the environment.
.TP 12n
\fB\--preserve-env=list\fR
Indicates to the security policy that the user wishes to add the
comma-separated list of environment variables to those preserved
from the user's environment.
The security policy may return an error if the user does not have
permission to preserve the environment.
.TP 12n
\fB\-e\fR, \fB\--edit\fR
Edit one or more files instead of running a command.
In lieu of a path name, the string "sudoedit" is used when consulting

View File

@@ -19,7 +19,7 @@
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
.Dd July 21, 2017
.Dd Auguest 2, 2017
.Dt SUDO @mansectsu@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@@ -236,6 +236,12 @@ Indicates to the security policy that the user wishes to
preserve their existing environment variables.
The security policy may return an error if the user does not have
permission to preserve the environment.
.It Fl -preserve-env=list
Indicates to the security policy that the user wishes to add the
comma-separated list of environment variables to those preserved
from the user's environment.
The security policy may return an error if the user does not have
permission to preserve the environment.
.It Fl e , -edit
Edit one or more files instead of running a command.
In lieu of a path name, the string "sudoedit" is used when consulting

View File

@@ -107,6 +107,12 @@ static struct sudo_settings sudo_settings[] = {
{ NULL }
};
struct environment {
char **envp; /* pointer to the new environment */
size_t env_size; /* size of new_environ in char **'s */
size_t env_len; /* number of slots used, not counting NULL */
};
/*
* Default flags allowed when running a command.
*/
@@ -127,7 +133,7 @@ static struct option long_opts[] = {
{ "background", no_argument, NULL, 'b' },
{ "close-from", required_argument, NULL, 'C' },
{ "login-class", required_argument, NULL, 'c' },
{ "preserve-env", no_argument, NULL, 'E' },
{ "preserve-env", optional_argument, NULL, 'E' },
{ "edit", no_argument, NULL, 'e' },
{ "group", required_argument, NULL, 'g' },
{ "set-home", no_argument, NULL, 'H' },
@@ -152,6 +158,73 @@ static struct option long_opts[] = {
{ NULL, no_argument, NULL, '\0' },
};
/*
* Insert a key=value pair into the specified environment.
*/
static void
env_insert(struct environment *e, char *pair)
{
debug_decl(env_insert, SUDO_DEBUG_ARGS)
/* Make sure we have at least two slots free (one for NULL). */
if (e->env_len + 1 >= e->env_size) {
char **tmp;
if (e->env_size == 0)
e->env_size = 16;
tmp = reallocarray(e->envp, e->env_size, 2 * sizeof(char *));
if (tmp == NULL)
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
e->envp = tmp;
e->env_size *= 2;
}
e->envp[e->env_len++] = pair;
e->envp[e->env_len] = NULL;
debug_return;
}
/*
* Format as var=val and insert into the specified environment.
*/
static void
env_set(struct environment *e, char *var, char *val)
{
char *pair;
debug_decl(env_set, SUDO_DEBUG_ARGS)
pair = sudo_new_key_val(var, val);
if (pair == NULL) {
sudo_fatalx(U_("%s: %s"),
__func__, U_("unable to allocate memory"));
}
env_insert(e, pair);
debug_return;
}
/*
* Parse a comma-separated list of env vars and add to the
* specified environment.
*/
static void
parse_env_list(struct environment *e, char *list)
{
char *cp, *last, *val;
debug_decl(parse_env_list, SUDO_DEBUG_ARGS)
for ((cp = strtok_r(list, ",", &last)); cp != NULL;
(cp = strtok_r(NULL, ",", &last))) {
if (strchr(cp, '=') != NULL) {
sudo_warnx(U_("invalid environment variable name: %s"), cp);
usage(1);
}
if ((val = getenv(cp)) != NULL)
env_set(e, cp, val);
}
debug_return;
}
/*
* Command line argument parsing.
* Sets nargc and nargv which corresponds to the argc/argv we'll use
@@ -161,27 +234,22 @@ int
parse_args(int argc, char **argv, int *nargc, char ***nargv,
struct sudo_settings **settingsp, char ***env_addp)
{
struct environment extra_env;
int mode = 0; /* what mode is sudo to be run in? */
int flags = 0; /* mode flags */
int valid_flags = DEFAULT_VALID_FLAGS;
int ch, i;
char *cp, **env_add;
char *cp;
const char *runas_user = NULL;
const char *runas_group = NULL;
const char *progname;
int proglen;
int nenv = 0;
int env_size = 32;
debug_decl(parse_args, SUDO_DEBUG_ARGS)
/* Is someone trying something funny? */
if (argc <= 0)
usage(1);
env_add = reallocarray(NULL, env_size, sizeof(char *));
if (env_add == NULL)
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
/* Pass progname to plugin so it can call initprogname() */
progname = getprogname();
sudo_settings[ARG_PROGNAME].value = progname;
@@ -218,6 +286,9 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
#define is_envar (optind < argc && argv[optind][0] != '/' && \
strchr(argv[optind], '=') != NULL)
/* Space for environment variables is lazy allocated. */
memset(&extra_env, 0, sizeof(extra_env));
/* XXX - should fill in settings at the end to avoid dupes */
for (;;) {
/*
@@ -253,7 +324,15 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
/* Ignored for backwards compatibility. */
break;
case 'E':
/*
* Optional argument is a comma-separated list of
* environment variables to preserve. If not present,
* preserve everything.
*/
if (optarg == NULL)
sudo_settings[ARG_PRESERVE_ENVIRONMENT].value = "true";
else
parse_env_list(&extra_env, optarg);
break;
case 'e':
if (mode && mode != MODE_EDIT)
@@ -368,25 +447,14 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
usage(1);
}
} else if (!got_end_of_args && is_envar) {
if (nenv == env_size - 2) {
char **tmp;
tmp = reallocarray(env_add, env_size, 2 * sizeof(char *));
if (tmp == NULL)
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
env_add = tmp;
env_size *= 2;
}
env_add[nenv++] = argv[optind];
/* Crank optind and resume getopt. */
/* Insert key=value pair, crank optind and resume getopt. */
env_insert(&extra_env, argv[optind]);
optind++;
} else {
/* Not an option or an environment variable -- we're done. */
break;
}
}
env_add[nenv] = NULL;
argc -= optind;
argv += optind;
@@ -421,10 +489,10 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
if ((flags & valid_flags) != flags)
usage(1);
if (mode == MODE_EDIT &&
(ISSET(flags, MODE_PRESERVE_ENV) || env_add[0] != NULL)) {
(ISSET(flags, MODE_PRESERVE_ENV) || extra_env.env_len != 0)) {
if (ISSET(mode, MODE_PRESERVE_ENV))
sudo_warnx(U_("the `-E' option is not valid in edit mode"));
if (env_add[0] != NULL)
if (extra_env.env_len != 0)
sudo_warnx(U_("you may not specify environment variables in edit mode"));
usage(1);
}
@@ -518,7 +586,7 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv,
}
*settingsp = sudo_settings;
*env_addp = env_add;
*env_addp = extra_env.envp;
*nargc = argc;
*nargv = argv;
debug_return_int(mode | flags);
@@ -624,6 +692,8 @@ help(void)
#endif
sudo_lbuf_append(&lbuf, " -E, --preserve-env %s\n",
_("preserve user environment when running command"));
sudo_lbuf_append(&lbuf, " --preserve-env=list %s\n",
_("preserve specific environment variables"));
sudo_lbuf_append(&lbuf, " -e, --edit %s\n",
_("edit files instead of running a command"));
sudo_lbuf_append(&lbuf, " -g, --group=group %s\n",