1/* sulogin.c - Single User Login. 2 * 3 * Copyright 2014 Ashish Kumar Gupta <ashishkguptaiit.cse@gmail.com> 4 * Copyright 2014 Kyungwan Han <asura321@gmail.com> 5 * 6 * 7 * Relies on libcrypt for hash calculation. 8 * No support for PAM/securetty/selinux/login script/issue/utmp 9 10 11USE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 12 13config SULOGIN 14 bool "sulogin" 15 default n 16 depends on TOYBOX_SHADOW 17 help 18 usage: sulogin [-t time] [tty] 19 20 Single User Login. 21 -t Default Time for Single User Login 22*/ 23#define FOR_sulogin 24#include "toys.h" 25 26GLOBALS( 27 long timeout; 28 struct termios crntio; 29) 30 31static void timeout_handle(int signo) 32{ 33 tcsetattr(0, TCSANOW, &(TT.crntio)); 34 fflush(stdout); 35 xprintf("\n Timed out - Normal startup\n"); 36 exit(0); 37} 38 39static int validate_password(char *pwd) 40{ 41 struct sigaction sa; 42 int ret; 43 char *s = "Give root password for system maintenance\n" 44 "(or type Control-D for normal startup):", 45 *pass; 46 47 tcgetattr(0, &(TT.crntio)); 48 sa.sa_handler = timeout_handle; 49 50 if(TT.timeout) { 51 sigaction(SIGALRM, &sa, NULL); 52 alarm(TT.timeout); 53 } 54 55 ret = read_password(toybuf, sizeof(toybuf), s); 56 if(TT.timeout) alarm(0); 57 58 if ( ret && !toybuf[0]) { 59 xprintf("Normal startup.\n"); 60 return -1; 61 } 62 63 pass = crypt(toybuf, pwd); 64 ret = 1; 65 if( pass && !strcmp(pass, pwd)) ret = 0; 66 67 return ret; 68} 69 70static void run_shell(char *shell) 71{ 72 snprintf(toybuf,sizeof(toybuf), "-%s", shell); 73 execl(shell, toybuf, NULL); 74 error_exit("Failed to spawn shell"); 75} 76 77void sulogin_main(void) 78{ 79 struct passwd *pwd = NULL; 80 struct spwd * spwd = NULL; 81 char *forbid[] = { 82 "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD", 83 "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH", 84 "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL", NULL 85 }; 86 char *shell = NULL, *pass = NULL, **temp = forbid; 87 88 if (toys.optargs[0]) { 89 int fd; 90 91 dup2((fd = xopen_stdio(toys.optargs[0], O_RDWR)), 0); 92 if (!isatty(0)) error_exit("%s: it is not a tty", toys.optargs[0]); 93 dup2( fd, 1); 94 dup2( fd, 2); 95 if (fd > 2) close(fd); 96 } 97 98 for (temp = forbid; *temp; temp++) unsetenv(*temp); 99 100 if (!(pwd = getpwuid(0))) error_exit("invalid user"); 101 pass = pwd->pw_passwd; 102 103 if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) { 104 if ((spwd = getspnam (pwd->pw_name))) pass = spwd->sp_pwdp; 105 } 106 107 while (1) { 108 int r = validate_password(pass); 109 110 if (r == 1) xprintf("Incorrect Login.\n"); 111 else if (r == 0) break; 112 else if (r == -1) return; 113 } 114 115 if ((shell = getenv("SUSHELL")) || (shell = getenv("sushell")) 116 || (shell = pwd->pw_shell)) 117 run_shell((shell && *shell)? shell: "/bin/sh"); 118} 119