diff options
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | util-linux/runuser.c | 97 | ||||
-rw-r--r-- | win32/mingw.c | 2 | ||||
-rw-r--r-- | win32/process.c | 2 |
4 files changed, 78 insertions, 24 deletions
diff --git a/include/mingw.h b/include/mingw.h index 7e6109f2e..0ccced2a3 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -593,3 +593,4 @@ char *get_last_slash(const char *path); | |||
593 | const char *applet_to_exe(const char *name); | 593 | const char *applet_to_exe(const char *name); |
594 | char *get_user_name(void); | 594 | char *get_user_name(void); |
595 | char *quote_arg(const char *arg); | 595 | char *quote_arg(const char *arg); |
596 | char *find_first_executable(const char *name); | ||
diff --git a/util-linux/runuser.c b/util-linux/runuser.c index f6abd9a74..6b87c641c 100644 --- a/util-linux/runuser.c +++ b/util-linux/runuser.c | |||
@@ -14,10 +14,19 @@ | |||
14 | //config: depends on PLATFORM_MINGW32 && SH_IS_ASH | 14 | //config: depends on PLATFORM_MINGW32 && SH_IS_ASH |
15 | //config: help | 15 | //config: help |
16 | //config: Run a shell without elevated privileges | 16 | //config: Run a shell without elevated privileges |
17 | //config: | ||
18 | //config:config DROP | ||
19 | //config: bool "drop" | ||
20 | //config: default y | ||
21 | //config: depends on PLATFORM_MINGW32 && SH_IS_ASH | ||
22 | //config: help | ||
23 | //config: Run a command without elevated privileges | ||
17 | 24 | ||
18 | //applet:IF_RUNUSER(APPLET(runuser, BB_DIR_USR_BIN, BB_SUID_DROP)) | 25 | //applet:IF_RUNUSER(APPLET(runuser, BB_DIR_USR_BIN, BB_SUID_DROP)) |
26 | //applet:IF_DROP(APPLET_ODDNAME(drop, runuser, BB_DIR_USR_BIN, BB_SUID_DROP, drop)) | ||
19 | 27 | ||
20 | //kbuild:lib-$(CONFIG_RUNUSER) += runuser.o | 28 | //kbuild:lib-$(CONFIG_RUNUSER) += runuser.o |
29 | //kbuild:lib-$(CONFIG_DROP) += runuser.o | ||
21 | 30 | ||
22 | //usage:#define runuser_trivial_usage | 31 | //usage:#define runuser_trivial_usage |
23 | //usage: "USER [ARG...]" | 32 | //usage: "USER [ARG...]" |
@@ -26,14 +35,26 @@ | |||
26 | //usage: "must be that of the user who was granted those privileges.\n" | 35 | //usage: "must be that of the user who was granted those privileges.\n" |
27 | //usage: "Any arguments are passed to the shell.\n" | 36 | //usage: "Any arguments are passed to the shell.\n" |
28 | 37 | ||
38 | //usage:#define drop_trivial_usage | ||
39 | //usage: "[COMMAND [ARG...]]" | ||
40 | //usage:#define drop_full_usage "\n\n" | ||
41 | //usage: "Run a command without elevated privileges. Run the BusyBox\n" | ||
42 | //usage: "shell if no COMMAND is provided. Any arguments are passed\n" | ||
43 | //usage: "to the command.\n" | ||
44 | |||
29 | #include "libbb.h" | 45 | #include "libbb.h" |
30 | #include <winsafer.h> | 46 | #include <winsafer.h> |
31 | #include <lazyload.h> | 47 | #include <lazyload.h> |
32 | 48 | ||
33 | int runuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 49 | int runuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
34 | int runuser_main(int argc UNUSED_PARAM, char **argv) | 50 | int runuser_main(int argc, char **argv) |
35 | { | 51 | { |
36 | const char *user; | 52 | #if ENABLE_RUNUSER && ENABLE_DROP |
53 | int is_runuser = strcmp(applet_name, "runuser") == 0; | ||
54 | #else | ||
55 | const int is_runuser = ENABLE_RUNUSER; | ||
56 | #endif | ||
57 | const char *user, *exe; | ||
37 | SAFER_LEVEL_HANDLE safer; | 58 | SAFER_LEVEL_HANDLE safer; |
38 | HANDLE token; | 59 | HANDLE token; |
39 | STARTUPINFO si; | 60 | STARTUPINFO si; |
@@ -56,15 +77,17 @@ int runuser_main(int argc UNUSED_PARAM, char **argv) | |||
56 | if (!INIT_PROC_ADDR(advapi32.dll, CreateProcessAsUserA)) | 77 | if (!INIT_PROC_ADDR(advapi32.dll, CreateProcessAsUserA)) |
57 | bb_simple_error_msg_and_die("not supported"); | 78 | bb_simple_error_msg_and_die("not supported"); |
58 | 79 | ||
59 | if (getuid() != 0) | 80 | if (is_runuser) { |
60 | bb_simple_error_msg_and_die("may not be used by non-root users"); | 81 | if (getuid() != 0) |
82 | bb_simple_error_msg_and_die("may not be used by non-root users"); | ||
61 | 83 | ||
62 | if (argc < 2) | 84 | if (argc < 2) |
63 | bb_show_usage(); | 85 | bb_show_usage(); |
64 | 86 | ||
65 | user = get_user_name(); | 87 | user = get_user_name(); |
66 | if (user == NULL || strcmp(argv[1], user) != 0) | 88 | if (user == NULL || strcmp(argv[1], user) != 0) |
67 | bb_simple_error_msg_and_die("invalid user"); | 89 | bb_simple_error_msg_and_die("invalid user"); |
90 | } | ||
68 | 91 | ||
69 | /* | 92 | /* |
70 | * Run a shell using a token with reduced privilege. Hints from: | 93 | * Run a shell using a token with reduced privilege. Hints from: |
@@ -81,16 +104,40 @@ int runuser_main(int argc UNUSED_PARAM, char **argv) | |||
81 | if (SetTokenInformation(token, TokenIntegrityLevel, &TIL, | 104 | if (SetTokenInformation(token, TokenIntegrityLevel, &TIL, |
82 | sizeof(TOKEN_MANDATORY_LABEL))) { | 105 | sizeof(TOKEN_MANDATORY_LABEL))) { |
83 | 106 | ||
84 | ZeroMemory(&si, sizeof(STARTUPINFO)); | 107 | if (is_runuser || argc == 1) { |
85 | si.cb = sizeof(STARTUPINFO); | 108 | exe = bb_busybox_exec_path; |
86 | si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); | 109 | cmd = xstrdup("sh"); |
87 | si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); | 110 | } else { |
88 | si.hStdError = GetStdHandle(STD_ERROR_HANDLE); | 111 | char *file; |
89 | si.dwFlags = STARTF_USESTDHANDLES; | 112 | |
113 | #if ENABLE_FEATURE_PREFER_APPLETS | ||
114 | if (!has_path(argv[1]) && find_applet_by_name(argv[1]) >= 0) { | ||
115 | file = xstrdup(bb_busybox_exec_path); | ||
116 | cmd = argv[1]; | ||
117 | } else | ||
118 | #endif | ||
119 | if (has_path(argv[1])) { | ||
120 | file = cmd = file_is_win32_exe(argv[1]); | ||
121 | } else { | ||
122 | file = cmd = find_first_executable(argv[1]); | ||
123 | } | ||
124 | |||
125 | if (file == NULL) { | ||
126 | xfunc_error_retval = 127; | ||
127 | bb_error_msg_and_die("can't find '%s'", argv[1]); | ||
128 | } | ||
129 | |||
130 | slash_to_bs(file); | ||
131 | exe = file; | ||
132 | cmd = xstrdup(cmd); | ||
133 | file = quote_arg(cmd); | ||
134 | if (file != cmd) | ||
135 | free(cmd); | ||
136 | cmd = file; | ||
137 | } | ||
90 | 138 | ||
91 | // Build the command line | 139 | // Build the command line |
92 | cmd = xstrdup("sh"); | 140 | for (a = argv + 1 + (argc != 1); *a; ++a) { |
93 | for (a = argv + 2; *a; ++a) { | ||
94 | char *q = quote_arg(*a); | 141 | char *q = quote_arg(*a); |
95 | char *newcmd = xasprintf("%s %s", cmd, q); | 142 | char *newcmd = xasprintf("%s %s", cmd, q); |
96 | if (q != *a) | 143 | if (q != *a) |
@@ -99,11 +146,17 @@ int runuser_main(int argc UNUSED_PARAM, char **argv) | |||
99 | cmd = newcmd; | 146 | cmd = newcmd; |
100 | } | 147 | } |
101 | 148 | ||
102 | if (!CreateProcessAsUserA(token, bb_busybox_exec_path, | 149 | ZeroMemory(&si, sizeof(STARTUPINFO)); |
103 | cmd, NULL, NULL, TRUE, 0, NULL, | 150 | si.cb = sizeof(STARTUPINFO); |
104 | NULL, &si, &pi)) { | 151 | si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); |
105 | errno = err_win_to_posix(); | 152 | si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); |
106 | bb_perror_msg_and_die("can't execute 'sh'"); | 153 | si.hStdError = GetStdHandle(STD_ERROR_HANDLE); |
154 | si.dwFlags = STARTF_USESTDHANDLES; | ||
155 | |||
156 | if (!CreateProcessAsUserA(token, exe, cmd, NULL, NULL, TRUE, | ||
157 | 0, NULL, NULL, &si, &pi)) { | ||
158 | xfunc_error_retval = 126; | ||
159 | bb_error_msg_and_die("can't execute '%s'", exe); | ||
107 | } | 160 | } |
108 | 161 | ||
109 | WaitForSingleObject(pi.hProcess, INFINITE); | 162 | WaitForSingleObject(pi.hProcess, INFINITE); |
diff --git a/win32/mingw.c b/win32/mingw.c index 0a1af6b72..fd670ebf6 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1136,7 +1136,7 @@ char *get_user_name(void) | |||
1136 | return user_name; | 1136 | return user_name; |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | #if ENABLE_RUNUSER | 1139 | #if ENABLE_RUNUSER || ENABLE_DROP |
1140 | /* | 1140 | /* |
1141 | * When runuser drops privileges TokenIsElevated still returns TRUE. | 1141 | * When runuser drops privileges TokenIsElevated still returns TRUE. |
1142 | * Use other means to determine if we're actually unprivileged. | 1142 | * Use other means to determine if we're actually unprivileged. |
diff --git a/win32/process.c b/win32/process.c index a0678f50d..7db7741fd 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -204,7 +204,7 @@ quote_arg(const char *arg) | |||
204 | return q; | 204 | return q; |
205 | } | 205 | } |
206 | 206 | ||
207 | static char * | 207 | char * |
208 | find_first_executable(const char *name) | 208 | find_first_executable(const char *name) |
209 | { | 209 | { |
210 | char *tmp, *path = getenv("PATH"); | 210 | char *tmp, *path = getenv("PATH"); |