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