blob: c8e5fc9a00544f897cadea30d3b13578ac464e77 [file] [log] [blame]
Eric Andersen27f64e12002-06-23 04:24:25 +00001/* vi: set sw=4 ts=4: */
"Robert P. J. Day"801ab142006-07-12 07:56:04 +00002/*
Rob Landleydd93abe2006-09-08 17:22:05 +00003 * Mini sulogin implementation for busybox
4 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02005 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
"Robert P. J. Day"801ab142006-07-12 07:56:04 +00006 */
7
Pere Orga6a3e01d2011-04-01 22:56:30 +02008//usage:#define sulogin_trivial_usage
9//usage: "[-t N] [TTY]"
10//usage:#define sulogin_full_usage "\n\n"
11//usage: "Single user login\n"
Pere Orga6a3e01d2011-04-01 22:56:30 +020012//usage: "\n -t N Timeout"
13
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000014#include "libbb.h"
Bernhard Reutner-Fischerf4701962008-01-27 12:50:12 +000015#include <syslog.h>
Eric Andersen27f64e12002-06-23 04:24:25 +000016
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000017int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000018int sulogin_main(int argc UNUSED_PARAM, char **argv)
Eric Andersen27f64e12002-06-23 04:24:25 +000019{
Eric Andersen27f64e12002-06-23 04:24:25 +000020 int timeout = 0;
Rob Landleydd93abe2006-09-08 17:22:05 +000021 struct passwd *pwd;
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000022 const char *shell;
Eric Andersen27f64e12002-06-23 04:24:25 +000023
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000024 logmode = LOGMODE_BOTH;
Denis Vlasenko8f8f2682006-10-03 21:00:43 +000025 openlog(applet_name, 0, LOG_AUTH);
Rob Landleydd93abe2006-09-08 17:22:05 +000026
Denis Vlasenko1d426652008-03-17 09:09:09 +000027 opt_complementary = "t+"; /* -t N */
28 getopt32(argv, "t:", &timeout);
Denis Vlasenko3fa36e22008-11-09 00:15:11 +000029 argv += optind;
Rob Landleydd93abe2006-09-08 17:22:05 +000030
Denis Vlasenko3fa36e22008-11-09 00:15:11 +000031 if (argv[0]) {
Rob Landleydd93abe2006-09-08 17:22:05 +000032 close(0);
33 close(1);
Denis Vlasenko3fa36e22008-11-09 00:15:11 +000034 dup(xopen(argv[0], O_RDWR));
Rob Landley69674942006-09-11 00:34:01 +000035 close(2);
Rob Landleydd93abe2006-09-08 17:22:05 +000036 dup(0);
37 }
38
Denis Vlasenko1d426652008-03-17 09:09:09 +000039 /* Malicious use like "sulogin /dev/sda"? */
Eric Andersen27f64e12002-06-23 04:24:25 +000040 if (!isatty(0) || !isatty(1) || !isatty(2)) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000041 logmode = LOGMODE_SYSLOG;
42 bb_error_msg_and_die("not a tty");
Denis Vlasenkoa9801652006-09-07 16:20:03 +000043 }
Eric Andersen27f64e12002-06-23 04:24:25 +000044
Denis Vlasenko52816302007-11-06 05:26:51 +000045 /* Clear dangerous stuff, set PATH */
Denis Vlasenkoc9ca0a32008-02-18 11:08:33 +000046 sanitize_env_if_suid();
Eric Andersen27f64e12002-06-23 04:24:25 +000047
maxwen27116ba2015-08-14 21:41:28 +020048 pwd = safegetpwuid(0);
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000049 if (!pwd) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000050 goto auth_error;
Denis Vlasenko9213a9e2006-09-17 16:28:10 +000051 }
Rob Landleydd93abe2006-09-08 17:22:05 +000052
Eric Andersen27f64e12002-06-23 04:24:25 +000053 while (1) {
Denis Vlasenkofdddab02008-06-12 16:56:52 +000054 int r;
55
maxwen27116ba2015-08-14 21:41:28 +020056 r = ask_and_check_password_extended(pwd, timeout,
57 "Give root password for system maintenance\n"
58 "(or type Control-D for normal startup):"
59 );
60 if (r < 0) {
61 /* ^D, ^C, timeout, or read error */
Rob Landleydd93abe2006-09-08 17:22:05 +000062 bb_info_msg("Normal startup");
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000063 return 0;
Eric Andersen27f64e12002-06-23 04:24:25 +000064 }
maxwen27116ba2015-08-14 21:41:28 +020065 if (r > 0) {
Eric Andersen27f64e12002-06-23 04:24:25 +000066 break;
67 }
Denys Vlasenko7d4e7a22011-03-08 21:07:05 +010068 bb_do_delay(LOGIN_FAIL_DELAY);
69 bb_info_msg("Login incorrect");
Eric Andersen27f64e12002-06-23 04:24:25 +000070 }
Rob Landley60158cb2005-05-03 06:25:50 +000071
Rob Landleydd93abe2006-09-08 17:22:05 +000072 bb_info_msg("System Maintenance Mode");
Rob Landley60158cb2005-05-03 06:25:50 +000073
Denis Vlasenko5e34ff22009-04-21 11:09:40 +000074 IF_SELINUX(renew_current_security_context());
Rob Landley60158cb2005-05-03 06:25:50 +000075
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000076 shell = getenv("SUSHELL");
Denis Vlasenkoa2f61012007-09-10 13:15:28 +000077 if (!shell)
78 shell = getenv("sushell");
Ladislav Michla73b87e2010-06-27 03:23:31 +020079 if (!shell)
80 shell = pwd->pw_shell;
81
Denis Vlasenkoa2f61012007-09-10 13:15:28 +000082 /* Exec login shell with no additional parameters. Never returns. */
83 run_shell(shell, 1, NULL, NULL);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000084
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000085 auth_error:
86 bb_error_msg_and_die("no password entry for root");
Eric Andersen27f64e12002-06-23 04:24:25 +000087}