1004
|
1 /* su.c - switch user
|
|
2 *
|
|
3 * Copyright 2013 CE Strake <strake888@gmail.com>
|
|
4 *
|
|
5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/su.html
|
|
6
|
|
7 USE_SU(NEWTOY(su, "lmpc:s:", TOYFLAG_BIN))
|
|
8
|
|
9 config SU
|
|
10 bool "su"
|
|
11 default n
|
|
12 help
|
|
13 usage: su [-lmp] [-c cmd] [-s shell] [user [argu...]]
|
|
14
|
|
15 Switch to given user, or root if not given, and call a shell with the given arguments.
|
|
16
|
|
17 options:
|
|
18 -s shell to call
|
|
19 -c command to pass to shell with -c
|
|
20
|
|
21 flags:
|
|
22 -l login shell
|
|
23 -(m|p) preserve environment
|
|
24 */
|
|
25
|
|
26 #define FOR_su
|
|
27 #include "toys.h"
|
|
28
|
|
29 GLOBALS(
|
|
30 char *sArgu;
|
|
31 char *cArgu;
|
|
32 )
|
|
33
|
|
34 extern char **environ;
|
|
35
|
|
36 static void deny () {
|
|
37 printf ("Denied\n");
|
|
38 xexit ();
|
|
39 }
|
|
40
|
|
41 void su_main () {
|
|
42 char *name, *passhash, **argu, **argv;
|
|
43 struct passwd *up;
|
|
44 struct spwd *shp;
|
|
45 long ii;
|
|
46
|
|
47 if (toys.optc && strcmp ("-", toys.optargs[0]) == 0) {
|
|
48 toys.optflags |= FLAG_l;
|
|
49 toys.optc--; toys.optargs++;
|
|
50 }
|
|
51
|
|
52 if (toys.optc) {
|
|
53 name = toys.optargs[0];
|
|
54 toys.optc--; toys.optargs++;
|
|
55 }
|
|
56 else name = "root";
|
|
57 shp = getspnam (name);
|
|
58 if (!shp) perror_exit ("failed to find password");
|
|
59
|
|
60 switch (shp -> sp_pwdp[0]) {
|
|
61 case '!': deny ();
|
|
62 case '$': break;
|
|
63 default : error_exit ("bad password format");
|
|
64 }
|
|
65
|
|
66 if (read_password (toybuf, sizeof (toybuf), "Password: ") != 0) perror_exit ("failed to read password");
|
|
67
|
|
68 passhash = crypt (toybuf, shp -> sp_pwdp);
|
|
69 if (!passhash) perror_exit ("failed to compute password hash");
|
|
70 for (ii = 0; toybuf[ii]; ii++) toybuf[ii] = 0;
|
|
71
|
|
72 if (strcmp (passhash, shp -> sp_pwdp) != 0) deny ();
|
|
73
|
|
74 up = getpwnam (name);
|
|
75 if (!up) perror_exit ("failed to getpwnam");
|
|
76
|
|
77 if (setuid (up -> pw_uid) < 0) perror_exit ("failed to setuid");
|
|
78 if (chdir (up -> pw_dir) < 0) perror_exit ("failed to chdir");
|
|
79
|
|
80 argu = xmalloc (sizeof (char *)*(toys.optc + 4));
|
|
81 argv = argu;
|
|
82 argv[0] = toys.optflags & FLAG_s ? TT.sArgu : up -> pw_shell;
|
|
83 if (toys.optflags & FLAG_c) {
|
|
84 argv[1] = toys.optflags & FLAG_l ? "-lc" : "-c";
|
|
85 argv[2] = TT.cArgu;
|
|
86 argv += 2;
|
|
87 }
|
|
88 else if (toys.optflags & FLAG_l) (argv++)[1] = "-l";
|
|
89 for (ii = 0; ii < toys.optc; ii++) argv[ii + 1] = toys.optargs[ii];
|
|
90 if (execve (argu[0], argu,
|
|
91 toys.optflags & FLAG_l ? (char *[]){
|
|
92 xmsprintf ( "HOME=%s", up -> pw_dir),
|
|
93 xmsprintf ("SHELL=%s", up -> pw_shell),
|
|
94 xmsprintf ( "USER=%s", up -> pw_name),
|
|
95 xmsprintf ( "TERM=%s", getenv ("TERM")),
|
|
96 0
|
|
97 } : environ) < 0) perror_exit ("failed to exec %s", argu[0]);
|
|
98 }
|