- update defconfig
[oweals/busybox.git] / loginutils / sulogin.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini sulogin implementation for busybox
4  *
5  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
6  */
7
8 #include <syslog.h>
9
10 #include "libbb.h"
11
12 //static void catchalarm(int ATTRIBUTE_UNUSED junk)
13 //{
14 //      exit(EXIT_FAILURE);
15 //}
16
17
18 int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
19 int sulogin_main(int argc, char **argv)
20 {
21         char *cp;
22         int timeout = 0;
23         char *timeout_arg;
24         struct passwd *pwd;
25         const char *shell;
26 #if ENABLE_FEATURE_SHADOWPASSWDS
27         /* Using _r function to avoid pulling in static buffers */
28         char buffer[256];
29         struct spwd spw;
30 #endif
31
32         logmode = LOGMODE_BOTH;
33         openlog(applet_name, 0, LOG_AUTH);
34
35         if (getopt32(argv, "t:", &timeout_arg)) {
36                 timeout = xatoi_u(timeout_arg);
37         }
38
39         if (argv[optind]) {
40                 close(0);
41                 close(1);
42                 dup(xopen(argv[optind], O_RDWR));
43                 close(2);
44                 dup(0);
45         }
46
47         if (!isatty(0) || !isatty(1) || !isatty(2)) {
48                 logmode = LOGMODE_SYSLOG;
49                 bb_error_msg_and_die("not a tty");
50         }
51
52         /* Clear dangerous stuff, set PATH */
53         sanitize_env_for_suid();
54
55 // bb_askpass() already handles this
56 //      signal(SIGALRM, catchalarm);
57
58         pwd = getpwuid(0);
59         if (!pwd) {
60                 goto auth_error;
61         }
62
63 #if ENABLE_FEATURE_SHADOWPASSWDS
64         {
65                 /* getspnam_r may return 0 yet set result to NULL.
66                  * At least glibc 2.4 does this. Be extra paranoid here. */
67                 struct spwd *result = NULL;
68                 int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
69                 if (r || !result) {
70                         goto auth_error;
71                 }
72                 pwd->pw_passwd = result->sp_pwdp;
73         }
74 #endif
75
76         while (1) {
77                 /* cp points to a static buffer that is zeroed every time */
78                 cp = bb_askpass(timeout,
79                                 "Give root password for system maintenance\n"
80                                 "(or type Control-D for normal startup):");
81
82                 if (!cp || !*cp) {
83                         bb_info_msg("Normal startup");
84                         return 0;
85                 }
86                 if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
87                         break;
88                 }
89                 bb_do_delay(FAIL_DELAY);
90                 bb_error_msg("login incorrect");
91         }
92         memset(cp, 0, strlen(cp));
93 //      signal(SIGALRM, SIG_DFL);
94
95         bb_info_msg("System Maintenance Mode");
96
97         USE_SELINUX(renew_current_security_context());
98
99         shell = getenv("SUSHELL");
100         if (!shell)
101                 shell = getenv("sushell");
102         if (!shell) {
103                 shell = "/bin/sh";
104                 if (pwd->pw_shell[0])
105                         shell = pwd->pw_shell;
106         }
107         /* Exec login shell with no additional parameters. Never returns. */
108         run_shell(shell, 1, NULL, NULL);
109
110  auth_error:
111         bb_error_msg_and_die("no password entry for root");
112 }