aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-03-19 10:25:23 +0000
committerRon Yorston <rmy@pobox.com>2023-03-19 10:25:23 +0000
commitb0e7a401d51402c052563f55331c8b9001a1215c (patch)
treedaad4a5fd2ab07a4cc85b837416cd80cc0d7a1e7 /miscutils
parent6de29a7e5346bea9c1c2ad4faf4010ee78f1a97b (diff)
downloadbusybox-w32-b0e7a401d51402c052563f55331c8b9001a1215c.tar.gz
busybox-w32-b0e7a401d51402c052563f55331c8b9001a1215c.tar.bz2
busybox-w32-b0e7a401d51402c052563f55331c8b9001a1215c.zip
runuser,drop: drop runuser, tweak drop
Remove the runuser applet, leaving only drop. Move drop from util-linux to miscutils. A command of the form 'drop -c command' causes the BusyBox shell to be used, just like 'drop' without any arguments. A simple OpenSSH configuration with 'drop.exe' as DefaultShell and no DefaultShellArguments now works both for interactive login and to run a command. This is useful for older versions of OpenSSH which don't support DefaultShellArguments. Saves 208-232 bytes.
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/drop.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/miscutils/drop.c b/miscutils/drop.c
new file mode 100644
index 000000000..3e71f6180
--- /dev/null
+++ b/miscutils/drop.c
@@ -0,0 +1,130 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * drop - run a command without elevated privileges.
4 *
5 * Copyright (c) 2023 Ronald M Yorston
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9//config:config DROP
10//config: bool "drop"
11//config: default y
12//config: depends on PLATFORM_MINGW32 && SH_IS_ASH
13//config: help
14//config: Run a command without elevated privileges
15
16//applet:IF_DROP(APPLET(drop, BB_DIR_USR_BIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_DROP) += drop.o
19
20//usage:#define drop_trivial_usage
21//usage: "[COMMAND | -c [ARG...]]"
22//usage:#define drop_full_usage "\n\n"
23//usage: "Drop elevated privileges and run a command. If no COMMAND\n"
24//usage: "is provided run the BusyBox shell.\n"
25
26#include "libbb.h"
27#include <winsafer.h>
28#include <lazyload.h>
29
30int drop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
31int drop_main(int argc, char **argv)
32{
33 const char *exe;
34 SAFER_LEVEL_HANDLE safer;
35 HANDLE token;
36 STARTUPINFO si;
37 PROCESS_INFORMATION pi;
38 TOKEN_MANDATORY_LABEL TIL;
39 // Medium integrity level S-1-16-8192
40 unsigned char medium[12] = {
41 0x01, 0x01, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x10,
43 0x00, 0x20, 0x00, 0x00
44 };
45 char *cmd, *q, *newcmd, **a;
46 DWORD code;
47 // This shouldn't be necessary but without it the binary complains
48 // it can't find CreateProcessAsUserA on older versions of Windows.
49 DECLARE_PROC_ADDR(BOOL, CreateProcessAsUserA, HANDLE, LPCSTR, LPSTR,
50 LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD,
51 LPVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
52
53 if (!INIT_PROC_ADDR(advapi32.dll, CreateProcessAsUserA))
54 bb_simple_error_msg_and_die("not supported");
55
56 /*
57 * Run a shell using a token with reduced privilege. Hints from:
58 *
59 * https://stackoverflow.com/questions/17765568/
60 */
61 if (SaferCreateLevel(SAFER_SCOPEID_USER, SAFER_LEVELID_NORMALUSER,
62 SAFER_LEVEL_OPEN, &safer, NULL) &&
63 SaferComputeTokenFromLevel(safer, NULL, &token, 0, NULL)) {
64
65 // Set medium integrity
66 TIL.Label.Sid = (PSID)medium;
67 TIL.Label.Attributes = SE_GROUP_INTEGRITY;
68 if (SetTokenInformation(token, TokenIntegrityLevel, &TIL,
69 sizeof(TOKEN_MANDATORY_LABEL))) {
70 int skip = 1;
71
72 if (argc == 1 || strcmp(argv[1], "-c") == 0) {
73 exe = bb_busybox_exec_path;
74 cmd = xstrdup("sh");
75 skip = 0;
76 } else {
77 char *file;
78
79#if ENABLE_FEATURE_PREFER_APPLETS
80 if (!has_path(argv[1]) && find_applet_by_name(argv[1]) >= 0) {
81 file = xstrdup(bb_busybox_exec_path);
82 } else
83#endif
84 if (has_path(argv[1])) {
85 file = file_is_win32_exe(argv[1]);
86 } else {
87 file = find_first_executable(argv[1]);
88 }
89
90 if (file == NULL) {
91 xfunc_error_retval = 127;
92 bb_error_msg_and_die("can't find '%s'", argv[1]);
93 }
94
95 slash_to_bs(file);
96 exe = file;
97 cmd = quote_arg(argv[1]);
98 }
99
100 // Build the command line
101 for (a = argv + 1 + skip; *a; ++a) {
102 q = quote_arg(*a);
103 newcmd = xasprintf("%s %s", cmd, q);
104 free(q);
105 free(cmd);
106 cmd = newcmd;
107 }
108
109 ZeroMemory(&si, sizeof(STARTUPINFO));
110 si.cb = sizeof(STARTUPINFO);
111 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
112 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
113 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
114 si.dwFlags = STARTF_USESTDHANDLES;
115
116 if (!CreateProcessAsUserA(token, exe, cmd, NULL, NULL, TRUE,
117 0, NULL, NULL, &si, &pi)) {
118 xfunc_error_retval = 126;
119 bb_error_msg_and_die("can't execute '%s'", exe);
120 }
121
122 WaitForSingleObject(pi.hProcess, INFINITE);
123 if (GetExitCodeProcess(pi.hProcess, &code)) {
124 return (int)code;
125 }
126 }
127 }
128
129 return EXIT_FAILURE;
130}