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