10f66f451Sopenharmony_ci/* sulogin.c - Single User Login.
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2014 Ashish Kumar Gupta <ashishkguptaiit.cse@gmail.com>
40f66f451Sopenharmony_ci * Copyright 2014 Kyungwan Han <asura321@gmail.com>
50f66f451Sopenharmony_ci *
60f66f451Sopenharmony_ci *
70f66f451Sopenharmony_ci * Relies on libcrypt for hash calculation.
80f66f451Sopenharmony_ci * No support for PAM/securetty/selinux/login script/issue/utmp
90f66f451Sopenharmony_ci
100f66f451Sopenharmony_ci
110f66f451Sopenharmony_ciUSE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
120f66f451Sopenharmony_ci
130f66f451Sopenharmony_ciconfig SULOGIN
140f66f451Sopenharmony_ci  bool "sulogin"
150f66f451Sopenharmony_ci  default n
160f66f451Sopenharmony_ci  depends on TOYBOX_SHADOW
170f66f451Sopenharmony_ci  help
180f66f451Sopenharmony_ci    usage: sulogin [-t time] [tty]
190f66f451Sopenharmony_ci
200f66f451Sopenharmony_ci    Single User Login.
210f66f451Sopenharmony_ci    -t	Default Time for Single User Login
220f66f451Sopenharmony_ci*/
230f66f451Sopenharmony_ci#define FOR_sulogin
240f66f451Sopenharmony_ci#include "toys.h"
250f66f451Sopenharmony_ci
260f66f451Sopenharmony_ciGLOBALS(
270f66f451Sopenharmony_ci  long timeout;
280f66f451Sopenharmony_ci  struct termios crntio;
290f66f451Sopenharmony_ci)
300f66f451Sopenharmony_ci
310f66f451Sopenharmony_cistatic void timeout_handle(int signo)
320f66f451Sopenharmony_ci{
330f66f451Sopenharmony_ci  tcsetattr(0, TCSANOW, &(TT.crntio));
340f66f451Sopenharmony_ci  fflush(stdout);
350f66f451Sopenharmony_ci  xprintf("\n Timed out - Normal startup\n");
360f66f451Sopenharmony_ci  exit(0);
370f66f451Sopenharmony_ci}
380f66f451Sopenharmony_ci
390f66f451Sopenharmony_cistatic int validate_password(char *pwd)
400f66f451Sopenharmony_ci{
410f66f451Sopenharmony_ci  struct sigaction sa;
420f66f451Sopenharmony_ci  int ret;
430f66f451Sopenharmony_ci  char *s = "Give root password for system maintenance\n"
440f66f451Sopenharmony_ci    "(or type Control-D for normal startup):",
450f66f451Sopenharmony_ci    *pass;
460f66f451Sopenharmony_ci
470f66f451Sopenharmony_ci  tcgetattr(0, &(TT.crntio));
480f66f451Sopenharmony_ci  sa.sa_handler = timeout_handle;
490f66f451Sopenharmony_ci
500f66f451Sopenharmony_ci  if(TT.timeout) {
510f66f451Sopenharmony_ci    sigaction(SIGALRM, &sa, NULL);
520f66f451Sopenharmony_ci    alarm(TT.timeout);
530f66f451Sopenharmony_ci  }
540f66f451Sopenharmony_ci
550f66f451Sopenharmony_ci  ret = read_password(toybuf, sizeof(toybuf), s);
560f66f451Sopenharmony_ci  if(TT.timeout) alarm(0);
570f66f451Sopenharmony_ci
580f66f451Sopenharmony_ci  if ( ret && !toybuf[0]) {
590f66f451Sopenharmony_ci    xprintf("Normal startup.\n");
600f66f451Sopenharmony_ci    return -1;
610f66f451Sopenharmony_ci  }
620f66f451Sopenharmony_ci
630f66f451Sopenharmony_ci  pass = crypt(toybuf, pwd);
640f66f451Sopenharmony_ci  ret = 1;
650f66f451Sopenharmony_ci  if( pass && !strcmp(pass, pwd)) ret = 0;
660f66f451Sopenharmony_ci
670f66f451Sopenharmony_ci  return ret;
680f66f451Sopenharmony_ci}
690f66f451Sopenharmony_ci
700f66f451Sopenharmony_cistatic void run_shell(char *shell)
710f66f451Sopenharmony_ci{
720f66f451Sopenharmony_ci  snprintf(toybuf,sizeof(toybuf), "-%s", shell);
730f66f451Sopenharmony_ci  execl(shell, toybuf, NULL);
740f66f451Sopenharmony_ci  error_exit("Failed to spawn shell");
750f66f451Sopenharmony_ci}
760f66f451Sopenharmony_ci
770f66f451Sopenharmony_civoid sulogin_main(void)
780f66f451Sopenharmony_ci{
790f66f451Sopenharmony_ci  struct passwd *pwd = NULL;
800f66f451Sopenharmony_ci  struct spwd * spwd = NULL;
810f66f451Sopenharmony_ci  char *forbid[] = {
820f66f451Sopenharmony_ci    "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD",
830f66f451Sopenharmony_ci    "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH",
840f66f451Sopenharmony_ci    "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL", NULL
850f66f451Sopenharmony_ci  };
860f66f451Sopenharmony_ci  char *shell = NULL, *pass = NULL, **temp = forbid;
870f66f451Sopenharmony_ci
880f66f451Sopenharmony_ci  if (toys.optargs[0]) {
890f66f451Sopenharmony_ci    int fd;
900f66f451Sopenharmony_ci
910f66f451Sopenharmony_ci    dup2((fd = xopen_stdio(toys.optargs[0], O_RDWR)), 0);
920f66f451Sopenharmony_ci    if (!isatty(0)) error_exit("%s: it is not a tty", toys.optargs[0]);
930f66f451Sopenharmony_ci    dup2( fd, 1);
940f66f451Sopenharmony_ci    dup2( fd, 2);
950f66f451Sopenharmony_ci    if (fd > 2) close(fd);
960f66f451Sopenharmony_ci  }
970f66f451Sopenharmony_ci
980f66f451Sopenharmony_ci  for (temp = forbid; *temp; temp++) unsetenv(*temp);
990f66f451Sopenharmony_ci
1000f66f451Sopenharmony_ci  if (!(pwd = getpwuid(0))) error_exit("invalid user");
1010f66f451Sopenharmony_ci  pass = pwd->pw_passwd;
1020f66f451Sopenharmony_ci
1030f66f451Sopenharmony_ci  if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) {
1040f66f451Sopenharmony_ci    if ((spwd = getspnam (pwd->pw_name))) pass = spwd->sp_pwdp;
1050f66f451Sopenharmony_ci  }
1060f66f451Sopenharmony_ci
1070f66f451Sopenharmony_ci  while (1) {
1080f66f451Sopenharmony_ci    int r = validate_password(pass);
1090f66f451Sopenharmony_ci
1100f66f451Sopenharmony_ci    if (r == 1) xprintf("Incorrect Login.\n");
1110f66f451Sopenharmony_ci    else if (r == 0) break;
1120f66f451Sopenharmony_ci    else if (r == -1) return;
1130f66f451Sopenharmony_ci  }
1140f66f451Sopenharmony_ci
1150f66f451Sopenharmony_ci  if ((shell = getenv("SUSHELL")) || (shell = getenv("sushell"))
1160f66f451Sopenharmony_ci      || (shell = pwd->pw_shell))
1170f66f451Sopenharmony_ci    run_shell((shell && *shell)? shell: "/bin/sh");
1180f66f451Sopenharmony_ci}
119