busybox/loginutils/sulogin.c
<<
>>
Prefs
   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 (17 kb)"
   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
  15//applet:IF_SULOGIN(APPLET_NOEXEC(sulogin, sulogin, BB_DIR_SBIN, BB_SUID_DROP, sulogin))
  16
  17//kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
  18
  19//usage:#define sulogin_trivial_usage
  20//usage:       "[-t N] [TTY]"
  21//usage:#define sulogin_full_usage "\n\n"
  22//usage:       "Single user login\n"
  23//usage:     "\n        -t N    Timeout"
  24
  25#include "libbb.h"
  26#include <syslog.h>
  27
  28int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  29int sulogin_main(int argc UNUSED_PARAM, char **argv)
  30{
  31        int timeout = 0;
  32        struct passwd *pwd;
  33        const char *shell;
  34
  35        /* Note: sulogin is not a suid app. It is meant to be run by init
  36         * for single user / emergency mode. init starts it as root.
  37         * Normal users (potentially malicious ones) can only run it under
  38         * their UID, therefore no paranoia here is warranted:
  39         * $LD_LIBRARY_PATH in env, TTY = /dev/sda
  40         * are no more dangerous here than in e.g. cp applet.
  41         */
  42
  43        logmode = LOGMODE_BOTH;
  44        openlog(applet_name, 0, LOG_AUTH);
  45
  46        getopt32(argv, "t:+", &timeout);
  47        argv += optind;
  48
  49        if (argv[0]) {
  50                close(0);
  51                close(1);
  52                dup(xopen(argv[0], O_RDWR));
  53                close(2);
  54                dup(0);
  55        }
  56
  57        pwd = getpwuid(0);
  58        if (!pwd) {
  59                bb_simple_error_msg_and_die("no password entry for root");
  60        }
  61
  62        while (1) {
  63                int r;
  64
  65                r = ask_and_check_password_extended(pwd, timeout,
  66                        "Give root password for system maintenance\n"
  67                        "(or type Control-D for normal startup):"
  68                );
  69                if (r < 0) {
  70                        /* ^D, ^C, timeout, or read error */
  71                        bb_simple_info_msg("normal startup");
  72                        return 0;
  73                }
  74                if (r > 0) {
  75                        break;
  76                }
  77                pause_after_failed_login();
  78                bb_simple_info_msg("Login incorrect");
  79        }
  80
  81        bb_simple_info_msg("starting shell for system maintenance");
  82
  83        IF_SELINUX(renew_current_security_context());
  84
  85        shell = getenv("SUSHELL");
  86        if (!shell)
  87                shell = getenv("sushell");
  88        if (!shell)
  89                shell = pwd->pw_shell;
  90
  91        /* Exec login shell with no additional parameters. Never returns. */
  92        exec_login_shell(shell);
  93}
  94