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