Shrinkage/cleanup from Tito.
[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 "busybox.h"
11
12
13 #define SULOGIN_PROMPT "Give root password for system maintenance\n" \
14         "(or type Control-D for normal startup):"
15
16 static const char * const forbid[] = {
17         "ENV",
18         "BASH_ENV",
19         "HOME",
20         "IFS",
21         "PATH",
22         "SHELL",
23         "LD_LIBRARY_PATH",
24         "LD_PRELOAD",
25         "LD_TRACE_LOADED_OBJECTS",
26         "LD_BIND_NOW",
27         "LD_AOUT_LIBRARY_PATH",
28         "LD_AOUT_PRELOAD",
29         "LD_NOWARN",
30         "LD_KEEPDIR",
31         (char *) 0
32 };
33
34
35
36 static void catchalarm(int ATTRIBUTE_UNUSED junk)
37 {
38         exit(EXIT_FAILURE);
39 }
40
41
42 int sulogin_main(int argc, char **argv)
43 {
44         char *cp;
45         int timeout = 0;
46         char *timeout_arg;
47         const char * const *p;
48         struct passwd *pwd;
49         struct spwd *spwd;
50
51         if (ENABLE_FEATURE_SYSLOG) {
52                 logmode = LOGMODE_BOTH;
53                 openlog(bb_applet_name, LOG_CONS | LOG_NOWAIT, LOG_AUTH);
54         }
55
56         if (bb_getopt_ulflags (argc, argv, "t:", &timeout_arg)) {
57                 if (safe_strtoi(timeout_arg, &timeout)) {
58                         timeout = 0;
59                 }
60         }
61
62         if (argv[optind]) {
63                 close(0);
64                 close(1);
65                 close(2);
66                 dup(xopen(argv[optind], O_RDWR));
67                 dup(0);
68         }
69
70         if (!isatty(0) || !isatty(1) || !isatty(2)) {
71                 bb_error_msg_and_die("Not a tty");
72         }
73
74         /* Clear out anything dangerous from the environment */
75         for (p = forbid; *p; p++)
76                 unsetenv(*p);
77
78         signal(SIGALRM, catchalarm);
79
80         if (!(pwd = getpwuid(0))) {
81                 goto AUTH_ERROR;
82         } 
83
84         if (ENABLE_FEATURE_SHADOWPASSWDS) {
85                 if (!(spwd = getspnam(pwd->pw_name))) {
86                         goto AUTH_ERROR;
87                 }
88                 pwd->pw_passwd = spwd->sp_pwdp;
89         }
90
91         while (1) {
92                 /* cp points to a static buffer that is zeroed every time */
93                 cp = bb_askpass(timeout, SULOGIN_PROMPT);
94                 if (!cp || !*cp) {
95                         bb_info_msg("Normal startup");
96                         exit(EXIT_SUCCESS);
97                 }
98                 if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
99                         break;
100                 }
101                 bb_do_delay(FAIL_DELAY);
102                 bb_error_msg("Login incorrect");
103         }
104         memset(cp, 0, strlen(cp));
105         signal(SIGALRM, SIG_DFL);
106
107         bb_info_msg("System Maintenance Mode");
108
109         USE_SELINUX(renew_current_security_context());
110
111         run_shell(pwd->pw_shell, 1, 0, 0);
112         /* never returns */
113 AUTH_ERROR:     
114         bb_error_msg_and_die("No password entry for `root'");
115 }