blob: a654ffb8932fd6963b82b5f8538f7592cdcdf374 [file] [log] [blame]
Eric Andersen27f64e12002-06-23 04:24:25 +00001/* vi: set sw=4 ts=4: */
2#include <fcntl.h>
3#include <signal.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <syslog.h>
8#include <termios.h>
9#include <unistd.h>
10#include <utmp.h>
11#include <sys/resource.h>
12#include <sys/stat.h>
13#include <sys/time.h>
14#include <sys/types.h>
15#include <ctype.h>
16#include <time.h>
17
18#include "busybox.h"
19
20
21// sulogin defines
22#define SULOGIN_PROMPT "\nGive root password for system maintenance\n" \
23 "(or type Control-D for normal startup):"
24
25static const char *forbid[] = {
26 "ENV",
27 "BASH_ENV",
28 "HOME",
29 "IFS",
30 "PATH",
31 "SHELL",
32 "LD_LIBRARY_PATH",
33 "LD_PRELOAD",
34 "LD_TRACE_LOADED_OBJECTS",
35 "LD_BIND_NOW",
36 "LD_AOUT_LIBRARY_PATH",
37 "LD_AOUT_PRELOAD",
38 "LD_NOWARN",
39 "LD_KEEPDIR",
40 (char *) 0
41};
42
43
44
45static void catchalarm(int junk)
46{
47 exit(EXIT_FAILURE);
48}
49
50
51extern int sulogin_main(int argc, char **argv)
52{
53 char *cp;
54 char *device = (char *) 0;
55 const char *name = "root";
56 int timeout = 0;
57 static char pass[BUFSIZ];
58 struct termios termio;
59 struct passwd pwent;
60 struct passwd *pwd;
61 time_t start, now;
62 const char **p;
63#ifdef CONFIG_FEATURE_SHADOWPASSWDS
64 struct spwd *spwd = NULL;
65#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
66
67 tcgetattr(0, &termio);
68 /* set control chars */
69 termio.c_cc[VINTR] = 3; /* C-c */
70 termio.c_cc[VQUIT] = 28; /* C-\ */
71 termio.c_cc[VERASE] = 127; /* C-? */
72 termio.c_cc[VKILL] = 21; /* C-u */
73 termio.c_cc[VEOF] = 4; /* C-d */
74 termio.c_cc[VSTART] = 17; /* C-q */
75 termio.c_cc[VSTOP] = 19; /* C-s */
76 termio.c_cc[VSUSP] = 26; /* C-z */
77 /* use line dicipline 0 */
78 termio.c_line = 0;
79 /* Make it be sane */
80 termio.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
81 termio.c_cflag |= CREAD|HUPCL|CLOCAL;
82 /* input modes */
83 termio.c_iflag = ICRNL | IXON | IXOFF;
84 /* output modes */
85 termio.c_oflag = OPOST | ONLCR;
86 /* local modes */
87 termio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
88 tcsetattr(0, TCSANOW, &termio);
89 openlog("sulogin", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
90 if (argc > 1) {
91 if (strncmp(argv[1], "-t", 2) == 0) {
92 if (strcmp(argv[1], "-t") == 0) {
93 if (argc > 2) {
94 timeout = atoi(argv[2]);
95 if (argc > 3) {
96 device = argv[3];
97 }
98 }
99 } else {
100 if (argc > 2) {
101 device = argv[2];
102 }
103 }
104 } else {
105 device = argv[1];
106 }
107 if (device) {
108 close(0);
109 close(1);
110 close(2);
111 if (open(device, O_RDWR) >= 0) {
112 dup(0);
113 dup(0);
114 } else {
115 syslog(LOG_WARNING, "cannot open %s\n", device);
116 exit(EXIT_FAILURE);
117 }
118 }
119 }
120 if (access(passwd_file, 0) == -1) {
121 syslog(LOG_WARNING, "No password file\n");
122 error_msg_and_die("No password file\n");
123 }
124 if (!isatty(0) || !isatty(1) || !isatty(2)) {
125 exit(EXIT_FAILURE);
126 }
127
128
129 /* Clear out anything dangerous from the environment */
130 for (p = forbid; *p; p++)
131 unsetenv(*p);
132
133
134 signal(SIGALRM, catchalarm);
135 alarm(timeout);
136 if (!(pwd = getpwnam(name))) {
137 syslog(LOG_WARNING, "No password entry for `root'\n");
138 error_msg_and_die("No password entry for `root'\n");
139 }
140 pwent = *pwd;
141#ifdef CONFIG_FEATURE_SHADOWPASSWDS
142 spwd = NULL;
143 if (pwd && ((strcmp(pwd->pw_passwd, "x") == 0)
144 || (strcmp(pwd->pw_passwd, "*") == 0))) {
145 endspent();
146 spwd = getspnam(name);
147 if (spwd) {
148 pwent.pw_passwd = spwd->sp_pwdp;
149 }
150 }
151#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
152 while (1) {
153 cp = getpass(SULOGIN_PROMPT);
154 if (!cp || !*cp) {
155 puts("\n");
156 fflush(stdout);
157 syslog(LOG_INFO, "Normal startup\n");
158 exit(EXIT_SUCCESS);
159 } else {
160 safe_strncpy(pass, cp, sizeof(pass));
161 bzero(cp, strlen(cp));
162 }
163 if (strcmp(pw_encrypt(pass, pwent.pw_passwd), pwent.pw_passwd) == 0) {
164 break;
165 }
166 time(&start);
167 now = start;
168 while (difftime(now, start) < FAIL_DELAY) {
169 sleep(FAIL_DELAY);
170 time(&now);
171 }
172 puts("Login incorrect");
173 fflush(stdout);
174 syslog(LOG_WARNING, "Incorrect root password\n");
175 }
176 bzero(pass, strlen(pass));
177 alarm(0);
178 signal(SIGALRM, SIG_DFL);
179 puts("Entering System Maintenance Mode\n");
180 fflush(stdout);
181 syslog(LOG_INFO, "System Maintenance Mode\n");
182 run_shell(pwent.pw_shell, 1, 0, 0);
183 return (0);
184}