Home | History | Annotate | Download | only in pending
      1 /* sulogin.c - Single User Login.
      2  *
      3  * Copyright 2014 Ashish Kumar Gupta <ashishkguptaiit.cse (at) gmail.com>
      4  * Copyright 2014 Kyungwan Han <asura321 (at) 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   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 
     26 GLOBALS(
     27   long timeout;
     28   struct termios crntio;
     29 )
     30 
     31 static 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 
     39 static 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 
     70 static 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 
     77 void 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