]> granicus.if.org Git - sudo/commitdiff
Allow the user to specify a list of environment variables to preserve.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 3 Aug 2017 13:32:24 +0000 (07:32 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Thu, 3 Aug 2017 13:32:24 +0000 (07:32 -0600)
This adds an option paramter to the --preserve-env option, a
comma-separated list of variable names.

NEWS
doc/sudo.cat
doc/sudo.man.in
doc/sudo.mdoc.in
src/parse_args.c

diff --git a/NEWS b/NEWS
index 6d7d7dab4f7d364e99985a9e60bae2ccdda9cbe0..60f7479220377b9bff4811886d2b93eebda4c644 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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
index a689a951c734af3da8021074f755c99f0de0554c..527f528c45d582f6492da63a352430709f331e5c 100644 (file)
@@ -107,6 +107,13 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
                  policy may return an error if the user does not have
                  permission to preserve the environment.
 
+     -\b--\b-p\bpr\bre\bes\bse\ber\brv\bve\be-\b-e\ben\bnv\bv=\b=l\bli\bis\bst\bt
+                 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.
+
      -\b-e\be, -\b--\b-e\bed\bdi\bit\bt  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 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
      file distributed with s\bsu\bud\bdo\bo 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
index 699aa3508d7a28f3bcc5b5c477dcd37edf3cf19b..a00ee3573370d35530bb1c921aabf155a648e8d5 100644 (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
index e995264d6afcd7d4b717488514288ef102900890..bf1e18cf7e683db1a97dbbffebf34848bf272951 100644 (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
index 1f774e67745d41b6ccb6c44b9ba36af93029dd4a..4b6abd1aafcb1cd59c39f537aaa4674f48b7fbc6 100644 (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':
-                   sudo_settings[ARG_PRESERVE_ENVIRONMENT].value = "true";
+                   /*
+                    * 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",