blob: 2e32e2bbdff1fd9de04fc93a08c6c23196a6c364
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 | |
15 | //applet:IF_SULOGIN(APPLET(sulogin, BB_DIR_SBIN, BB_SUID_DROP)) |
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 | |
28 | int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
29 | int 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 malisious 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_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_error_msg("normal startup"); |
72 | return 0; |
73 | } |
74 | if (r > 0) { |
75 | break; |
76 | } |
77 | bb_do_delay(LOGIN_FAIL_DELAY); |
78 | bb_error_msg("Login incorrect"); |
79 | } |
80 | |
81 | bb_error_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 | run_shell(shell, 1, NULL); |
93 | } |
94 |