blob: caa1a83351a8f2e01005db4cad8079d362c927b4 [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 char *timeout_arg;
Rob Landleydd93abe2006-09-08 17:22:05 +000023 struct passwd *pwd;
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000024 const char *shell;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000025#if ENABLE_FEATURE_SHADOWPASSWDS
26 /* Using _r function to avoid pulling in static buffers */
27 char buffer[256];
28 struct spwd spw;
Denis Vlasenko5df955f2007-03-13 13:01:14 +000029#endif
Eric Andersen27f64e12002-06-23 04:24:25 +000030
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000031 logmode = LOGMODE_BOTH;
Denis Vlasenko8f8f2682006-10-03 21:00:43 +000032 openlog(applet_name, 0, LOG_AUTH);
Rob Landleydd93abe2006-09-08 17:22:05 +000033
Denis Vlasenkofe7cd642007-08-18 15:32:12 +000034 if (getopt32(argv, "t:", &timeout_arg)) {
Denis Vlasenko13858992006-10-08 12:49:22 +000035 timeout = xatoi_u(timeout_arg);
Eric Andersen27f64e12002-06-23 04:24:25 +000036 }
Rob Landleydd93abe2006-09-08 17:22:05 +000037
38 if (argv[optind]) {
39 close(0);
40 close(1);
Rob Landleydd93abe2006-09-08 17:22:05 +000041 dup(xopen(argv[optind], O_RDWR));
Rob Landley69674942006-09-11 00:34:01 +000042 close(2);
Rob Landleydd93abe2006-09-08 17:22:05 +000043 dup(0);
44 }
45
Eric Andersen27f64e12002-06-23 04:24:25 +000046 if (!isatty(0) || !isatty(1) || !isatty(2)) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000047 logmode = LOGMODE_SYSLOG;
48 bb_error_msg_and_die("not a tty");
Denis Vlasenkoa9801652006-09-07 16:20:03 +000049 }
Eric Andersen27f64e12002-06-23 04:24:25 +000050
Denis Vlasenko52816302007-11-06 05:26:51 +000051 /* Clear dangerous stuff, set PATH */
Denis Vlasenkoc9ca0a32008-02-18 11:08:33 +000052 sanitize_env_if_suid();
Eric Andersen27f64e12002-06-23 04:24:25 +000053
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000054// bb_askpass() already handles this
55// signal(SIGALRM, catchalarm);
Rob Landleydd93abe2006-09-08 17:22:05 +000056
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000057 pwd = getpwuid(0);
58 if (!pwd) {
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000059 goto auth_error;
Denis Vlasenko9213a9e2006-09-17 16:28:10 +000060 }
Rob Landleydd93abe2006-09-08 17:22:05 +000061
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000062#if ENABLE_FEATURE_SHADOWPASSWDS
Denis Vlasenko15ca51e2007-10-29 19:25:45 +000063 {
64 /* getspnam_r may return 0 yet set result to NULL.
65 * At least glibc 2.4 does this. Be extra paranoid here. */
66 struct spwd *result = NULL;
67 int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
68 if (r || !result) {
69 goto auth_error;
70 }
71 pwd->pw_passwd = result->sp_pwdp;
Eric Andersen27f64e12002-06-23 04:24:25 +000072 }
Denis Vlasenkob5a122b2006-12-30 14:46:51 +000073#endif
Rob Landleydd93abe2006-09-08 17:22:05 +000074
Eric Andersen27f64e12002-06-23 04:24:25 +000075 while (1) {
Rob Landleydd93abe2006-09-08 17:22:05 +000076 /* cp points to a static buffer that is zeroed every time */
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000077 cp = bb_askpass(timeout,
78 "Give root password for system maintenance\n"
79 "(or type Control-D for normal startup):");
80
Eric Andersen27f64e12002-06-23 04:24:25 +000081 if (!cp || !*cp) {
Rob Landleydd93abe2006-09-08 17:22:05 +000082 bb_info_msg("Normal startup");
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000083 return 0;
Eric Andersen27f64e12002-06-23 04:24:25 +000084 }
Rob Landleydd93abe2006-09-08 17:22:05 +000085 if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
Eric Andersen27f64e12002-06-23 04:24:25 +000086 break;
87 }
Rob Landley84cb7672006-01-06 20:59:09 +000088 bb_do_delay(FAIL_DELAY);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +000089 bb_error_msg("login incorrect");
Eric Andersen27f64e12002-06-23 04:24:25 +000090 }
Rob Landleydd93abe2006-09-08 17:22:05 +000091 memset(cp, 0, strlen(cp));
Denis Vlasenkoe5387a02007-10-20 19:20:22 +000092// signal(SIGALRM, SIG_DFL);
Rob Landley60158cb2005-05-03 06:25:50 +000093
Rob Landleydd93abe2006-09-08 17:22:05 +000094 bb_info_msg("System Maintenance Mode");
Rob Landley60158cb2005-05-03 06:25:50 +000095
Rob Landleydd93abe2006-09-08 17:22:05 +000096 USE_SELINUX(renew_current_security_context());
Rob Landley60158cb2005-05-03 06:25:50 +000097
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +000098 shell = getenv("SUSHELL");
Denis Vlasenkoa2f61012007-09-10 13:15:28 +000099 if (!shell)
100 shell = getenv("sushell");
Denis Vlasenkoc345d8e2006-10-14 11:47:02 +0000101 if (!shell) {
102 shell = "/bin/sh";
103 if (pwd->pw_shell[0])
104 shell = pwd->pw_shell;
105 }
Denis Vlasenkoa2f61012007-09-10 13:15:28 +0000106 /* Exec login shell with no additional parameters. Never returns. */
107 run_shell(shell, 1, NULL, NULL);
Denis Vlasenko9852d5a2006-09-09 14:00:58 +0000108
Denis Vlasenkoe5387a02007-10-20 19:20:22 +0000109 auth_error:
110 bb_error_msg_and_die("no password entry for root");
Eric Andersen27f64e12002-06-23 04:24:25 +0000111}