sulogin.c revision f9c3fc8475722679029cd653d98965fb2767f20c
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  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
25GLOBALS(
26  long timeout;
27  struct termios crntio;
28)
29
30static 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
38static 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
69static 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
76void 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(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