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