Skip to content

Commit 1674a80

Browse files
committed
su.c: implement --exec-command
It's now possible to run commands as other users without shell interpolation by using "--exec-command": Read /etc/shadow as root without specifying user: ``` su --exec-command /bin/cat -- /etc/shadow ``` Or specify user: ``` su --exec-command /bin/cat root -- /etc/shadow ```
1 parent 41985df commit 1674a80

File tree

1 file changed

+39
-4
lines changed

1 file changed

+39
-4
lines changed

src/su.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static bool do_interactive_shell = false;
9494
static bool fakelogin = false;
9595
static /*@observer@*/const char *shellstr;
9696
static /*@null@*/char *command = NULL;
97+
static /*@null@*/char *exec_command = NULL;
9798
static int optidx;
9899

99100

@@ -440,12 +441,14 @@ static void usage (int status)
440441
"\n"
441442
"Options:\n"
442443
" -c, --command COMMAND pass COMMAND to the invoked shell\n"
444+
" -e, --exec PATH run PATH without shell, follow -- with args\n"
443445
" -h, --help display this help message and exit\n"
444446
" -, -l, --login make the shell a login shell\n"
445447
" -m, -p,\n"
446448
" --preserve-environment do not reset environment variables, and\n"
447449
" keep the same shell\n"
448450
" -s, --shell SHELL use SHELL instead of the default in passwd\n"
451+
" -- pass all subsequent arguments on as-is\n"
449452
"\n"
450453
"If no username is given, assume root.\n"), (E_SUCCESS != status) ? stderr : stdout);
451454
exit (status);
@@ -820,6 +823,19 @@ static void process_flags (int argc, char **argv)
820823
}
821824

822825
command = argv[++optidx];
826+
} else if (flags_match (arg, "--exec-command", "-e", NULL)) {
827+
if (optidx == argc - 1) {
828+
flag_arg_required (arg);
829+
}
830+
831+
exec_command = argv[++optidx];
832+
833+
if (access (exec_command, X_OK) < 0) {
834+
fprintf (stderr,
835+
_("%s: unable to access \'%s\'\n"),
836+
Prog, exec_command);
837+
exit (E_BAD_ARG);
838+
}
823839
} else if (flags_match (arg, "--help", "-h", NULL)) {
824840
usage (E_SUCCESS);
825841
} else if (flags_match (arg, "--login", "-l", "-")) {
@@ -843,6 +859,17 @@ static void process_flags (int argc, char **argv)
843859
}
844860
}
845861

862+
if (NULL != exec_command && NULL != command) {
863+
fprintf (stderr,
864+
_("%s: COMMAND and PATH are mutually exclusive\n"),
865+
argv[0]);
866+
usage (E_USAGE);
867+
}
868+
869+
if (NULL != exec_command) {
870+
command = exec_command;
871+
}
872+
846873
/* if next arg is not "--", treat as USER */
847874
if (optidx < argc && strcmp (argv[optidx], "--")) {
848875
STRFCPY (name, argv[optidx++]); /* use this login id */
@@ -1226,10 +1253,18 @@ int main (int argc, char **argv)
12261253
* with the rest of the command line included.
12271254
*/
12281255
argv[-1] = cp;
1229-
execve_shell (shellstr, &argv[-1], environ);
1230-
err = errno;
1231-
(void) fprintf (stderr,
1232-
_("Cannot execute %s\n"), shellstr);
1256+
1257+
if (NULL != exec_command) {
1258+
(void) execve (command, &argv[1], environ);
1259+
err = errno;
1260+
(void) fprintf (stderr,
1261+
_("Cannot execute \'%s\'\n"), command);
1262+
} else {
1263+
execve_shell (shellstr, &argv[-1], environ);
1264+
err = errno;
1265+
(void) fprintf (stderr,
1266+
_("Cannot execute \'%s\'\n"), shellstr);
1267+
}
12331268
errno = err;
12341269
} else {
12351270
(void) shell (shellstr, cp, environ);

0 commit comments

Comments
 (0)