1 /* sulogin.c - Single User Login.
3 * Copyright 2014 Ashish Kumar Gupta <ashishkguptaiit.cse@gmail.com>
4 * Copyright 2014 Kyungwan Han <asura321@gmail.com>
7 * Relies on libcrypt for hash calculation.
8 * No support for PAM/securetty/selinux/login script/issue/utmp
11 USE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
16 depends on TOYBOX_SHADOW
18 usage: sulogin [-t time] [tty]
21 -t Default Time for Single User Login
28 struct termios crntio;
31 static void timeout_handle(int signo)
33 tcsetattr(0, TCSANOW, &(TT.crntio));
35 xprintf("\n Timed out - Normal startup\n");
39 static int validate_password(char *pwd)
43 char *s = "Give root password for system maintenance\n"
44 "(or type Control-D for normal startup):",
47 tcgetattr(0, &(TT.crntio));
48 sa.sa_handler = timeout_handle;
51 sigaction(SIGALRM, &sa, NULL);
55 ret = read_password(toybuf, sizeof(toybuf), s);
56 if(TT.timeout) alarm(0);
58 if ( ret && !toybuf[0]) {
59 xprintf("Normal startup.\n");
63 pass = crypt(toybuf, pwd);
65 if( pass && !strcmp(pass, pwd)) ret = 0;
70 static void run_shell(char *shell)
72 snprintf(toybuf,sizeof(toybuf), "-%s", shell);
73 execl(shell, toybuf, NULL);
74 error_exit("Failed to spawn shell");
77 void sulogin_main(void)
79 struct passwd *pwd = NULL;
80 struct spwd * spwd = NULL;
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
86 char *shell = NULL, *pass = NULL, **temp = forbid;
88 if (toys.optargs[0]) {
91 dup2((fd = xopen(toys.optargs[0], O_RDWR)), 0);
92 if (!isatty(0)) error_exit("%s: it is not a tty", toys.optargs[0]);
95 if (fd > 2) close(fd);
98 for (temp = forbid; *temp; temp++) unsetenv(*temp);
100 if (!(pwd = getpwuid(0))) error_exit("invalid user");
101 pass = pwd->pw_passwd;
103 if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) {
104 if ((spwd = getspnam (pwd->pw_name))) pass = spwd->sp_pwdp;
108 int r = validate_password(pass);
110 if (r == 1) xprintf("Incorrect Login.\n");
111 else if (r == 0) break;
112 else if (r == -1) return;
115 if ((shell = getenv("SUSHELL")) || (shell = getenv("sushell"))
116 || (shell = pwd->pw_shell))
117 run_shell((shell && *shell)? shell: "/bin/sh");