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 * TODO: suid support 8 * Supports undocumented compatibility options: -m synonym for -p, - for -l 9 10USE_SU(NEWTOY(su, "^lmpu:g:c:s:[!lmp]", TOYFLAG_BIN|TOYFLAG_ROOTONLY)) 11 12config SU 13 bool "su" 14 default y 15 depends on TOYBOX_SHADOW 16 help 17 usage: su [-lp] [-u UID] [-g GID,...] [-s SHELL] [-c CMD] [USER [COMMAND...]] 18 19 Switch user, prompting for password of new user when not run as root. 20 21 With one argument, switch to USER and run user's shell from /etc/passwd. 22 With no arguments, USER is root. If COMMAND line provided after USER, 23 exec() it as new USER (bypassing shell). If -u or -g specified, first 24 argument (if any) isn't USER (it's COMMAND). 25 26 first argument is USER name to switch to (which must exist). 27 Non-root users are prompted for new user's password. 28 29 -s Shell to use (default is user's shell from /etc/passwd) 30 -c Command line to pass to -s shell (ala sh -c "CMD") 31 -l Reset environment as if new login. 32 -u Switch to UID instead of USER 33 -g Switch to GID (only root allowed, can be comma separated list) 34 -p Preserve environment (except for $PATH and $IFS) 35*/ 36 37#define FOR_su 38#include "toys.h" 39 40GLOBALS( 41 char *s; 42 char *c; 43) 44 45void su_main() 46{ 47 char *name, *passhash = 0, **argu, **argv; 48 struct passwd *up; 49 struct spwd *shp; 50 51 if (*toys.optargs && !strcmp("-", *toys.optargs)) { 52 toys.optflags |= FLAG_l; 53 toys.optargs++; 54 } 55 56 if (*toys.optargs) name = *(toys.optargs++); 57 else name = "root"; 58 59 loggit(LOG_NOTICE, "%s->%s", getusername(geteuid()), name); 60 61 shp = getspnam(name); 62 if (getuid() && shp) { 63 if (*shp->sp_pwdp != '$') goto deny; 64 if (read_password(toybuf, sizeof(toybuf), "Password: ")) goto deny; 65 passhash = crypt(toybuf, shp->sp_pwdp); 66 memset(toybuf, 0, sizeof(toybuf)); 67 if (!passhash || strcmp(passhash, shp->sp_pwdp)) goto deny; 68 } 69 closelog(); 70 71 xsetuser(up = xgetpwnam(name)); 72 73 if (FLAG(m)||FLAG(p)) { 74 unsetenv("IFS"); 75 setenv("PATH", _PATH_DEFPATH, 1); 76 } else reset_env(up, FLAG(l)); 77 78 argv = argu = xmalloc(sizeof(char *)*(toys.optc + 4)); 79 *(argv++) = TT.s ? TT.s : up->pw_shell; 80 loggit(LOG_NOTICE, "run %s", *argu); 81 82 if (FLAG(l)) *(argv++) = "-l"; 83 if (FLAG(c)) { 84 *(argv++) = "-c"; 85 *(argv++) = TT.c; 86 } 87 while ((*(argv++) = *(toys.optargs++))); 88 xexec(argu); 89 90deny: 91 syslog(LOG_NOTICE, "No."); 92 puts("No."); 93 toys.exitval = 1; 94} 95