]> granicus.if.org Git - sudo/commitdiff
Go back to escaping the command args for "sudo -i" and "sudo -s"
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 29 Jul 2011 14:10:40 +0000 (10:10 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 29 Jul 2011 14:10:40 +0000 (10:10 -0400)
before calling the plugin.  Otherwise, spaces in the command args
are not treated properly.  The sudoers plugin will unescape non-spaces
to make matching easier.

plugins/sudoers/sudoers.c
src/parse_args.c
src/sudo.c

index 2cc3d8bab416e5ae57a060071fa4c5f28c582a24..8a8d1ad5500eae748bfe2c480c4a2e248b379882 100644 (file)
@@ -861,21 +861,38 @@ set_cmnd(void)
 
        /* set user_args */
        if (NewArgc > 1) {
-           char *to, **from;
+           char *to, *from, **av;
            size_t size, n;
 
            /* Alloc and build up user_args. */
-           for (size = 0, from = NewArgv + 1; *from; from++)
-               size += strlen(*from) + 1;
+           for (size = 0, av = NewArgv + 1; *av; av++)
+               size += strlen(*av) + 1;
            user_args = emalloc(size);
-           for (to = user_args, from = NewArgv + 1; *from; from++) {
-               n = strlcpy(to, *from, size - (to - user_args));
-               if (n >= size - (to - user_args))
-                   errorx(1, _("internal error, set_cmnd() overflow"));
-               to += n;
-               *to++ = ' ';
+           if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
+               /*
+                * When running a command via a shell, the sudo front-end
+                * escapes potential meta chars.  We unescape non-spaces
+                * for sudoers matching and logging purposes.
+                */
+               for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
+                   while (*from) {
+                       if (from[0] == '\\' && !isspace((unsigned char)from[1]))
+                           from++;
+                       *to++ = *from++;
+                   }
+                   *to++ = ' ';
+               }
+               *--to = '\0';
+           } else {
+               for (to = user_args, av = NewArgv + 1; *av; av++) {
+                   n = strlcpy(to, *av, size - (to - user_args));
+                   if (n >= size - (to - user_args))
+                       errorx(1, _("internal error, set_cmnd() overflow"));
+                   to += n;
+                   *to++ = ' ';
+               }
+               *--to = '\0';
            }
-           *--to = '\0';
        }
     }
     if (strlen(user_cmnd) >= PATH_MAX)
index c2a7842d3aa8a528e08779eb37b3bd7ee7e7118a..f8aac4b62b9f4b07c6042eec0e0338cb24fdbb0d 100644 (file)
@@ -385,17 +385,28 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
            memcpy(av + 1, argv, argc * sizeof(char *));
        } else {
            /* shell -c "command" */
-           char *src, *dst, *end;
+           char *cmnd, *src, *dst;
            size_t cmnd_size = (size_t) (argv[argc - 1] - argv[0]) +
-                   strlen(argv[argc - 1]) + 1;
+               strlen(argv[argc - 1]) + 1;
+
+           cmnd = dst = emalloc2(cmnd_size, 2);
+           for (av = argv; *av != NULL; av++) {
+               for (src = *av; *src != '\0'; src++) {
+                   /* quote potential meta characters */
+                   if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-')
+                       *dst++ = '\\';
+                   *dst++ = *src;
+               }
+               *dst++ = ' ';
+           }
+           if (cmnd != dst)
+               dst--;  /* replace last space with a NUL */
+           *dst = '\0';
+
            ac = 3;
            av = emalloc2(ac + 1, sizeof(char *));
            av[1] = "-c";
-           av[2] = dst = emalloc(cmnd_size);
-           src = argv[0];
-           for (end = src + cmnd_size - 1; src < end; src++, dst++)
-               *dst = *src == '\0' ? ' ' : *src;
-           *dst = '\0';
+           av[2] = cmnd;
        }
        av[0] = (char *)user_details.shell; /* plugin may override shell */
        av[ac] = NULL;
index c0eb9942d4d9bacdfdd42bbfe79c30136ea6c430..658d23eeaa588897431fc4596a38c94d5ceb23a0 100644 (file)
@@ -121,7 +121,6 @@ static int iolog_open(struct plugin_container *plugin, char * const settings[],
     int argc, char * const argv[], char * const user_env[]);
 static void iolog_close(struct plugin_container *plugin, int exit_status,
     int error);
-static char *escape_cmnd(const char *src);
 
 /* Policy plugin convenience functions. */
 static int policy_open(struct plugin_container *plugin, char * const settings[],
@@ -293,12 +292,6 @@ main(int argc, char *argv[], char *envp[])
            if (ISSET(command_details.flags, CD_SUDOEDIT)) {
                exitcode = sudo_edit(&command_details);
            } else {
-               if (ISSET(sudo_mode, MODE_SHELL)) {
-                   /* Escape meta chars if running a shell with args. */
-                   if (argv_out[1] != NULL && strcmp(argv_out[1], "-c") == 0 &&
-                       argv_out[2] != NULL && argv_out[3] == NULL)
-                       argv_out[2] = escape_cmnd(argv_out[2]);
-               }
                exitcode = run_command(&command_details);
            }
            /* The close method was called by sudo_edit/run_command. */
@@ -1054,30 +1047,6 @@ done:
     return rval;
 }
 
-/*
- * Escape any non-alpha numeric or blank characters to make sure
- * they are not interpreted specially by the shell.
- */
-static char *
-escape_cmnd(const char *src)
-{
-    char *cmnd, *dst;
-
-    /* Worst case scenario, we have to escape everything. */
-    cmnd = dst = emalloc((2 * strlen(src)) + 1);
-    while (*src != '\0') {
-       if (!isalnum((unsigned char)*src) && !isspace((unsigned char)*src) &&
-           *src != '_' && *src != '-') {
-           /* quote potential meta character */
-           *dst++ = '\\';
-       }
-       *dst++ = *src++;
-    }
-    *dst++ = '\0';
-
-    return cmnd;
-}
-
 /*
  * Run the command and wait for it to complete.
  */