Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/loginutils/login.c

    r2725 r3232  
    33 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    44 */
     5
     6//usage:#define login_trivial_usage
     7//usage:       "[-p] [-h HOST] [[-f] USER]"
     8//usage:#define login_full_usage "\n\n"
     9//usage:       "Begin a new session on the system\n"
     10//usage:     "\n    -f  Don't authenticate (user already authenticated)"
     11//usage:     "\n    -h  Name of the remote host"
     12//usage:     "\n    -p  Preserve environment"
     13
    514#include "libbb.h"
    615#include <syslog.h>
    7 #if ENABLE_FEATURE_UTMP
    8 # include <utmp.h> /* USER_PROCESS */
    9 #endif
    1016#include <sys/resource.h>
    1117
     
    3238    TIMEOUT = 60,
    3339    EMPTY_USERNAME_COUNT = 10,
    34     USERNAME_SIZE = 32,
     40    /* Some users found 32 chars limit to be too low: */
     41    USERNAME_SIZE = 64,
    3542    TTYNAME_SIZE = 32,
    3643};
    3744
    38 static char* short_tty;
     45struct globals {
     46    struct termios tty_attrs;
     47} FIX_ALIASING;
     48#define G (*(struct globals*)&bb_common_bufsiz1)
     49#define INIT_G() do { } while (0)
     50
    3951
    4052#if ENABLE_FEATURE_NOLOGIN
     
    6981
    7082#if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM
    71 static int check_securetty(void)
     83static int check_securetty(const char *short_tty)
    7284{
    7385    char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */
     
    8496}
    8597#else
    86 static ALWAYS_INLINE int check_securetty(void) { return 1; }
     98static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; }
    8799#endif
    88100
     
    137149#endif
    138150
     151#if ENABLE_LOGIN_SESSION_AS_CHILD && ENABLE_PAM
     152static void login_pam_end(pam_handle_t *pamh)
     153{
     154    int pamret;
     155
     156    pamret = pam_setcred(pamh, PAM_DELETE_CRED);
     157    if (pamret != PAM_SUCCESS) {
     158        bb_error_msg("pam_%s failed: %s (%d)", "setcred",
     159            pam_strerror(pamh, pamret), pamret);
     160    }
     161    pamret = pam_close_session(pamh, 0);
     162    if (pamret != PAM_SUCCESS) {
     163        bb_error_msg("pam_%s failed: %s (%d)", "close_session",
     164            pam_strerror(pamh, pamret), pamret);
     165    }
     166    pamret = pam_end(pamh, pamret);
     167    if (pamret != PAM_SUCCESS) {
     168        bb_error_msg("pam_%s failed: %s (%d)", "end",
     169            pam_strerror(pamh, pamret), pamret);
     170    }
     171}
     172#endif /* ENABLE_PAM */
     173
    139174static void get_username_or_die(char *buf, int size_buf)
    140175{
     
    180215static void alarm_handler(int sig UNUSED_PARAM)
    181216{
    182     /* This is the escape hatch!  Poor serial line users and the like
     217    /* This is the escape hatch! Poor serial line users and the like
    183218     * arrive here when their connection is broken.
    184219     * We don't want to block here */
    185     ndelay_on(1);
    186     printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT);
     220    ndelay_on(STDOUT_FILENO);
     221    /* Test for correct attr restoring:
     222     * run "getty 0 -" from a shell, enter bogus username, stop at
     223     * password prompt, let it time out. Without the tcsetattr below,
     224     * when you are back at shell prompt, echo will be still off.
     225     */
     226    tcsetattr_stdin_TCSANOW(&G.tty_attrs);
     227    printf("\r\nLogin timed out after %u seconds\r\n", TIMEOUT);
    187228    fflush_all();
    188229    /* unix API is brain damaged regarding O_NONBLOCK,
    189230     * we should undo it, or else we can affect other processes */
    190     ndelay_off(1);
     231    ndelay_off(STDOUT_FILENO);
    191232    _exit(EXIT_SUCCESS);
    192233}
     
    202243    char *fromhost;
    203244    char username[USERNAME_SIZE];
    204     const char *shell;
    205245    int run_by_root;
    206246    unsigned opt;
     
    210250    char *opt_user = opt_user; /* for compiler */
    211251    char *full_tty;
     252    char *short_tty;
    212253    IF_SELINUX(security_context_t user_sid = NULL;)
    213254#if ENABLE_PAM
     
    218259    struct passwd pwdstruct;
    219260    char pwdbuf[256];
    220 #endif
    221 
    222     username[0] = '\0';
    223     signal(SIGALRM, alarm_handler);
    224     alarm(TIMEOUT);
     261    char **pamenv;
     262#endif
     263#if ENABLE_LOGIN_SESSION_AS_CHILD
     264    pid_t child_pid;
     265#endif
     266
     267    INIT_G();
    225268
    226269    /* More of suid paranoia if called by non-root: */
     
    234277    bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL);
    235278
     279    username[0] = '\0';
    236280    opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
    237281    if (opt & LOGIN_OPT_f) {
     
    244288        safe_strncpy(username, argv[0], sizeof(username));
    245289
    246     /* Let's find out and memorize our tty */
    247     if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO))
     290    /* Save tty attributes - and by doing it, check that it's indeed a tty */
     291    if (tcgetattr(STDIN_FILENO, &G.tty_attrs) < 0
     292     || !isatty(STDOUT_FILENO)
     293     /*|| !isatty(STDERR_FILENO) - no, guess some people might want to redirect this */
     294    ) {
    248295        return EXIT_FAILURE;  /* Must be a terminal */
     296    }
     297
     298    /* We install timeout handler only _after_ we saved G.tty_attrs */
     299    signal(SIGALRM, alarm_handler);
     300    alarm(TIMEOUT);
     301
     302    /* Find out and memorize our tty name */
    249303    full_tty = xmalloc_ttyname(STDIN_FILENO);
    250304    if (!full_tty)
     
    282336            goto pam_auth_failed;
    283337        }
    284         pamret = pam_authenticate(pamh, 0);
    285         if (pamret != PAM_SUCCESS) {
    286             failed_msg = "authenticate";
    287             goto pam_auth_failed;
    288             /* TODO: or just "goto auth_failed"
    289              * since user seems to enter wrong password
    290              * (in this case pamret == 7)
    291              */
     338        /* set RHOST */
     339        if (opt_host) {
     340            pamret = pam_set_item(pamh, PAM_RHOST, opt_host);
     341            if (pamret != PAM_SUCCESS) {
     342                failed_msg = "set_item(RHOST)";
     343                goto pam_auth_failed;
     344            }
     345        }
     346        if (!(opt & LOGIN_OPT_f)) {
     347            pamret = pam_authenticate(pamh, 0);
     348            if (pamret != PAM_SUCCESS) {
     349                failed_msg = "authenticate";
     350                goto pam_auth_failed;
     351                /* TODO: or just "goto auth_failed"
     352                 * since user seems to enter wrong password
     353                 * (in this case pamret == 7)
     354                 */
     355            }
    292356        }
    293357        /* check that the account is healthy */
     
    346410            break; /* -f USER: success without asking passwd */
    347411
    348         if (pw->pw_uid == 0 && !check_securetty())
     412        if (pw->pw_uid == 0 && !check_securetty(short_tty))
    349413            goto auth_failed;
    350414
     
    353417            break;
    354418 fake_it:
    355         /* authorization takes place here */
     419        /* Password reading and authorization takes place here.
     420         * Note that reads (in no-echo mode) trash tty attributes.
     421         * If we get interrupted by SIGALRM, we need to restore attrs.
     422         */
    356423        if (correct_password(pw))
    357424            break;
     
    359426 auth_failed:
    360427        opt &= ~LOGIN_OPT_f;
    361         bb_do_delay(FAIL_DELAY);
     428        bb_do_delay(LOGIN_FAIL_DELAY);
    362429        /* TODO: doesn't sound like correct English phrase to me */
    363430        puts("Login incorrect");
     
    380447        die_if_nologin();
    381448
    382     IF_SELINUX(initselinux(username, full_tty, &user_sid));
     449#if ENABLE_LOGIN_SESSION_AS_CHILD
     450    child_pid = vfork();
     451    if (child_pid != 0) {
     452        if (child_pid < 0)
     453            bb_perror_msg("vfork");
     454        else {
     455            if (safe_waitpid(child_pid, NULL, 0) == -1)
     456                bb_perror_msg("waitpid");
     457            update_utmp(child_pid, DEAD_PROCESS, NULL, NULL, NULL);
     458        }
     459        IF_PAM(login_pam_end(pamh);)
     460        return 0;
     461    }
     462#endif
     463
     464    IF_SELINUX(initselinux(username, full_tty, &user_sid);)
    383465
    384466    /* Try these, but don't complain if they fail.
     
    394476
    395477    change_identity(pw);
    396     shell = pw->pw_shell;
    397     if (!shell || !shell[0])
    398         shell = DEFAULT_SHELL;
    399     setup_environment(shell,
     478    setup_environment(pw->pw_shell,
    400479            (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV,
    401480            pw);
     481
     482#if ENABLE_PAM
     483    /* Modules such as pam_env will setup the PAM environment,
     484     * which should be copied into the new environment. */
     485    pamenv = pam_getenvlist(pamh);
     486    if (pamenv) while (*pamenv) {
     487        putenv(*pamenv);
     488        pamenv++;
     489    }
     490#endif
    402491
    403492    motd();
     
    435524
    436525    /* Exec login shell with no additional parameters */
    437     run_shell(shell, 1, NULL, NULL);
     526    run_shell(pw->pw_shell, 1, NULL, NULL);
    438527
    439528    /* return EXIT_FAILURE; - not reached */
Note: See TracChangeset for help on using the changeset viewer.