PAMH_ARG_DECL(int get_account_info, const char *name, struct passwd **pwd, struct spwd **spwdent) { /* UNIX passwords area */ *pwd = pam_modutil_getpwnam(pamh, name); /* Get password file entry... */ *spwdent = NULL; if (*pwd != NULL) { if (strcmp((*pwd)->pw_passwd, "*NP*") == 0) { /* NIS+ */ #ifdef HELPER_COMPILE uid_t save_euid, save_uid; save_euid = geteuid(); save_uid = getuid(); if (save_uid == (*pwd)->pw_uid) setreuid(save_euid, save_uid); else { setreuid(0, -1); if (setreuid(-1, (*pwd)->pw_uid) == -1) { setreuid(-1, 0); setreuid(0, -1); if(setreuid(-1, (*pwd)->pw_uid) == -1) return PAM_CRED_INSUFFICIENT; } } *spwdent = pam_modutil_getspnam(pamh, name); if (save_uid == (*pwd)->pw_uid) setreuid(save_uid, save_euid); else { setreuid(-1, 0); setreuid(save_uid, -1); setreuid(-1, save_euid); } if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) return PAM_AUTHINFO_UNAVAIL; #else /* we must run helper for NIS+ passwords */ return PAM_UNIX_RUN_HELPER; #endif } else if (is_pwd_shadowed(*pwd)) { /* * ...and shadow password file entry for this user, * if shadowing is enabled */ #ifndef HELPER_COMPILE if (geteuid() || SELINUX_ENABLED) return PAM_UNIX_RUN_HELPER; #endif *spwdent = pam_modutil_getspnam(pamh, name); if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) return PAM_AUTHINFO_UNAVAIL; } } else { return PAM_USER_UNKNOWN; } return PAM_SUCCESS; }
int pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) { struct passwd *pwd; const char *newpass; const char *user; int retval, tries; options_t options; memset (&options, 0, sizeof (options)); /* Set some default values, which could be overwritten later. */ options.remember = 10; options.tries = 1; /* Parse parameters for module */ for ( ; argc-- > 0; argv++) parse_option (pamh, *argv, &options); if (options.debug) pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok entered"); if (options.remember == 0) return PAM_IGNORE; retval = pam_get_user (pamh, &user, NULL); if (retval != PAM_SUCCESS) return retval; if (user == NULL || strlen (user) == 0) { if (options.debug) pam_syslog (pamh, LOG_DEBUG, "User is not known to system"); return PAM_USER_UNKNOWN; } if (flags & PAM_PRELIM_CHECK) { if (options.debug) pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok(PAM_PRELIM_CHECK)"); return PAM_SUCCESS; } pwd = pam_modutil_getpwnam (pamh, user); if (pwd == NULL) return PAM_USER_UNKNOWN; if ((strcmp(pwd->pw_passwd, "x") == 0) || ((pwd->pw_passwd[0] == '#') && (pwd->pw_passwd[1] == '#') && (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0))) { struct spwd *spw = pam_modutil_getspnam (pamh, user); if (spw == NULL) return PAM_USER_UNKNOWN; retval = save_old_pass (pamh, user, pwd->pw_uid, spw->sp_pwdp, options.remember, options.debug); if (retval != PAM_SUCCESS) return retval; } else { retval = save_old_pass (pamh, user, pwd->pw_uid, pwd->pw_passwd, options.remember, options.debug); if (retval != PAM_SUCCESS) return retval; } newpass = NULL; tries = 0; while ((newpass == NULL) && (tries < options.tries)) { retval = pam_get_authtok (pamh, PAM_AUTHTOK, &newpass, NULL); if (retval != PAM_SUCCESS && retval != PAM_TRY_AGAIN) { if (retval == PAM_CONV_AGAIN) retval = PAM_INCOMPLETE; return retval; } tries++; if (options.debug) { if (newpass) pam_syslog (pamh, LOG_DEBUG, "got new auth token"); else pam_syslog (pamh, LOG_DEBUG, "got no auth token"); } if (newpass == NULL || retval == PAM_TRY_AGAIN) continue; if (options.debug) pam_syslog (pamh, LOG_DEBUG, "check against old password file"); if (check_old_pass (pamh, user, newpass, options.debug) != PAM_SUCCESS) { if (getuid() || options.enforce_for_root || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) { pam_error (pamh, _("Password has been already used. Choose another.")); newpass = NULL; /* Remove password item, else following module will use it */ pam_set_item (pamh, PAM_AUTHTOK, (void *) NULL); } else pam_info (pamh, _("Password has been already used.")); } } if (newpass == NULL && tries >= options.tries) { if (options.debug) pam_syslog (pamh, LOG_DEBUG, "Aborted, too many tries"); return PAM_MAXTRIES; } return PAM_SUCCESS; }