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 * TODO: log su attempts 7 8USE_SU(NEWTOY(su, "lmpc:s:", TOYFLAG_BIN|TOYFLAG_ROOTONLY)) 9 10config SU 11 bool "su" 12 default y 13 depends on TOYBOX_SHADOW 14 help 15 usage: su [-lmp] [-c CMD] [-s SHELL] [USER [ARGS...]] 16 17 Switch to user (or root) and run shell (with optional command line). 18 19 -s shell to use 20 -c command to pass to shell with -c 21 -l login shell 22 -(m|p) preserve environment 23*/ 24 25#define FOR_su 26#include "toys.h" 27 28GLOBALS( 29 char *s; 30 char *c; 31) 32 33static char *snapshot_env(char *name) 34{ 35 char *s = getenv(name); 36 37 if (s) return xmprintf("%s=%s", name, s); 38 39 return 0; 40} 41 42void su_main() 43{ 44 char *name, *passhash = 0, **argu, **argv; 45 struct passwd *up; 46 struct spwd *shp; 47 48 if (*toys.optargs && !strcmp("-", *toys.optargs)) { 49 toys.optflags |= FLAG_l; 50 toys.optargs++; 51 } 52 53 if (*toys.optargs) name = *(toys.optargs++); 54 else name = "root"; 55 56 if (!(shp = getspnam(name))) perror_exit("no '%s'", name); 57 if (getuid()) { 58 if (*shp->sp_pwdp != '$') goto deny; 59 if (read_password(toybuf, sizeof(toybuf), "Password: ")) goto deny; 60 passhash = crypt(toybuf, shp->sp_pwdp); 61 memset(toybuf, 0, sizeof(toybuf)); 62 if (!passhash || strcmp(passhash, shp->sp_pwdp)) goto deny; 63 } 64 65 up = xgetpwnam(name); 66 xsetuser(up); 67 68 argv = argu = xmalloc(sizeof(char *)*(toys.optc + 4)); 69 *(argv++) = TT.s ? TT.s : up->pw_shell; 70 71 if (toys.optflags & FLAG_l) { 72 int i; 73 char *stuff[] = {snapshot_env("TERM"), snapshot_env("DISPLAY"), 74 snapshot_env("COLORTERM"), snapshot_env("XAUTHORITY")}; 75 76 clearenv(); 77 for (i=0; i < ARRAY_LEN(stuff); i++) if (stuff[i]) putenv(stuff[i]); 78 *(argv++) = "-l"; 79 xchdir(up->pw_dir); 80 } else unsetenv("IFS"); 81 setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); 82 if (!(toys.optflags & (FLAG_m|FLAG_p))) { 83 setenv("HOME", up->pw_dir, 1); 84 setenv("SHELL", up->pw_shell, 1); 85 setenv("USER", up->pw_name, 1); 86 setenv("LOGNAME", up->pw_name, 1); 87 } else unsetenv("IFS"); 88 89 if (toys.optflags & FLAG_c) { 90 *(argv++) = "-c"; 91 *(argv++) = TT.c; 92 } 93 while ((*(argv++) = *(toys.optargs++))); 94 xexec(argu); 95 96deny: 97 puts("No."); 98 toys.exitval = 1; 99} 100