puts("\r\nSystem closed for routine maintenance\r");
fclose(fp);
- fflush(NULL);
+ fflush_all();
/* Users say that they do need this prior to exit: */
tcdrain(STDOUT_FILENO);
exit(EXIT_FAILURE);
static ALWAYS_INLINE int check_securetty(void) { return 1; }
#endif
+#if ENABLE_SELINUX
+static void initselinux(char *username, char *full_tty,
+ security_context_t *user_sid)
+{
+ security_context_t old_tty_sid, new_tty_sid;
+
+ if (!is_selinux_enabled())
+ return;
+
+ if (get_default_context(username, NULL, user_sid)) {
+ bb_error_msg_and_die("can't 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
+
+#if ENABLE_LOGIN_SCRIPTS
+static void run_login_script(struct passwd *pw, char *full_tty)
+{
+ char *t_argv[2];
+
+ 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");
+ }
+}
+#else
+void run_login_script(struct passwd *pw, char *full_tty);
+#endif
+
static void get_username_or_die(char *buf, int size_buf)
{
int c, cntdown;
/* skip whitespace */
do {
c = getchar();
- if (c == EOF) exit(EXIT_FAILURE);
+ if (c == EOF)
+ exit(EXIT_FAILURE);
if (c == '\n') {
- if (!--cntdown) exit(EXIT_FAILURE);
+ if (!--cntdown)
+ exit(EXIT_FAILURE);
goto prompt;
}
- } while (isspace(c));
+ } while (isspace(c)); /* maybe isblank? */
*buf++ = c;
if (!fgets(buf, size_buf-2, stdin))
exit(EXIT_FAILURE);
if (!strchr(buf, '\n'))
exit(EXIT_FAILURE);
- while (isgraph(*buf)) buf++;
+ while ((unsigned char)*buf > ' ')
+ buf++;
*buf = '\0';
}
fd = open(bb_path_motd_file, O_RDONLY);
if (fd >= 0) {
- fflush(stdout);
+ fflush_all();
bb_copyfd_eof(fd, STDOUT_FILENO);
close(fd);
}
* We don't want to block here */
ndelay_on(1);
printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT);
- fflush(stdout);
+ fflush_all();
/* unix API is brain damaged regarding O_NONBLOCK,
* we should undo it, or else we can affect other processes */
ndelay_off(1);
struct passwd *pw;
char *opt_host = opt_host; /* for compiler */
char *opt_user = opt_user; /* for compiler */
- char full_tty[TTYNAME_SIZE];
- USE_SELINUX(security_context_t user_sid = NULL;)
- USE_FEATURE_UTMP(struct utmp utent;)
+ char *full_tty;
+ IF_SELINUX(security_context_t user_sid = NULL;)
+ IF_FEATURE_UTMP(struct utmp utent;)
#if ENABLE_PAM
int pamret;
pam_handle_t *pamh;
char pwdbuf[256];
#endif
- short_tty = full_tty;
username[0] = '\0';
signal(SIGALRM, alarm_handler);
alarm(TIMEOUT);
safe_strncpy(username, argv[0], sizeof(username));
/* Let's find out and memorize our tty */
- if (!isatty(0) || !isatty(1) || !isatty(2))
+ if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO))
return EXIT_FAILURE; /* Must be a terminal */
- safe_strncpy(full_tty, "UNKNOWN", sizeof(full_tty));
- tmp = ttyname(0);
- if (tmp) {
- safe_strncpy(full_tty, tmp, sizeof(full_tty));
- if (strncmp(full_tty, "/dev/", 5) == 0)
- short_tty = full_tty + 5;
- }
+ full_tty = xmalloc_ttyname(STDIN_FILENO);
+ if (!full_tty)
+ full_tty = xstrdup("UNKNOWN");
+ short_tty = full_tty;
+ if (strncmp(full_tty, "/dev/", 5) == 0)
+ short_tty += 5;
read_or_build_utent(&utent, run_by_root);
if (opt & LOGIN_OPT_h) {
- USE_FEATURE_UTMP(
- safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host));
- )
+ IF_FEATURE_UTMP(safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host));)
fromhost = xasprintf(" on '%s' from '%s'", short_tty, opt_host);
- } else
+ } else {
fromhost = xasprintf(" on '%s'", short_tty);
+ }
/* Was breaking "login <username>" from shell command line: */
/*bb_setpgrp();*/
- openlog(applet_name, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+ openlog(applet_name, LOG_PID | LOG_CONS, LOG_AUTH);
while (1) {
/* flush away any type-ahead (as getty does) */
break; /* success, continue login process */
pam_auth_failed:
- bb_error_msg("pam_%s call failed: %s (%d)", failed_msg,
+ /* syslog, because we don't want potential attacker
+ * to know _why_ login failed */
+ syslog(LOG_WARNING, "pam_%s call failed: %s (%d)", failed_msg,
pam_strerror(pamh, pamret), pamret);
safe_strncpy(username, "UNKNOWN", sizeof(username));
#else /* not PAM */
write_utent(&utent, username);
-#if ENABLE_SELINUX
- if (is_selinux_enabled()) {
- security_context_t old_tty_sid, new_tty_sid;
+ IF_SELINUX(initselinux(username, full_tty, &user_sid));
- 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
/* Try these, but don't complain if they fail.
* _f_chown is safe wrt race t=ttyname(0);...;chown(t); */
fchown(0, pw->pw_uid, pw->pw_gid);
fchmod(0, 0600);
/* We trust environment only if we run by root */
- if (ENABLE_LOGIN_SCRIPTS && run_by_root) {
- char *t_argv[2];
-
- 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");
- }
- }
+ if (ENABLE_LOGIN_SCRIPTS && run_by_root)
+ run_login_script(pw, full_tty);
change_identity(pw);
tmp = pw->pw_shell;
if (pw->pw_uid == 0)
syslog(LOG_INFO, "root login%s", fromhost);
-#if ENABLE_SELINUX
+
/* well, a simple setexeccon() here would do the job as well,
* but let's play the game for now */
- set_current_security_context(user_sid);
-#endif
+ IF_SELINUX(set_current_security_context(user_sid);)
// util-linux login also does:
// /* start new session */
// If this stuff is really needed, add it and explain why!
/* Set signals to defaults */
- /*signal(SIGALRM, SIG_DFL); - not needed, we already set it
- * to non-SIG_IGN, and on exec such signals are reset to SIG_DFL */
+ /* Non-ignored signals revert to SIG_DFL on exec anyway */
+ /*signal(SIGALRM, SIG_DFL);*/
/* Is this correct? This way user can ctrl-c out of /etc/profile,
* potentially creating security breach (tested with bash 3.0).