sulogin.c 2.7 KB

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