]> 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>
Sun, 14 Aug 2011 14:19:48 +0000 (10:19 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 14 Aug 2011 14:19:48 +0000 (10:19 -0400)
in NewArgv before checking sudoers but unescape non-spaces when
building user_args to make sudoers matching easier.

--HG--
branch : 1.7

sudo.c

diff --git a/sudo.c b/sudo.c
index fbcd99e2e5aea6ae03a7dad008ede6c83f8be72e..c89aed11c947f5e5b16de381cd252b13c85ead96 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -560,31 +560,6 @@ main(argc, argv, envp)
     exit(0);   /* not reached */
 }
 
-/*
- * Escape any non-alpha numeric or blank characters to make sure
- * they are not interpreted specially by the shell.
- */
-static char *
-escape_cmnd(src)
-    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;
-}
-
 /*
  * Initialize timezone, set umask, fill in ``sudo_user'' struct and
  * load the ``interfaces'' array.
@@ -734,15 +709,25 @@ init_vars(envp)
 
        av[0] = user_shell;     /* may be updated later */
        if (NewArgc > 0) {
-           size_t cmnd_size;
-           char *cmnd, *src, *dst, *end;
-           cmnd_size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) +
+           /* shell -c "command" */
+           char *cmnd, *src, *dst;
+           size_t cmnd_size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) +
                    strlen(NewArgv[NewArgc - 1]) + 1;
-           cmnd = dst = emalloc(cmnd_size);
-           src = NewArgv[0];
-           for (end = src + cmnd_size - 1; src < end; src++, dst++)
-               *dst = *src == '\0' ? ' ' : *src;
+
+           cmnd = dst = emalloc2(cmnd_size, 2);
+           for (av = NewArgv; *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';
+
            av[1] = "-c";
            av[2] = cmnd;
            NewArgc = 2;
@@ -792,28 +777,43 @@ set_cmnd(sudo_mode)
 
        /* set user_args */
        if (NewArgc > 1) {
-           char *to, **from;
+           char *to, *from, **av;
            size_t size, n;
 
-           /* If we didn't realloc NewArgv it is contiguous so just count. */
-           if (!ISSET(sudo_mode, MODE_SHELL)) {
-               size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
-                       strlen(NewArgv[NewArgc-1]) + 1;
+           if (ISSET(sudo_mode, MODE_SHELL)) {
+               for (size = 0, av = NewArgv + 1; *av; av++)
+                   size += strlen(*av) + 1;
+               user_args = emalloc(size);
+
+               /*
+                * When running a command via a shell, sudo escapes potential
+                * meta chars in NewArgv.  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 (size = 0, from = NewArgv + 1; *from; from++)
-                   size += strlen(*from) + 1;
+               /* NewArgv is contiguous so just count. */
+               size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[1]) +
+                       strlen(NewArgv[NewArgc - 1]) + 1;
+               user_args = emalloc(size);
+
+               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, init_vars() overflow");
+                   to += n;
+                   *to++ = ' ';
+               }
+               *--to = '\0';
            }
-
-           /* Alloc and build up user_args. */
-           user_args = (char *) 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, init_vars() overflow");
-               to += n;
-               *to++ = ' ';
-           }
-           *--to = '\0';
        }
     }
     if ((user_base = strrchr(user_cmnd, '/')) != NULL)
@@ -937,13 +937,6 @@ run_command(path, argv, envp, uid, dowait)
     cstat.type = CMD_INVALID;
     cstat.val = 0;
 
-    /* Escape meta chars if running a shell with args. */
-    if (ISSET(sudo_mode, MODE_SHELL) && argv[1] != NULL) {
-       char *cmnd = argv[2];
-       argv[2] = escape_cmnd(cmnd);
-       efree(cmnd);
-    }
-
     sudo_execve(path, argv, envp, uid, &cstat, dowait,
        ISSET(sudo_mode, MODE_BACKGROUND));