static void loginpam_acct(struct login_context *cxt) { int rc; pam_handle_t *pamh = cxt->pamh; rc = pam_acct_mgmt(pamh, 0); if (rc == PAM_NEW_AUTHTOK_REQD) rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (is_pam_failure(rc)) loginpam_err(pamh, rc); /* * Grab the user information out of the password file for future use. * First get the username that we are actually using, though. */ rc = loginpam_get_username(pamh, &cxt->username); if (is_pam_failure(rc)) loginpam_err(pamh, rc); if (!cxt->username || !*cxt->username) { warnx(_("\nSession setup problem, abort.")); syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."), __FUNCTION__, __LINE__); pam_end(pamh, PAM_SYSTEM_ERR); sleepexit(EXIT_FAILURE); } }
static pam_handle_t *init_loginpam(struct login_context *cxt) { pam_handle_t *pamh = NULL; int rc; /* * username is initialized to NULL and if specified on the command line * it is set. Therefore, we are safe not setting it to anything */ rc = pam_start(cxt->remote ? "remote" : "login", cxt->username, &cxt->conv, &pamh); if (rc != PAM_SUCCESS) { warnx(_("PAM failure, aborting: %s"), pam_strerror(pamh, rc)); syslog(LOG_ERR, _("Couldn't initialize PAM: %s"), pam_strerror(pamh, rc)); sleepexit(EXIT_FAILURE); } /* hostname & tty are either set to NULL or their correct values, * depending on how much we know */ rc = pam_set_item(pamh, PAM_RHOST, cxt->hostname); if (is_pam_failure(rc)) loginpam_err(pamh, rc); rc = pam_set_item(pamh, PAM_TTY, cxt->tty_name); if (is_pam_failure(rc)) loginpam_err(pamh, rc); /* * [email protected]: Provide a user prompt to PAM so that * the "login: "******"Password: " string (yet). */ rc = pam_set_item(pamh, PAM_USER_PROMPT, loginpam_get_prompt(cxt)); if (is_pam_failure(rc)) loginpam_err(pamh, rc); /* we need't the original username. We have to follow PAM. */ free(cxt->username); cxt->username = NULL; cxt->pamh = pamh; return pamh; }
/* * Note that the position of the pam_setcred() call is discussable: * * - the PAM docs recommend pam_setcred() before pam_open_session() * - but the original RFC http://www.opengroup.org/rfc/mirror-rfc/rfc86.0.txt * uses pam_setcred() after pam_open_session() * * The old login versions (before year 2011) followed the RFC. This is probably * not optimal, because there could be a dependence between some session modules * and the user's credentials. * * The best is probably to follow openssh and call pam_setcred() before and * after pam_open_session(). -- [email protected] (18-Nov-2011) * */ static void loginpam_session(struct login_context *cxt) { int rc; pam_handle_t *pamh = cxt->pamh; rc = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (is_pam_failure(rc)) loginpam_err(pamh, rc); rc = pam_open_session(pamh, 0); if (is_pam_failure(rc)) { pam_setcred(cxt->pamh, PAM_DELETE_CRED); loginpam_err(pamh, rc); } rc = pam_setcred(pamh, PAM_REINITIALIZE_CRED); if (is_pam_failure(rc)) { pam_close_session(pamh, 0); loginpam_err(pamh, rc); } }