blob: 5638c4bc9fee907586f6cd224910f66ed0d87c4c [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 Vlasenko6ca409e2007-08-12 20:58:27 +000012static const char *const forbid[] = {
Eric Andersen27f64e12002-06-23 04:24:25 +000013 "ENV",
14 "BASH_ENV",
15 "HOME",
16 "IFS",
17 "PATH",
18 "SHELL",
19 "LD_LIBRARY_PATH",
20 "LD_PRELOAD",
21 "LD_TRACE_LOADED_OBJECTS",
22 "LD_BIND_NOW",
23 "LD_AOUT_LIBRARY_PATH",
24 "LD_AOUT_PRELOAD",
25 "LD_NOWARN",
26 "LD_KEEPDIR",
27 (char *) 0
28};
29
30
Bernhard Reutner-Fischer30385572006-01-31 17:57:48 +000031static void catchalarm(int ATTRIBUTE_UNUSED junk)
Eric Andersen27f64e12002-06-23 04:24:25 +000032{
33 exit(EXIT_FAILURE);
34}
35
36
Denis Vlasenko06af2162007-02-03 17:28:39 +000037int sulogin_main(int argc, char **argv);
Rob Landleydfba7412006-03-06 20:47:33 +000038int sulogin_main(int argc, char **argv)
Eric Andersen27f64e12002-06-23 04:24:25 +000039{
40 char *cp;
Eric Andersen27f64e12002-06-23 04:24:25 +000041 int timeout = 0;
Rob Landleydd93abe2006-09-08 17:22:05 +000042 char *timeout_arg;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000043 const char *const *p;
Rob Landleydd93abe2006-09-08 17:22:05 +000044 struct passwd *pwd;
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000045 const char *shell;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000046#if ENABLE_FEATURE_SHADOWPASSWDS
47 /* Using _r function to avoid pulling in static buffers */
48 char buffer[256];
49 struct spwd spw;
50 struct spwd *result;
51#endif
Eric Andersen27f64e12002-06-23 04:24:25 +000052
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000053 logmode = LOGMODE_BOTH;
Denis Vlasenko8f8f2682006-10-03 21:00:43 +000054 openlog(applet_name, 0, LOG_AUTH);
Rob Landleydd93abe2006-09-08 17:22:05 +000055
Denis Vlasenko13858992006-10-08 12:49:22 +000056 if (getopt32(argc, argv, "t:", &timeout_arg)) {
57 timeout = xatoi_u(timeout_arg);
Eric Andersen27f64e12002-06-23 04:24:25 +000058 }
Rob Landleydd93abe2006-09-08 17:22:05 +000059
60 if (argv[optind]) {
61 close(0);
62 close(1);
Rob Landleydd93abe2006-09-08 17:22:05 +000063 dup(xopen(argv[optind], O_RDWR));
Rob Landley69674942006-09-11 00:34:01 +000064 close(2);
Rob Landleydd93abe2006-09-08 17:22:05 +000065 dup(0);
66 }
67
Eric Andersen27f64e12002-06-23 04:24:25 +000068 if (!isatty(0) || !isatty(1) || !isatty(2)) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000069 logmode = LOGMODE_SYSLOG;
70 bb_error_msg_and_die("not a tty");
Denis Vlasenkoa9801652006-09-07 16:20:03 +000071 }
Eric Andersen27f64e12002-06-23 04:24:25 +000072
73 /* Clear out anything dangerous from the environment */
74 for (p = forbid; *p; p++)
75 unsetenv(*p);
76
Eric Andersen27f64e12002-06-23 04:24:25 +000077 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 Vlasenko5df955f2007-03-13 13:01:14 +000085 if (getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result)) {
86 goto auth_error;
Eric Andersen27f64e12002-06-23 04:24:25 +000087 }
Denis Vlasenko5df955f2007-03-13 13:01:14 +000088 pwd->pw_passwd = spw.sp_pwdp;
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000089#endif
Rob Landleydd93abe2006-09-08 17:22:05 +000090
Eric Andersen27f64e12002-06-23 04:24:25 +000091 while (1) {
Rob Landleydd93abe2006-09-08 17:22:05 +000092 /* cp points to a static buffer that is zeroed every time */
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000093 cp = bb_askpass(timeout,
94 "Give root password for system maintenance\n"
95 "(or type Control-D for normal startup):");
96
Eric Andersen27f64e12002-06-23 04:24:25 +000097 if (!cp || !*cp) {
Rob Landleydd93abe2006-09-08 17:22:05 +000098 bb_info_msg("Normal startup");
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000099 return 0;
Eric Andersen27f64e12002-06-23 04:24:25 +0000100 }
Rob Landleydd93abe2006-09-08 17:22:05 +0000101 if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
Eric Andersen27f64e12002-06-23 04:24:25 +0000102 break;
103 }
Rob Landley84cb7672006-01-06 20:59:09 +0000104 bb_do_delay(FAIL_DELAY);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000105 bb_error_msg("login incorrect");
Eric Andersen27f64e12002-06-23 04:24:25 +0000106 }
Rob Landleydd93abe2006-09-08 17:22:05 +0000107 memset(cp, 0, strlen(cp));
Eric Andersen27f64e12002-06-23 04:24:25 +0000108 signal(SIGALRM, SIG_DFL);
Rob Landley60158cb2005-05-03 06:25:50 +0000109
Rob Landleydd93abe2006-09-08 17:22:05 +0000110 bb_info_msg("System Maintenance Mode");
Rob Landley60158cb2005-05-03 06:25:50 +0000111
Rob Landleydd93abe2006-09-08 17:22:05 +0000112 USE_SELINUX(renew_current_security_context());
Rob Landley60158cb2005-05-03 06:25:50 +0000113
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +0000114 shell = getenv("SUSHELL");
115 if (!shell) shell = getenv("sushell");
116 if (!shell) {
117 shell = "/bin/sh";
118 if (pwd->pw_shell[0])
119 shell = pwd->pw_shell;
120 }
121 run_shell(shell, 1, 0, 0);
Rob Landleydd93abe2006-09-08 17:22:05 +0000122 /* never returns */
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000123
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000124auth_error:
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +0000125 bb_error_msg_and_die("no password entry for 'root'");
Eric Andersen27f64e12002-06-23 04:24:25 +0000126}