blob: 17bb15efae9d72dbd21d71665ff013560ea59cbb [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 *
"Robert P. J. Day"801ab142006-07-12 07:56:04 +00005 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
6 */
7
Denis Vlasenkob6adbf12007-05-26 19:00:18 +00008#include "libbb.h"
Bernhard Reutner-Fischerf4701962008-01-27 12:50:12 +00009#include <syslog.h>
Eric Andersen27f64e12002-06-23 04:24:25 +000010
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000011//static void catchalarm(int ATTRIBUTE_UNUSED junk)
12//{
13// exit(EXIT_FAILURE);
14//}
Eric Andersen27f64e12002-06-23 04:24:25 +000015
16
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000017int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko68404f12008-03-17 09:00:54 +000018int sulogin_main(int argc ATTRIBUTE_UNUSED, char **argv)
Eric Andersen27f64e12002-06-23 04:24:25 +000019{
20 char *cp;
Eric Andersen27f64e12002-06-23 04:24:25 +000021 int timeout = 0;
Rob Landleydd93abe2006-09-08 17:22:05 +000022 struct passwd *pwd;
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000023 const char *shell;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000024#if ENABLE_FEATURE_SHADOWPASSWDS
25 /* Using _r function to avoid pulling in static buffers */
26 char buffer[256];
27 struct spwd spw;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000028#endif
Eric Andersen27f64e12002-06-23 04:24:25 +000029
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000030 logmode = LOGMODE_BOTH;
Denis Vlasenko8f8f2682006-10-03 21:00:43 +000031 openlog(applet_name, 0, LOG_AUTH);
Rob Landleydd93abe2006-09-08 17:22:05 +000032
Denis Vlasenko1d426652008-03-17 09:09:09 +000033 opt_complementary = "t+"; /* -t N */
34 getopt32(argv, "t:", &timeout);
Rob Landleydd93abe2006-09-08 17:22:05 +000035
36 if (argv[optind]) {
37 close(0);
38 close(1);
Rob Landleydd93abe2006-09-08 17:22:05 +000039 dup(xopen(argv[optind], O_RDWR));
Rob Landley69674942006-09-11 00:34:01 +000040 close(2);
Rob Landleydd93abe2006-09-08 17:22:05 +000041 dup(0);
42 }
43
Denis Vlasenko1d426652008-03-17 09:09:09 +000044 /* Malicious use like "sulogin /dev/sda"? */
Eric Andersen27f64e12002-06-23 04:24:25 +000045 if (!isatty(0) || !isatty(1) || !isatty(2)) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000046 logmode = LOGMODE_SYSLOG;
47 bb_error_msg_and_die("not a tty");
Denis Vlasenkoa9801652006-09-07 16:20:03 +000048 }
Eric Andersen27f64e12002-06-23 04:24:25 +000049
Denis Vlasenko52816302007-11-06 05:26:51 +000050 /* Clear dangerous stuff, set PATH */
Denis Vlasenkoc9ca0a32008-02-18 11:08:33 +000051 sanitize_env_if_suid();
Eric Andersen27f64e12002-06-23 04:24:25 +000052
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000053// bb_askpass() already handles this
54// signal(SIGALRM, catchalarm);
Rob Landleydd93abe2006-09-08 17:22:05 +000055
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000056 pwd = getpwuid(0);
57 if (!pwd) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000058 goto auth_error;
Denis Vlasenko9213a9e2006-09-17 16:28:10 +000059 }
Rob Landleydd93abe2006-09-08 17:22:05 +000060
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000061#if ENABLE_FEATURE_SHADOWPASSWDS
Denis Vlasenko15ca51e2007-10-29 19:25:45 +000062 {
63 /* getspnam_r may return 0 yet set result to NULL.
64 * At least glibc 2.4 does this. Be extra paranoid here. */
65 struct spwd *result = NULL;
66 int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
67 if (r || !result) {
68 goto auth_error;
69 }
70 pwd->pw_passwd = result->sp_pwdp;
Eric Andersen27f64e12002-06-23 04:24:25 +000071 }
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000072#endif
Rob Landleydd93abe2006-09-08 17:22:05 +000073
Eric Andersen27f64e12002-06-23 04:24:25 +000074 while (1) {
Rob Landleydd93abe2006-09-08 17:22:05 +000075 /* cp points to a static buffer that is zeroed every time */
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000076 cp = bb_askpass(timeout,
77 "Give root password for system maintenance\n"
78 "(or type Control-D for normal startup):");
79
Eric Andersen27f64e12002-06-23 04:24:25 +000080 if (!cp || !*cp) {
Rob Landleydd93abe2006-09-08 17:22:05 +000081 bb_info_msg("Normal startup");
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000082 return 0;
Eric Andersen27f64e12002-06-23 04:24:25 +000083 }
Rob Landleydd93abe2006-09-08 17:22:05 +000084 if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
Eric Andersen27f64e12002-06-23 04:24:25 +000085 break;
86 }
Rob Landley84cb7672006-01-06 20:59:09 +000087 bb_do_delay(FAIL_DELAY);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000088 bb_error_msg("login incorrect");
Eric Andersen27f64e12002-06-23 04:24:25 +000089 }
Rob Landleydd93abe2006-09-08 17:22:05 +000090 memset(cp, 0, strlen(cp));
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000091// signal(SIGALRM, SIG_DFL);
Rob Landley60158cb2005-05-03 06:25:50 +000092
Rob Landleydd93abe2006-09-08 17:22:05 +000093 bb_info_msg("System Maintenance Mode");
Rob Landley60158cb2005-05-03 06:25:50 +000094
Rob Landleydd93abe2006-09-08 17:22:05 +000095 USE_SELINUX(renew_current_security_context());
Rob Landley60158cb2005-05-03 06:25:50 +000096
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000097 shell = getenv("SUSHELL");
Denis Vlasenkoa2f61012007-09-10 13:15:28 +000098 if (!shell)
99 shell = getenv("sushell");
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +0000100 if (!shell) {
101 shell = "/bin/sh";
102 if (pwd->pw_shell[0])
103 shell = pwd->pw_shell;
104 }
Denis Vlasenkoa2f61012007-09-10 13:15:28 +0000105 /* Exec login shell with no additional parameters. Never returns. */
106 run_shell(shell, 1, NULL, NULL);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000107
Denis Vlasenkoe5387a02007-10-20 19:20:22 +0000108 auth_error:
109 bb_error_msg_and_die("no password entry for root");
Eric Andersen27f64e12002-06-23 04:24:25 +0000110}