X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=loginutils%2Flogin.c;h=70e85625b2ab60848955c646da0cc1b7c4e40d2d;hb=f2cbb03a378aa48f2e08b64877d54da3fab4ea6a;hp=af871436a37509306b0400fe7286b7b13f913f27;hpb=4e12b1a2a9e68685dff61acaee1e1f6c377d978c;p=oweals%2Fbusybox.git diff --git a/loginutils/login.c b/loginutils/login.c index af871436a..70e85625b 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -165,6 +165,56 @@ static int check_securetty(void) 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("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 + +#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; @@ -175,19 +225,22 @@ static void get_username_or_die(char *buf, int size_buf) /* 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'; } @@ -234,9 +287,9 @@ int login_main(int argc UNUSED_PARAM, char **argv) 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; @@ -246,7 +299,6 @@ int login_main(int argc UNUSED_PARAM, char **argv) char pwdbuf[256]; #endif - short_tty = full_tty; username[0] = '\0'; signal(SIGALRM, alarm_handler); alarm(TIMEOUT); @@ -272,21 +324,19 @@ int login_main(int argc UNUSED_PARAM, char **argv) 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 = xmalloc_ttyname(STDIN_FILENO); - 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) { - if (ENABLE_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 { fromhost = xasprintf(" on '%s'", short_tty); @@ -295,7 +345,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) /* Was breaking "login " 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) */ @@ -362,7 +412,9 @@ int login_main(int argc UNUSED_PARAM, char **argv) 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 */ @@ -410,54 +462,16 @@ int login_main(int argc UNUSED_PARAM, char **argv) 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; @@ -470,11 +484,10 @@ int login_main(int argc UNUSED_PARAM, char **argv) 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 */