blob: f1545b78fab2be38426de2da502eb9e8c3d38fbe [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
Eric Andersen27f64e12002-06-23 04:24:25 +00008#include <syslog.h>
Eric Andersen27f64e12002-06-23 04:24:25 +00009
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000010#include "libbb.h"
Eric Andersen27f64e12002-06-23 04:24:25 +000011
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000012static const char forbid[] ALIGN1 =
13 "ENV" "\0"
14 "BASH_ENV" "\0"
15 "HOME" "\0"
16 "IFS" "\0"
17 "PATH" "\0"
18 "SHELL" "\0"
19 "LD_LIBRARY_PATH" "\0"
20 "LD_PRELOAD" "\0"
21 "LD_TRACE_LOADED_OBJECTS" "\0"
22 "LD_BIND_NOW" "\0"
23 "LD_AOUT_LIBRARY_PATH" "\0"
24 "LD_AOUT_PRELOAD" "\0"
25 "LD_NOWARN" "\0"
26 "LD_KEEPDIR" "\0";
Eric Andersen27f64e12002-06-23 04:24:25 +000027
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000028//static void catchalarm(int ATTRIBUTE_UNUSED junk)
29//{
30// exit(EXIT_FAILURE);
31//}
Eric Andersen27f64e12002-06-23 04:24:25 +000032
33
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000034int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Rob Landleydfba7412006-03-06 20:47:33 +000035int sulogin_main(int argc, char **argv)
Eric Andersen27f64e12002-06-23 04:24:25 +000036{
37 char *cp;
Eric Andersen27f64e12002-06-23 04:24:25 +000038 int timeout = 0;
Rob Landleydd93abe2006-09-08 17:22:05 +000039 char *timeout_arg;
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000040 const char *p;
Rob Landleydd93abe2006-09-08 17:22:05 +000041 struct passwd *pwd;
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000042 const char *shell;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000043#if ENABLE_FEATURE_SHADOWPASSWDS
44 /* Using _r function to avoid pulling in static buffers */
45 char buffer[256];
46 struct spwd spw;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000047#endif
Eric Andersen27f64e12002-06-23 04:24:25 +000048
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000049 logmode = LOGMODE_BOTH;
Denis Vlasenko8f8f2682006-10-03 21:00:43 +000050 openlog(applet_name, 0, LOG_AUTH);
Rob Landleydd93abe2006-09-08 17:22:05 +000051
Denis Vlasenkofe7cd642007-08-18 15:32:12 +000052 if (getopt32(argv, "t:", &timeout_arg)) {
Denis Vlasenko13858992006-10-08 12:49:22 +000053 timeout = xatoi_u(timeout_arg);
Eric Andersen27f64e12002-06-23 04:24:25 +000054 }
Rob Landleydd93abe2006-09-08 17:22:05 +000055
56 if (argv[optind]) {
57 close(0);
58 close(1);
Rob Landleydd93abe2006-09-08 17:22:05 +000059 dup(xopen(argv[optind], O_RDWR));
Rob Landley69674942006-09-11 00:34:01 +000060 close(2);
Rob Landleydd93abe2006-09-08 17:22:05 +000061 dup(0);
62 }
63
Eric Andersen27f64e12002-06-23 04:24:25 +000064 if (!isatty(0) || !isatty(1) || !isatty(2)) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000065 logmode = LOGMODE_SYSLOG;
66 bb_error_msg_and_die("not a tty");
Denis Vlasenkoa9801652006-09-07 16:20:03 +000067 }
Eric Andersen27f64e12002-06-23 04:24:25 +000068
69 /* Clear out anything dangerous from the environment */
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000070 p = forbid;
71 do {
72 unsetenv(p);
73 p += strlen(p) + 1;
74 } while (*p);
Eric Andersen27f64e12002-06-23 04:24:25 +000075
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000076// bb_askpass() already handles this
77// signal(SIGALRM, catchalarm);
Rob Landleydd93abe2006-09-08 17:22:05 +000078
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000079 pwd = getpwuid(0);
80 if (!pwd) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000081 goto auth_error;
Denis Vlasenko9213a9e2006-09-17 16:28:10 +000082 }
Rob Landleydd93abe2006-09-08 17:22:05 +000083
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000084#if ENABLE_FEATURE_SHADOWPASSWDS
Denis Vlasenko15ca51e2007-10-29 19:25:45 +000085 {
86 /* getspnam_r may return 0 yet set result to NULL.
87 * At least glibc 2.4 does this. Be extra paranoid here. */
88 struct spwd *result = NULL;
89 int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
90 if (r || !result) {
91 goto auth_error;
92 }
93 pwd->pw_passwd = result->sp_pwdp;
Eric Andersen27f64e12002-06-23 04:24:25 +000094 }
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000095#endif
Rob Landleydd93abe2006-09-08 17:22:05 +000096
Eric Andersen27f64e12002-06-23 04:24:25 +000097 while (1) {
Rob Landleydd93abe2006-09-08 17:22:05 +000098 /* cp points to a static buffer that is zeroed every time */
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000099 cp = bb_askpass(timeout,
100 "Give root password for system maintenance\n"
101 "(or type Control-D for normal startup):");
102
Eric Andersen27f64e12002-06-23 04:24:25 +0000103 if (!cp || !*cp) {
Rob Landleydd93abe2006-09-08 17:22:05 +0000104 bb_info_msg("Normal startup");
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000105 return 0;
Eric Andersen27f64e12002-06-23 04:24:25 +0000106 }
Rob Landleydd93abe2006-09-08 17:22:05 +0000107 if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
Eric Andersen27f64e12002-06-23 04:24:25 +0000108 break;
109 }
Rob Landley84cb7672006-01-06 20:59:09 +0000110 bb_do_delay(FAIL_DELAY);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000111 bb_error_msg("login incorrect");
Eric Andersen27f64e12002-06-23 04:24:25 +0000112 }
Rob Landleydd93abe2006-09-08 17:22:05 +0000113 memset(cp, 0, strlen(cp));
Denis Vlasenkoe5387a02007-10-20 19:20:22 +0000114// signal(SIGALRM, SIG_DFL);
Rob Landley60158cb2005-05-03 06:25:50 +0000115
Rob Landleydd93abe2006-09-08 17:22:05 +0000116 bb_info_msg("System Maintenance Mode");
Rob Landley60158cb2005-05-03 06:25:50 +0000117
Rob Landleydd93abe2006-09-08 17:22:05 +0000118 USE_SELINUX(renew_current_security_context());
Rob Landley60158cb2005-05-03 06:25:50 +0000119
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +0000120 shell = getenv("SUSHELL");
Denis Vlasenkoa2f61012007-09-10 13:15:28 +0000121 if (!shell)
122 shell = getenv("sushell");
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +0000123 if (!shell) {
124 shell = "/bin/sh";
125 if (pwd->pw_shell[0])
126 shell = pwd->pw_shell;
127 }
Denis Vlasenkoa2f61012007-09-10 13:15:28 +0000128 /* Exec login shell with no additional parameters. Never returns. */
129 run_shell(shell, 1, NULL, NULL);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000130
Denis Vlasenkoe5387a02007-10-20 19:20:22 +0000131 auth_error:
132 bb_error_msg_and_die("no password entry for root");
Eric Andersen27f64e12002-06-23 04:24:25 +0000133}