From: Todd C. Miller Date: Fri, 29 Jul 2011 14:10:40 +0000 (-0400) Subject: Go back to escaping the command args for "sudo -i" and "sudo -s" X-Git-Tag: SUDO_1_8_2~24^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8255ed69b9c426d90a10c6d68e8d2241d7f3260e;p=sudo Go back to escaping the command args for "sudo -i" and "sudo -s" 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. --- diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 2cc3d8bab..8a8d1ad55 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -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) diff --git a/src/parse_args.c b/src/parse_args.c index c2a7842d3..f8aac4b62 100644 --- a/src/parse_args.c +++ b/src/parse_args.c @@ -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; diff --git a/src/sudo.c b/src/sudo.c index c0eb9942d..658d23eea 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -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. */