1 /*-
2 * Copyright(c) 2024 Baptiste Daroussin <[email protected]>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/limits.h>
8
9 #include <err.h>
10 #include <paths.h>
11 #include <pwd.h>
12 #include <stdbool.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 static void
usage(void)19 usage(void)
20 {
21 fprintf(stderr, "usage: mdo [-u username] [-i] [--] [command [args]]\n");
22 exit(EXIT_FAILURE);
23 }
24
25 int
main(int argc,char ** argv)26 main(int argc, char **argv)
27 {
28 struct passwd *pw;
29 const char *username = "root";
30 bool uidonly = false;
31 int ch;
32
33 while ((ch = getopt(argc, argv, "u:i")) != -1) {
34 switch (ch) {
35 case 'u':
36 username = optarg;
37 break;
38 case 'i':
39 uidonly = true;
40 break;
41 default:
42 usage();
43 }
44 }
45 argc -= optind;
46 argv += optind;
47
48 if ((pw = getpwnam(username)) == NULL) {
49 if (strspn(username, "0123456789") == strlen(username)) {
50 const char *errp = NULL;
51 uid_t uid = strtonum(username, 0, UID_MAX, &errp);
52 if (errp != NULL)
53 err(EXIT_FAILURE, "%s", errp);
54 pw = getpwuid(uid);
55 }
56 if (pw == NULL)
57 err(EXIT_FAILURE, "invalid username '%s'", username);
58 }
59 if (!uidonly) {
60 if (initgroups(pw->pw_name, pw->pw_gid) == -1)
61 err(EXIT_FAILURE, "failed to call initgroups");
62 if (setgid(pw->pw_gid) == -1)
63 err(EXIT_FAILURE, "failed to call setgid");
64 }
65 if (setuid(pw->pw_uid) == -1)
66 err(EXIT_FAILURE, "failed to call setuid");
67 if (*argv == NULL) {
68 const char *sh = getenv("SHELL");
69 if (sh == NULL)
70 sh = _PATH_BSHELL;
71 execlp(sh, sh, "-i", NULL);
72 } else {
73 execvp(argv[0], argv);
74 }
75 err(EXIT_FAILURE, "exec failed");
76 }
77