annotate toys/pending/su.c @ 1004:13ac68b51d3d

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