sulogin.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini sulogin implementation for busybox
  4. *
  5. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  6. */
  7. //config:config SULOGIN
  8. //config: bool "sulogin"
  9. //config: default y
  10. //config: select FEATURE_SYSLOG
  11. //config: help
  12. //config: sulogin is invoked when the system goes into single user
  13. //config: mode (this is done through an entry in inittab).
  14. //applet:IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP))
  15. //kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
  16. //usage:#define sulogin_trivial_usage
  17. //usage: "[-t N] [TTY]"
  18. //usage:#define sulogin_full_usage "\n\n"
  19. //usage: "Single user login\n"
  20. //usage: "\n -t N Timeout"
  21. #include "libbb.h"
  22. #include <syslog.h>
  23. int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  24. int sulogin_main(int argc UNUSED_PARAM, char **argv)
  25. {
  26. int timeout = 0;
  27. struct passwd *pwd;
  28. const char *shell;
  29. /* Note: sulogin is not a suid app. It is meant to be run by init
  30. * for single user / emergency mode. init starts it as root.
  31. * Normal users (potentially malisious ones) can only run it under
  32. * their UID, therefore no paranoia here is warranted:
  33. * $LD_LIBRARY_PATH in env, TTY = /dev/sda
  34. * are no more dangerous here than in e.g. cp applet.
  35. */
  36. logmode = LOGMODE_BOTH;
  37. openlog(applet_name, 0, LOG_AUTH);
  38. opt_complementary = "t+"; /* -t N */
  39. getopt32(argv, "t:", &timeout);
  40. argv += optind;
  41. if (argv[0]) {
  42. close(0);
  43. close(1);
  44. dup(xopen(argv[0], O_RDWR));
  45. close(2);
  46. dup(0);
  47. }
  48. pwd = getpwuid(0);
  49. if (!pwd) {
  50. bb_error_msg_and_die("no password entry for root");
  51. }
  52. while (1) {
  53. int r;
  54. r = ask_and_check_password_extended(pwd, timeout,
  55. "Give root password for system maintenance\n"
  56. "(or type Control-D for normal startup):"
  57. );
  58. if (r < 0) {
  59. /* ^D, ^C, timeout, or read error */
  60. bb_error_msg("normal startup");
  61. return 0;
  62. }
  63. if (r > 0) {
  64. break;
  65. }
  66. bb_do_delay(LOGIN_FAIL_DELAY);
  67. bb_error_msg("Login incorrect");
  68. }
  69. bb_error_msg("starting shell for system maintenance");
  70. IF_SELINUX(renew_current_security_context());
  71. shell = getenv("SUSHELL");
  72. if (!shell)
  73. shell = getenv("sushell");
  74. if (!shell)
  75. shell = pwd->pw_shell;
  76. /* Exec login shell with no additional parameters. Never returns. */
  77. run_shell(shell, 1, NULL, NULL);
  78. }