[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PAM-Announce] Linux-PAM 0.74 released



Andrew,

Please, find attached PAM code from
linux/util-linux-2.10f/login-utils/login.c
file. This is User login procedure.
It works fine, except one major problem, which contradicts to PAM specification.
I use PAM module with remote user's database (LDAP, RADIUS, TACACS+)
retcode = pam_authenticate(pamh, 0);
retcode = pam_acct_mgmt(pamh, 0);
Authentication runs OK. Both functions above returned PAM_SUCCESS.
Great lets go further.
Would you, please, look at the following 3 lines of code

/* Grab the user information out of the password file for future usage
   First get the username that we are actually using, though.
 */
retcode = pam_get_item(pamh, PAM_USER, (const void **) &username);
setpwent();                                                             /* line 635 */
pwd = getpwnam(username);                                /* line 636 */
if (pwd) initgroups(username, pwd->pw_gid);       /* line 637 */

If we use PAM module, how come we "Grab the user information out of the password file for future usage"
PAM doesn't have access to remote database, does it? It doesn't make any sense for me.
getpwnam() fails (user is unreachable), login fails as well.

I would appreciate clarification.
Best regards,

Leon




#ifdef USE_PAM
    /* username is initialized to NULL
       and if specified on the command line it is set.
       Therefore, we are safe not setting it to anything
    */

    retcode = pam_start("login",username, &conv, &pamh);
    if(retcode != PAM_SUCCESS) {
        fprintf(stderr,_("login: PAM Failure, aborting: %s\n"),
        pam_strerror(pamh, retcode));
        syslog(LOG_ERR,_("Couldn't initialize PAM: %s"), pam_strerror(pamh, retcode));
        exit(99);
    }
    /* hostname & tty are either set to NULL or their correct values,
       depending on how much we know */
    retcode = pam_set_item(pamh, PAM_RHOST, hostname);
    PAM_FAIL_CHECK;
    retcode = pam_set_item(pamh, PAM_TTY, tty);
    PAM_FAIL_CHECK;

    /* Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM
       so that the "login: " prompt gets localized. Unfortunately,
       PAM doesn't have an interface to specify the "Password: " string (yet). */
    retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
    PAM_FAIL_CHECK;
   
#if 0
    /* other than iso-8859-1
     * one more time due to reset tty by PAM
     */
    printf("\033(K");
    fprintf(stderr,"\033(K");
#endif
           
    /* if fflag == 1, then the user has already been authenticated */
    if (fflag && (getuid() == 0))
        passwd_req = 0;
    else
        passwd_req = 1;

    if(passwd_req == 1) {
        int failcount=0;

        /* there may be better ways to deal with some of these
           conditions, but at least this way I don't think we'll
           be giving away information... */
        /* Perhaps someday we can trust that all PAM modules will
           pay attention to failure count and get rid of MAX_LOGIN_TRIES? */

        retcode = pam_authenticate(pamh, 0);
        
        while((failcount++ < PAM_MAX_LOGIN_TRIES) &&
              ((retcode == PAM_AUTH_ERR) ||
               (retcode == PAM_USER_UNKNOWN) ||
               (retcode == PAM_CRED_INSUFFICIENT) ||
               (retcode == PAM_AUTHINFO_UNAVAIL))) {
          pam_get_item(pamh, PAM_USER, (const void **) &username);
          syslog(LOG_NOTICE,_("FAILED LOGIN %d FROM %s FOR %s, %s"),
                 failcount, hostname, username, pam_strerror(pamh, retcode));
          logbtmp(ttyn + 5, username, hostname);
          fprintf(stderr,_("Login incorrect\n\n"));
          pam_set_item(pamh,PAM_USER,NULL);

          retcode = pam_authenticate(pamh, 0);
        }

        if (retcode != PAM_SUCCESS) {
            pam_get_item(pamh, PAM_USER, (const void **) &username);

            if (retcode == PAM_MAXTRIES) {
                syslog(LOG_NOTICE,_("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
                        "%s, %s"), failcount, hostname, username,
                         pam_strerror(pamh, retcode));
                logbtmp(ttyn + 5, username, hostname);
            } else {
                syslog(LOG_NOTICE,_("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
                        hostname, username, pam_strerror(pamh, retcode));
                logbtmp(ttyn + 5, username, hostname);
            }

            fprintf(stderr,_("\nLogin incorrect\n"));
            pam_end(pamh, retcode);
            exit(0);
        }

        /* note PAM_RHOST parameter keeps user's privilege level */
        retcode = pam_set_item(pamh, PAM_RHOST, privilege);
        PAM_FAIL_CHECK;

        retcode = pam_acct_mgmt(pamh, 0);

        if(retcode == PAM_NEW_AUTHTOK_REQD) {
            retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
        }

        PAM_FAIL_CHECK;
    }

    /* Grab the user information out of the password file for future usage
       First get the username that we are actually using, though.
    */
    retcode = pam_get_item(pamh, PAM_USER, (const void **) &username);
    setpwent();                                                           /* line 635 */
    pwd = getpwnam(username);                              /* line 636 */
    if (pwd) initgroups(username, pwd->pw_gid);      /* line 637 */

    retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
    PAM_FAIL_CHECK;
   
    retcode = pam_open_session(pamh, 0);
    PAM_FAIL_CHECK;

    openlog("login", LOG_ODELAY, LOG_AUTHPRIV);

#else /* ! USE_PAM */

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []