137 |
puts("\r\nSystem closed for routine maintenance\r"); |
puts("\r\nSystem closed for routine maintenance\r"); |
138 |
|
|
139 |
fclose(fp); |
fclose(fp); |
140 |
fflush(NULL); |
fflush_all(); |
141 |
/* Users say that they do need this prior to exit: */ |
/* Users say that they do need this prior to exit: */ |
142 |
tcdrain(STDOUT_FILENO); |
tcdrain(STDOUT_FILENO); |
143 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
165 |
static ALWAYS_INLINE int check_securetty(void) { return 1; } |
static ALWAYS_INLINE int check_securetty(void) { return 1; } |
166 |
#endif |
#endif |
167 |
|
|
168 |
|
#if ENABLE_SELINUX |
169 |
|
static void initselinux(char *username, char *full_tty, |
170 |
|
security_context_t *user_sid) |
171 |
|
{ |
172 |
|
security_context_t old_tty_sid, new_tty_sid; |
173 |
|
|
174 |
|
if (!is_selinux_enabled()) |
175 |
|
return; |
176 |
|
|
177 |
|
if (get_default_context(username, NULL, user_sid)) { |
178 |
|
bb_error_msg_and_die("can't get SID for %s", username); |
179 |
|
} |
180 |
|
if (getfilecon(full_tty, &old_tty_sid) < 0) { |
181 |
|
bb_perror_msg_and_die("getfilecon(%s) failed", full_tty); |
182 |
|
} |
183 |
|
if (security_compute_relabel(*user_sid, old_tty_sid, |
184 |
|
SECCLASS_CHR_FILE, &new_tty_sid) != 0) { |
185 |
|
bb_perror_msg_and_die("security_change_sid(%s) failed", full_tty); |
186 |
|
} |
187 |
|
if (setfilecon(full_tty, new_tty_sid) != 0) { |
188 |
|
bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid); |
189 |
|
} |
190 |
|
} |
191 |
|
#endif |
192 |
|
|
193 |
|
#if ENABLE_LOGIN_SCRIPTS |
194 |
|
static void run_login_script(struct passwd *pw, char *full_tty) |
195 |
|
{ |
196 |
|
char *t_argv[2]; |
197 |
|
|
198 |
|
t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT"); |
199 |
|
if (t_argv[0]) { |
200 |
|
t_argv[1] = NULL; |
201 |
|
xsetenv("LOGIN_TTY", full_tty); |
202 |
|
xsetenv("LOGIN_USER", pw->pw_name); |
203 |
|
xsetenv("LOGIN_UID", utoa(pw->pw_uid)); |
204 |
|
xsetenv("LOGIN_GID", utoa(pw->pw_gid)); |
205 |
|
xsetenv("LOGIN_SHELL", pw->pw_shell); |
206 |
|
spawn_and_wait(t_argv); /* NOMMU-friendly */ |
207 |
|
unsetenv("LOGIN_TTY"); |
208 |
|
unsetenv("LOGIN_USER"); |
209 |
|
unsetenv("LOGIN_UID"); |
210 |
|
unsetenv("LOGIN_GID"); |
211 |
|
unsetenv("LOGIN_SHELL"); |
212 |
|
} |
213 |
|
} |
214 |
|
#else |
215 |
|
void run_login_script(struct passwd *pw, char *full_tty); |
216 |
|
#endif |
217 |
|
|
218 |
static void get_username_or_die(char *buf, int size_buf) |
static void get_username_or_die(char *buf, int size_buf) |
219 |
{ |
{ |
220 |
int c, cntdown; |
int c, cntdown; |
225 |
/* skip whitespace */ |
/* skip whitespace */ |
226 |
do { |
do { |
227 |
c = getchar(); |
c = getchar(); |
228 |
if (c == EOF) exit(EXIT_FAILURE); |
if (c == EOF) |
229 |
|
exit(EXIT_FAILURE); |
230 |
if (c == '\n') { |
if (c == '\n') { |
231 |
if (!--cntdown) exit(EXIT_FAILURE); |
if (!--cntdown) |
232 |
|
exit(EXIT_FAILURE); |
233 |
goto prompt; |
goto prompt; |
234 |
} |
} |
235 |
} while (isspace(c)); |
} while (isspace(c)); /* maybe isblank? */ |
236 |
|
|
237 |
*buf++ = c; |
*buf++ = c; |
238 |
if (!fgets(buf, size_buf-2, stdin)) |
if (!fgets(buf, size_buf-2, stdin)) |
239 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
240 |
if (!strchr(buf, '\n')) |
if (!strchr(buf, '\n')) |
241 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
242 |
while (isgraph(*buf)) buf++; |
while ((unsigned char)*buf > ' ') |
243 |
|
buf++; |
244 |
*buf = '\0'; |
*buf = '\0'; |
245 |
} |
} |
246 |
|
|
250 |
|
|
251 |
fd = open(bb_path_motd_file, O_RDONLY); |
fd = open(bb_path_motd_file, O_RDONLY); |
252 |
if (fd >= 0) { |
if (fd >= 0) { |
253 |
fflush(stdout); |
fflush_all(); |
254 |
bb_copyfd_eof(fd, STDOUT_FILENO); |
bb_copyfd_eof(fd, STDOUT_FILENO); |
255 |
close(fd); |
close(fd); |
256 |
} |
} |
263 |
* We don't want to block here */ |
* We don't want to block here */ |
264 |
ndelay_on(1); |
ndelay_on(1); |
265 |
printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT); |
printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT); |
266 |
fflush(stdout); |
fflush_all(); |
267 |
/* unix API is brain damaged regarding O_NONBLOCK, |
/* unix API is brain damaged regarding O_NONBLOCK, |
268 |
* we should undo it, or else we can affect other processes */ |
* we should undo it, or else we can affect other processes */ |
269 |
ndelay_off(1); |
ndelay_off(1); |
287 |
struct passwd *pw; |
struct passwd *pw; |
288 |
char *opt_host = opt_host; /* for compiler */ |
char *opt_host = opt_host; /* for compiler */ |
289 |
char *opt_user = opt_user; /* for compiler */ |
char *opt_user = opt_user; /* for compiler */ |
290 |
char full_tty[TTYNAME_SIZE]; |
char *full_tty; |
291 |
USE_SELINUX(security_context_t user_sid = NULL;) |
IF_SELINUX(security_context_t user_sid = NULL;) |
292 |
USE_FEATURE_UTMP(struct utmp utent;) |
IF_FEATURE_UTMP(struct utmp utent;) |
293 |
#if ENABLE_PAM |
#if ENABLE_PAM |
294 |
int pamret; |
int pamret; |
295 |
pam_handle_t *pamh; |
pam_handle_t *pamh; |
299 |
char pwdbuf[256]; |
char pwdbuf[256]; |
300 |
#endif |
#endif |
301 |
|
|
|
short_tty = full_tty; |
|
302 |
username[0] = '\0'; |
username[0] = '\0'; |
303 |
signal(SIGALRM, alarm_handler); |
signal(SIGALRM, alarm_handler); |
304 |
alarm(TIMEOUT); |
alarm(TIMEOUT); |
324 |
safe_strncpy(username, argv[0], sizeof(username)); |
safe_strncpy(username, argv[0], sizeof(username)); |
325 |
|
|
326 |
/* Let's find out and memorize our tty */ |
/* Let's find out and memorize our tty */ |
327 |
if (!isatty(0) || !isatty(1) || !isatty(2)) |
if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) |
328 |
return EXIT_FAILURE; /* Must be a terminal */ |
return EXIT_FAILURE; /* Must be a terminal */ |
329 |
safe_strncpy(full_tty, "UNKNOWN", sizeof(full_tty)); |
full_tty = xmalloc_ttyname(STDIN_FILENO); |
330 |
tmp = ttyname(0); |
if (!full_tty) |
331 |
if (tmp) { |
full_tty = xstrdup("UNKNOWN"); |
332 |
safe_strncpy(full_tty, tmp, sizeof(full_tty)); |
short_tty = full_tty; |
333 |
if (strncmp(full_tty, "/dev/", 5) == 0) |
if (strncmp(full_tty, "/dev/", 5) == 0) |
334 |
short_tty = full_tty + 5; |
short_tty += 5; |
|
} |
|
335 |
|
|
336 |
read_or_build_utent(&utent, run_by_root); |
read_or_build_utent(&utent, run_by_root); |
337 |
|
|
338 |
if (opt & LOGIN_OPT_h) { |
if (opt & LOGIN_OPT_h) { |
339 |
USE_FEATURE_UTMP( |
IF_FEATURE_UTMP(safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host));) |
|
safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host)); |
|
|
) |
|
340 |
fromhost = xasprintf(" on '%s' from '%s'", short_tty, opt_host); |
fromhost = xasprintf(" on '%s' from '%s'", short_tty, opt_host); |
341 |
} else |
} else { |
342 |
fromhost = xasprintf(" on '%s'", short_tty); |
fromhost = xasprintf(" on '%s'", short_tty); |
343 |
|
} |
344 |
|
|
345 |
/* Was breaking "login <username>" from shell command line: */ |
/* Was breaking "login <username>" from shell command line: */ |
346 |
/*bb_setpgrp();*/ |
/*bb_setpgrp();*/ |
347 |
|
|
348 |
openlog(applet_name, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH); |
openlog(applet_name, LOG_PID | LOG_CONS, LOG_AUTH); |
349 |
|
|
350 |
while (1) { |
while (1) { |
351 |
/* flush away any type-ahead (as getty does) */ |
/* flush away any type-ahead (as getty does) */ |
412 |
break; /* success, continue login process */ |
break; /* success, continue login process */ |
413 |
|
|
414 |
pam_auth_failed: |
pam_auth_failed: |
415 |
bb_error_msg("pam_%s call failed: %s (%d)", failed_msg, |
/* syslog, because we don't want potential attacker |
416 |
|
* to know _why_ login failed */ |
417 |
|
syslog(LOG_WARNING, "pam_%s call failed: %s (%d)", failed_msg, |
418 |
pam_strerror(pamh, pamret), pamret); |
pam_strerror(pamh, pamret), pamret); |
419 |
safe_strncpy(username, "UNKNOWN", sizeof(username)); |
safe_strncpy(username, "UNKNOWN", sizeof(username)); |
420 |
#else /* not PAM */ |
#else /* not PAM */ |
462 |
|
|
463 |
write_utent(&utent, username); |
write_utent(&utent, username); |
464 |
|
|
465 |
#if ENABLE_SELINUX |
IF_SELINUX(initselinux(username, full_tty, &user_sid)); |
|
if (is_selinux_enabled()) { |
|
|
security_context_t old_tty_sid, new_tty_sid; |
|
466 |
|
|
|
if (get_default_context(username, NULL, &user_sid)) { |
|
|
bb_error_msg_and_die("cannot get SID for %s", |
|
|
username); |
|
|
} |
|
|
if (getfilecon(full_tty, &old_tty_sid) < 0) { |
|
|
bb_perror_msg_and_die("getfilecon(%s) failed", |
|
|
full_tty); |
|
|
} |
|
|
if (security_compute_relabel(user_sid, old_tty_sid, |
|
|
SECCLASS_CHR_FILE, &new_tty_sid) != 0) { |
|
|
bb_perror_msg_and_die("security_change_sid(%s) failed", |
|
|
full_tty); |
|
|
} |
|
|
if (setfilecon(full_tty, new_tty_sid) != 0) { |
|
|
bb_perror_msg_and_die("chsid(%s, %s) failed", |
|
|
full_tty, new_tty_sid); |
|
|
} |
|
|
} |
|
|
#endif |
|
467 |
/* Try these, but don't complain if they fail. |
/* Try these, but don't complain if they fail. |
468 |
* _f_chown is safe wrt race t=ttyname(0);...;chown(t); */ |
* _f_chown is safe wrt race t=ttyname(0);...;chown(t); */ |
469 |
fchown(0, pw->pw_uid, pw->pw_gid); |
fchown(0, pw->pw_uid, pw->pw_gid); |
470 |
fchmod(0, 0600); |
fchmod(0, 0600); |
471 |
|
|
472 |
/* We trust environment only if we run by root */ |
/* We trust environment only if we run by root */ |
473 |
if (ENABLE_LOGIN_SCRIPTS && run_by_root) { |
if (ENABLE_LOGIN_SCRIPTS && run_by_root) |
474 |
char *t_argv[2]; |
run_login_script(pw, full_tty); |
|
|
|
|
t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT"); |
|
|
if (t_argv[0]) { |
|
|
t_argv[1] = NULL; |
|
|
xsetenv("LOGIN_TTY", full_tty); |
|
|
xsetenv("LOGIN_USER", pw->pw_name); |
|
|
xsetenv("LOGIN_UID", utoa(pw->pw_uid)); |
|
|
xsetenv("LOGIN_GID", utoa(pw->pw_gid)); |
|
|
xsetenv("LOGIN_SHELL", pw->pw_shell); |
|
|
spawn_and_wait(t_argv); /* NOMMU-friendly */ |
|
|
unsetenv("LOGIN_TTY" ); |
|
|
unsetenv("LOGIN_USER" ); |
|
|
unsetenv("LOGIN_UID" ); |
|
|
unsetenv("LOGIN_GID" ); |
|
|
unsetenv("LOGIN_SHELL"); |
|
|
} |
|
|
} |
|
475 |
|
|
476 |
change_identity(pw); |
change_identity(pw); |
477 |
tmp = pw->pw_shell; |
tmp = pw->pw_shell; |
484 |
|
|
485 |
if (pw->pw_uid == 0) |
if (pw->pw_uid == 0) |
486 |
syslog(LOG_INFO, "root login%s", fromhost); |
syslog(LOG_INFO, "root login%s", fromhost); |
487 |
#if ENABLE_SELINUX |
|
488 |
/* well, a simple setexeccon() here would do the job as well, |
/* well, a simple setexeccon() here would do the job as well, |
489 |
* but let's play the game for now */ |
* but let's play the game for now */ |
490 |
set_current_security_context(user_sid); |
IF_SELINUX(set_current_security_context(user_sid);) |
|
#endif |
|
491 |
|
|
492 |
// util-linux login also does: |
// util-linux login also does: |
493 |
// /* start new session */ |
// /* start new session */ |