1 /* vi: set sw=4 ts=4: */
3 * Mini sulogin implementation for busybox
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 //usage:#define sulogin_trivial_usage
9 //usage: "[-t N] [TTY]"
10 //usage:#define sulogin_full_usage "\n\n"
11 //usage: "Single user login\n"
12 //usage: "\n -t N Timeout"
17 //static void catchalarm(int UNUSED_PARAM junk)
19 // exit(EXIT_FAILURE);
23 int sulogin_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
24 int sulogin_main(int argc UNUSED_PARAM
, char **argv
)
30 #if ENABLE_FEATURE_SHADOWPASSWDS
31 /* Using _r function to avoid pulling in static buffers */
36 logmode
= LOGMODE_BOTH
;
37 openlog(applet_name
, 0, LOG_AUTH
);
39 opt_complementary
= "t+"; /* -t N */
40 getopt32(argv
, "t:", &timeout
);
46 dup(xopen(argv
[0], O_RDWR
));
51 /* Malicious use like "sulogin /dev/sda"? */
52 if (!isatty(0) || !isatty(1) || !isatty(2)) {
53 logmode
= LOGMODE_SYSLOG
;
54 bb_error_msg_and_die("not a tty");
57 /* Clear dangerous stuff, set PATH */
58 sanitize_env_if_suid();
65 #if ENABLE_FEATURE_SHADOWPASSWDS
67 /* getspnam_r may return 0 yet set result to NULL.
68 * At least glibc 2.4 does this. Be extra paranoid here. */
69 struct spwd
*result
= NULL
;
70 int r
= getspnam_r(pwd
->pw_name
, &spw
, buffer
, sizeof(buffer
), &result
);
74 pwd
->pw_passwd
= result
->sp_pwdp
;
82 /* cp points to a static buffer that is zeroed every time */
83 cp
= bb_ask(STDIN_FILENO
, timeout
,
84 "Give root password for system maintenance\n"
85 "(or type Control-D for normal startup):");
88 bb_info_msg("Normal startup");
91 encrypted
= pw_encrypt(cp
, pwd
->pw_passwd
, 1);
92 r
= strcmp(encrypted
, pwd
->pw_passwd
);
97 bb_do_delay(LOGIN_FAIL_DELAY
);
98 bb_info_msg("Login incorrect");
100 memset(cp
, 0, strlen(cp
));
101 // signal(SIGALRM, SIG_DFL);
103 bb_info_msg("System Maintenance Mode");
105 IF_SELINUX(renew_current_security_context());
107 shell
= getenv("SUSHELL");
109 shell
= getenv("sushell");
111 shell
= pwd
->pw_shell
;
113 /* Exec login shell with no additional parameters. Never returns. */
114 run_shell(shell
, 1, NULL
, NULL
);
117 bb_error_msg_and_die("no password entry for root");