diff --git a/pam-0.99.8.1-unix-blankpass.patch b/pam-0.99.8.1-unix-blankpass.patch index 3519346..9a1c054 100644 --- a/pam-0.99.8.1-unix-blankpass.patch +++ b/pam-0.99.8.1-unix-blankpass.patch @@ -1,7 +1,7 @@ diff -up Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.blankpass Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c ---- Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.blankpass 2007-08-22 18:45:17.000000000 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c 2007-08-24 10:21:54.000000000 +0200 -@@ -48,7 +48,7 @@ int main(int argc, char *argv[]) +--- Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.blankpass 2007-09-18 13:50:40.000000000 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c 2007-09-18 13:50:40.000000000 +0200 +@@ -50,7 +50,7 @@ int main(int argc, char *argv[]) char pass[MAXPASS + 1]; char *option; int npass, nullok; @@ -10,7 +10,7 @@ diff -up Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.blankpass Linux-PAM-0 int retval = PAM_AUTH_ERR; char *user; char *passwords[] = { pass }; -@@ -113,6 +113,10 @@ int main(int argc, char *argv[]) +@@ -115,6 +115,10 @@ int main(int argc, char *argv[]) if (npass != 1) { /* is it a valid password? */ _log_err(LOG_DEBUG, "no valid password supplied"); } @@ -21,7 +21,7 @@ diff -up Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.blankpass Linux-PAM-0 retval = _unix_verify_password(user, pass, nullok); -@@ -120,8 +124,11 @@ int main(int argc, char *argv[]) +@@ -122,8 +126,11 @@ int main(int argc, char *argv[]) /* return pass or fail */ @@ -36,11 +36,11 @@ diff -up Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.blankpass Linux-PAM-0 } else { return PAM_SUCCESS; diff -up Linux-PAM-0.99.8.1/modules/pam_unix/support.c.blankpass Linux-PAM-0.99.8.1/modules/pam_unix/support.c ---- Linux-PAM-0.99.8.1/modules/pam_unix/support.c.blankpass 2007-08-22 18:45:17.000000000 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/support.c 2007-08-24 10:38:09.000000000 +0200 -@@ -36,6 +36,9 @@ - #define SELINUX_ENABLED 0 - #endif +--- Linux-PAM-0.99.8.1/modules/pam_unix/support.c.blankpass 2007-09-18 13:50:40.000000000 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/support.c 2007-09-18 17:56:57.000000000 +0200 +@@ -38,6 +38,9 @@ + + const char app_name[]="pam_unix"; +static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, + unsigned int ctrl, const char *user); @@ -48,18 +48,17 @@ diff -up Linux-PAM-0.99.8.1/modules/pam_unix/support.c.blankpass Linux-PAM-0.99. /* this is a front-end for module-application conversations */ int _make_remark(pam_handle_t * pamh, unsigned int ctrl, -@@ -441,6 +444,14 @@ _unix_blankpasswd (pam_handle_t *pamh, u +@@ -442,6 +445,13 @@ _unix_blankpasswd (pam_handle_t *pamh, u + * ...and shadow password file entry for this user, * if shadowing is enabled */ - spwdent = pam_modutil_getspnam(pamh, name); -+ if (spwdent == NULL && (geteuid() || SELINUX_ENABLED)) { -+ /* we are not root perhaps this is the reason? Run helper */ ++ if (geteuid() || SELINUX_ENABLED) { ++ /* We do not have direct access to shadow. Run helper. */ + D(("running helper binary")); + if (_unix_run_helper_binary(pamh, "", ctrl, name) == PAM_SUCCESS) + return 1; -+ else -+ return 0; ++ return 0; + } + spwdent = pam_modutil_getspnam(pamh, name); } if (spwdent) - salt = x_strdup(spwdent->sp_pwdp); diff --git a/pam-0.99.8.1-unix-update-helper.patch b/pam-0.99.8.1-unix-update-helper.patch index 013b9f4..93baab4 100644 --- a/pam-0.99.8.1-unix-update-helper.patch +++ b/pam-0.99.8.1-unix-update-helper.patch @@ -1,5 +1,1397 @@ ---- /dev/null 2007-07-08 21:11:04.052436262 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/passupdate.c 2007-07-23 13:40:56.000000000 +0200 +diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c +--- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c.update-helper 2007-04-30 12:47:30.000000000 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c 2007-09-18 09:52:43.000000000 +0200 +@@ -2,6 +2,7 @@ + * Main coding by Elliot Lee , Red Hat Software. + * Copyright (C) 1996. + * Copyright (c) Jan Rêkorajski, 1999. ++ * Copyright (c) Red Hat, Inc., 2007. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -92,15 +93,6 @@ extern int getrpcport(const char *host, + #endif /* GNU libc 2.1 */ + + /* +- * PAM framework looks for these entry-points to pass control to the +- * password changing module. +- */ +- +-#if defined(USE_LCKPWDF) && !defined(HAVE_LCKPWDF) +-# include "./lckpwdf.-c" +-#endif +- +-/* + How it works: + Gets in username (has to be done) from the calling program + Does authentication of user (only if we are not running as root) +@@ -108,82 +100,15 @@ extern int getrpcport(const char *host, + Sets it. + */ + +-/* passwd/salt conversion macros */ +- +-#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') +-#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') +- + /* data tokens */ + + #define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS" + #define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS" + + #define MAX_PASSWD_TRIES 3 +-#define PW_TMPFILE "/etc/npasswd" +-#define SH_TMPFILE "/etc/nshadow" + #ifndef CRACKLIB_DICTS + #define CRACKLIB_DICTS NULL + #endif +-#define OPW_TMPFILE "/etc/security/nopasswd" +-#define OLD_PASSWORDS_FILE "/etc/security/opasswd" +- +-/* +- * i64c - convert an integer to a radix 64 character +- */ +-static int i64c(int i) +-{ +- if (i < 0) +- return ('.'); +- else if (i > 63) +- return ('z'); +- if (i == 0) +- return ('.'); +- if (i == 1) +- return ('/'); +- if (i >= 2 && i <= 11) +- return ('0' - 2 + i); +- if (i >= 12 && i <= 37) +- return ('A' - 12 + i); +- if (i >= 38 && i <= 63) +- return ('a' - 38 + i); +- return ('\0'); +-} +- +-static char *crypt_md5_wrapper(const char *pass_new) +-{ +- /* +- * Code lifted from Marek Michalkiewicz's shadow suite. (CG) +- * removed use of static variables (AGM) +- */ +- +- struct timeval tv; +- MD5_CTX ctx; +- unsigned char result[16]; +- char *cp = (char *) result; +- unsigned char tmp[16]; +- int i; +- char *x = NULL; +- +- GoodMD5Init(&ctx); +- gettimeofday(&tv, (struct timezone *) 0); +- GoodMD5Update(&ctx, (void *) &tv, sizeof tv); +- i = getpid(); +- GoodMD5Update(&ctx, (void *) &i, sizeof i); +- i = clock(); +- GoodMD5Update(&ctx, (void *) &i, sizeof i); +- GoodMD5Update(&ctx, result, sizeof result); +- GoodMD5Final(tmp, &ctx); +- strcpy(cp, "$1$"); /* magic for the MD5 */ +- cp += strlen(cp); +- for (i = 0; i < 8; i++) +- *cp++ = i64c(tmp[i] & 077); +- *cp = '\0'; +- +- /* no longer need cleartext */ +- x = Goodcrypt_md5(pass_new, (const char *) result); +- +- return x; +-} + + static char *getNISserver(pam_handle_t *pamh) + { +@@ -217,7 +142,8 @@ static char *getNISserver(pam_handle_t * + + #ifdef WITH_SELINUX + +-static int _unix_run_shadow_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, const char *fromwhat, const char *towhat) ++static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, ++ const char *fromwhat, const char *towhat, int remember) + { + int retval, child, fds[2]; + void (*sighandler)(int) = NULL; +@@ -247,7 +173,8 @@ static int _unix_run_shadow_binary(pam_h + size_t i=0; + struct rlimit rlim; + static char *envp[] = { NULL }; +- char *args[] = { NULL, NULL, NULL, NULL }; ++ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; ++ char buffer[16]; + + /* XXX - should really tidy up PAM here too */ + +@@ -270,11 +197,18 @@ static int _unix_run_shadow_binary(pam_h + } + + /* exec binary helper */ +- args[0] = x_strdup(CHKPWD_HELPER); ++ args[0] = x_strdup(UPDATE_HELPER); + args[1] = x_strdup(user); +- args[2] = x_strdup("shadow"); ++ args[2] = x_strdup("update"); ++ if (on(UNIX_SHADOW, ctrl)) ++ args[3] = x_strdup("1"); ++ else ++ args[3] = x_strdup("0"); + +- execve(CHKPWD_HELPER, args, envp); ++ snprintf(buffer, sizeof(buffer), "%d", remember); ++ args[4] = x_strdup(buffer); ++ ++ execve(UPDATE_HELPER, args, envp); + + /* should not get here: exit with error */ + D(("helper binary is not available")); +@@ -297,7 +231,7 @@ static int _unix_run_shadow_binary(pam_h + close(fds[1]); + rc=waitpid(child, &retval, 0); /* wait for helper to complete */ + if (rc<0) { +- pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); ++ pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m"); + retval = PAM_AUTH_ERR; + } else { + retval = WEXITSTATUS(retval); +@@ -315,8 +249,56 @@ static int _unix_run_shadow_binary(pam_h + + return retval; + } ++ ++static int selinux_confined(void) ++{ ++ static int confined = -1; ++ int fd; ++ char tempfile[]="/etc/.pwdXXXXXX"; ++ ++ if (confined != -1) ++ return confined; ++ ++ /* cannot be confined without SELinux enabled */ ++ if (!SELINUX_ENABLED){ ++ confined = 0; ++ return confined; ++ } ++ ++ /* let's try opening shadow read only */ ++ if ((fd=open("/etc/shadow", O_RDONLY)) != -1) { ++ close(fd); ++ confined = 0; ++ return confined; ++ } ++ ++ if (errno == EACCES) { ++ confined = 1; ++ return confined; ++ } ++ ++ /* shadow opening failed because of other reasons let's try ++ creating a file in /etc */ ++ if ((fd=mkstemp(tempfile)) != -1) { ++ unlink(tempfile); ++ close(fd); ++ confined = 0; ++ return confined; ++ } ++ ++ confined = 1; ++ return confined; ++} ++ ++#else ++static int selinux_confined(void) ++{ ++ return 0; ++} + #endif + ++#include "passupdate.c" ++ + static int check_old_password(const char *forwho, const char *newpass) + { + static char buf[16384]; +@@ -354,393 +336,6 @@ static int check_old_password(const char + return retval; + } + +-static int save_old_password(pam_handle_t *pamh, +- const char *forwho, const char *oldpass, +- int howmany) +-{ +- static char buf[16384]; +- static char nbuf[16384]; +- char *s_luser, *s_uid, *s_npas, *s_pas, *pass; +- int npas; +- FILE *pwfile, *opwfile; +- int err = 0; +- int oldmask; +- int found = 0; +- struct passwd *pwd = NULL; +- struct stat st; +- +- if (howmany < 0) { +- return PAM_SUCCESS; +- } +- +- if (oldpass == NULL) { +- return PAM_SUCCESS; +- } +- +- oldmask = umask(077); +- +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- security_context_t passwd_context=NULL; +- if (getfilecon("/etc/passwd",&passwd_context)<0) { +- return PAM_AUTHTOK_ERR; +- }; +- if (getfscreatecon(&prev_context)<0) { +- freecon(passwd_context); +- return PAM_AUTHTOK_ERR; +- } +- if (setfscreatecon(passwd_context)) { +- freecon(passwd_context); +- freecon(prev_context); +- return PAM_AUTHTOK_ERR; +- } +- freecon(passwd_context); +- } +-#endif +- pwfile = fopen(OPW_TMPFILE, "w"); +- umask(oldmask); +- if (pwfile == NULL) { +- err = 1; +- goto done; +- } +- +- opwfile = fopen(OLD_PASSWORDS_FILE, "r"); +- if (opwfile == NULL) { +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fstat(fileno(opwfile), &st) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- if (fchmod(fileno(pwfile), st.st_mode) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- while (fgets(buf, 16380, opwfile)) { +- if (!strncmp(buf, forwho, strlen(forwho))) { +- char *sptr; +- buf[strlen(buf) - 1] = '\0'; +- s_luser = strtok_r(buf, ":", &sptr); +- s_uid = strtok_r(NULL, ":", &sptr); +- s_npas = strtok_r(NULL, ":", &sptr); +- s_pas = strtok_r(NULL, ":", &sptr); +- npas = strtol(s_npas, NULL, 10) + 1; +- while (npas > howmany) { +- s_pas = strpbrk(s_pas, ","); +- if (s_pas != NULL) +- s_pas++; +- npas--; +- } +- pass = crypt_md5_wrapper(oldpass); +- if (s_pas == NULL) +- snprintf(nbuf, sizeof(nbuf), "%s:%s:%d:%s\n", +- s_luser, s_uid, npas, pass); +- else +- snprintf(nbuf, sizeof(nbuf),"%s:%s:%d:%s,%s\n", +- s_luser, s_uid, npas, s_pas, pass); +- _pam_delete(pass); +- if (fputs(nbuf, pwfile) < 0) { +- err = 1; +- break; +- } +- found = 1; +- } else if (fputs(buf, pwfile) < 0) { +- err = 1; +- break; +- } +- } +- fclose(opwfile); +- +- if (!found) { +- pwd = pam_modutil_getpwnam(pamh, forwho); +- if (pwd == NULL) { +- err = 1; +- } else { +- pass = crypt_md5_wrapper(oldpass); +- snprintf(nbuf, sizeof(nbuf), "%s:%lu:1:%s\n", +- forwho, (unsigned long)pwd->pw_uid, pass); +- _pam_delete(pass); +- if (fputs(nbuf, pwfile) < 0) { +- err = 1; +- } +- } +- } +- +- if (fclose(pwfile)) { +- D(("error writing entries to old passwords file: %m")); +- err = 1; +- } +- +-done: +- if (!err) { +- if (rename(OPW_TMPFILE, OLD_PASSWORDS_FILE)) +- err = 1; +- } +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- if (setfscreatecon(prev_context)) { +- err = 1; +- } +- if (prev_context) +- freecon(prev_context); +- prev_context=NULL; +- } +-#endif +- if (!err) { +- return PAM_SUCCESS; +- } else { +- unlink(OPW_TMPFILE); +- return PAM_AUTHTOK_ERR; +- } +-} +- +-static int _update_passwd(pam_handle_t *pamh, +- const char *forwho, const char *towhat) +-{ +- struct passwd *tmpent = NULL; +- struct stat st; +- FILE *pwfile, *opwfile; +- int err = 1; +- int oldmask; +- +- oldmask = umask(077); +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- security_context_t passwd_context=NULL; +- if (getfilecon("/etc/passwd",&passwd_context)<0) { +- return PAM_AUTHTOK_ERR; +- }; +- if (getfscreatecon(&prev_context)<0) { +- freecon(passwd_context); +- return PAM_AUTHTOK_ERR; +- } +- if (setfscreatecon(passwd_context)) { +- freecon(passwd_context); +- freecon(prev_context); +- return PAM_AUTHTOK_ERR; +- } +- freecon(passwd_context); +- } +-#endif +- pwfile = fopen(PW_TMPFILE, "w"); +- umask(oldmask); +- if (pwfile == NULL) { +- err = 1; +- goto done; +- } +- +- opwfile = fopen("/etc/passwd", "r"); +- if (opwfile == NULL) { +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fstat(fileno(opwfile), &st) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- if (fchmod(fileno(pwfile), st.st_mode) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- tmpent = fgetpwent(opwfile); +- while (tmpent) { +- if (!strcmp(tmpent->pw_name, forwho)) { +- /* To shut gcc up */ +- union { +- const char *const_charp; +- char *charp; +- } assigned_passwd; +- assigned_passwd.const_charp = towhat; +- +- tmpent->pw_passwd = assigned_passwd.charp; +- err = 0; +- } +- if (putpwent(tmpent, pwfile)) { +- D(("error writing entry to password file: %m")); +- err = 1; +- break; +- } +- tmpent = fgetpwent(opwfile); +- } +- fclose(opwfile); +- +- if (fclose(pwfile)) { +- D(("error writing entries to password file: %m")); +- err = 1; +- } +- +-done: +- if (!err) { +- if (!rename(PW_TMPFILE, "/etc/passwd")) +- pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho); +- else +- err = 1; +- } +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- if (setfscreatecon(prev_context)) { +- err = 1; +- } +- if (prev_context) +- freecon(prev_context); +- prev_context=NULL; +- } +-#endif +- if (!err) { +- return PAM_SUCCESS; +- } else { +- unlink(PW_TMPFILE); +- return PAM_AUTHTOK_ERR; +- } +-} +- +-static int _update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) +-{ +- struct spwd *spwdent = NULL, *stmpent = NULL; +- struct stat st; +- FILE *pwfile, *opwfile; +- int err = 1; +- int oldmask; +- +- spwdent = getspnam(forwho); +- if (spwdent == NULL) { +- return PAM_USER_UNKNOWN; +- } +- oldmask = umask(077); +- +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- security_context_t shadow_context=NULL; +- if (getfilecon("/etc/shadow",&shadow_context)<0) { +- return PAM_AUTHTOK_ERR; +- }; +- if (getfscreatecon(&prev_context)<0) { +- freecon(shadow_context); +- return PAM_AUTHTOK_ERR; +- } +- if (setfscreatecon(shadow_context)) { +- freecon(shadow_context); +- freecon(prev_context); +- return PAM_AUTHTOK_ERR; +- } +- freecon(shadow_context); +- } +-#endif +- pwfile = fopen(SH_TMPFILE, "w"); +- umask(oldmask); +- if (pwfile == NULL) { +- err = 1; +- goto done; +- } +- +- opwfile = fopen("/etc/shadow", "r"); +- if (opwfile == NULL) { +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fstat(fileno(opwfile), &st) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- if (fchmod(fileno(pwfile), st.st_mode) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- stmpent = fgetspent(opwfile); +- while (stmpent) { +- +- if (!strcmp(stmpent->sp_namp, forwho)) { +- stmpent->sp_pwdp = towhat; +- stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); +- err = 0; +- D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); +- } +- +- if (putspent(stmpent, pwfile)) { +- D(("error writing entry to shadow file: %m")); +- err = 1; +- break; +- } +- +- stmpent = fgetspent(opwfile); +- } +- fclose(opwfile); +- +- if (fclose(pwfile)) { +- D(("error writing entries to shadow file: %m")); +- err = 1; +- } +- +- done: +- if (!err) { +- if (!rename(SH_TMPFILE, "/etc/shadow")) +- pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho); +- else +- err = 1; +- } +- +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- if (setfscreatecon(prev_context)) { +- err = 1; +- } +- if (prev_context) +- freecon(prev_context); +- prev_context=NULL; +- } +-#endif +- +- if (!err) { +- return PAM_SUCCESS; +- } else { +- unlink(SH_TMPFILE); +- return PAM_AUTHTOK_ERR; +- } +-} +- + static int _do_setpass(pam_handle_t* pamh, const char *forwho, + const char *fromwhat, + char *towhat, unsigned int ctrl, int remember) +@@ -769,7 +364,7 @@ static int _do_setpass(pam_handle_t* pam + + /* Unlock passwd file to avoid deadlock */ + #ifdef USE_LCKPWDF +- ulckpwdf(); ++ unlock_pwdf(); + #endif + unlocked = 1; + +@@ -832,33 +427,22 @@ static int _do_setpass(pam_handle_t* pam + if (_unix_comesfromsource(pamh, forwho, 1, 0)) { + #ifdef USE_LCKPWDF + if(unlocked) { +- int i = 0; +- /* These values for the number of attempts and the sleep time +- are, of course, completely arbitrary. +- My reading of the PAM docs is that, once pam_chauthtok() has been +- called with PAM_UPDATE_AUTHTOK, we are obliged to take any +- reasonable steps to make sure the token is updated; so retrying +- for 1/10 sec. isn't overdoing it. */ +- while((retval = lckpwdf()) != 0 && i < 100) { +- usleep(1000); +- i++; +- } +- if(retval != 0) { ++ if (lock_pwdf() != PAM_SUCCESS) { + return PAM_AUTHTOK_LOCK_BUSY; + } + } + #endif ++#ifdef WITH_SELINUX ++ if (selinux_confined()) ++ return _unix_run_update_binary(pamh, ctrl, forwho, fromwhat, towhat, remember); ++#endif + /* first, save old password */ +- if (save_old_password(pamh, forwho, fromwhat, remember)) { ++ if (save_old_password(forwho, fromwhat, remember)) { + retval = PAM_AUTHTOK_ERR; + goto done; + } + if (on(UNIX_SHADOW, ctrl) || _unix_shadowed(pwd)) { + retval = _update_shadow(pamh, forwho, towhat); +-#ifdef WITH_SELINUX +- if (retval != PAM_SUCCESS && SELINUX_ENABLED) +- retval = _unix_run_shadow_binary(pamh, ctrl, forwho, fromwhat, towhat); +-#endif + if (retval == PAM_SUCCESS) + if (!_unix_shadowed(pwd)) + retval = _update_passwd(pamh, forwho, "x"); +@@ -870,7 +454,7 @@ static int _do_setpass(pam_handle_t* pam + + done: + #ifdef USE_LCKPWDF +- ulckpwdf(); ++ unlock_pwdf(); + #endif + + return retval; +@@ -891,13 +475,17 @@ static int _unix_verify_shadow(pam_handl + if (_unix_shadowed(pwd)) { + /* ...and shadow password file entry for this user, if shadowing + is enabled */ +- setspent(); +- spwdent = getspnam(user); +- endspent(); +- + #ifdef WITH_SELINUX +- if (spwdent == NULL && SELINUX_ENABLED ) +- spwdent = _unix_run_verify_binary(pamh, ctrl, user); ++ if (selinux_confined()) ++ spwdent = _unix_run_verify_binary(pamh, ctrl, user); ++ else ++ { ++#endif ++ setspent(); ++ spwdent = getspnam(user); ++ endspent(); ++#ifdef WITH_SELINUX ++ } + #endif + if (spwdent == NULL) + return PAM_AUTHINFO_UNAVAIL; +@@ -1020,7 +608,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand + int argc, const char **argv) + { + unsigned int ctrl, lctrl; +- int retval, i; ++ int retval; + int remember = -1; + + /* */ +@@ -1240,49 +828,40 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand + return retval; + } + #ifdef USE_LCKPWDF +- /* These values for the number of attempts and the sleep time +- are, of course, completely arbitrary. +- My reading of the PAM docs is that, once pam_chauthtok() has been +- called with PAM_UPDATE_AUTHTOK, we are obliged to take any +- reasonable steps to make sure the token is updated; so retrying +- for 1/10 sec. isn't overdoing it. */ +- i=0; +- while((retval = lckpwdf()) != 0 && i < 100) { +- usleep(1000); +- i++; +- } +- if(retval != 0) { ++ if (lock_pwdf() != PAM_SUCCESS) { + return PAM_AUTHTOK_LOCK_BUSY; + } + #endif + +- if (pass_old) { ++ if (!selinux_confined() && pass_old) { + retval = _unix_verify_password(pamh, user, pass_old, ctrl); + if (retval != PAM_SUCCESS) { + pam_syslog(pamh, LOG_NOTICE, "user password changed by another process"); + #ifdef USE_LCKPWDF +- ulckpwdf(); ++ unlock_pwdf(); + #endif + return retval; + } + } + +- retval = _unix_verify_shadow(pamh, user, ctrl); +- if (retval != PAM_SUCCESS) { ++ ++ if (!selinux_confined() && ++ (retval=_unix_verify_shadow(pamh, user, ctrl)) != PAM_SUCCESS) { + pam_syslog(pamh, LOG_NOTICE, "user not authenticated 2"); + #ifdef USE_LCKPWDF +- ulckpwdf(); ++ unlock_pwdf(); + #endif + return retval; + } + +- retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); +- if (retval != PAM_SUCCESS) { ++ ++ if (!selinux_confined() && ++ (retval=_pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new)) != PAM_SUCCESS) { + pam_syslog(pamh, LOG_NOTICE, + "new password not acceptable 2"); + pass_new = pass_old = NULL; /* tidy up */ + #ifdef USE_LCKPWDF +- ulckpwdf(); ++ unlock_pwdf(); + #endif + return retval; + } +@@ -1326,7 +905,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand + "out of memory for password"); + pass_new = pass_old = NULL; /* tidy up */ + #ifdef USE_LCKPWDF +- ulckpwdf(); ++ unlock_pwdf(); + #endif + return PAM_BUF_ERR; + } +@@ -1349,7 +928,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand + + retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, + remember); +- /* _do_setpass has called ulckpwdf for us */ ++ /* _do_setpass has called unlock_pwdf for us */ + + _pam_delete(tpass); + pass_old = pass_new = NULL; +diff -up Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c +--- Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.update-helper 2007-03-12 15:35:14.000000000 +0100 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c 2007-09-18 10:15:54.000000000 +0200 +@@ -41,386 +41,9 @@ static int selinux_enabled=-1; + + #include "md5.h" + #include "bigcrypt.h" ++#include "passverify.h" + +-/* syslogging function for errors and other information */ +- +-static void _log_err(int err, const char *format,...) +-{ +- va_list args; +- +- va_start(args, format); +- openlog("unix_chkpwd", LOG_CONS | LOG_PID, LOG_AUTHPRIV); +- vsyslog(err, format, args); +- va_end(args); +- closelog(); +-} +- +-static int _unix_shadowed(const struct passwd *pwd) +-{ +- char hashpass[1024]; +- if (pwd != NULL) { +- if (strcmp(pwd->pw_passwd, "x") == 0) { +- return 1; +- } +- if (strlen(pwd->pw_name) < sizeof(hashpass) - 2) { +- strcpy(hashpass, "##"); +- strcpy(hashpass + 2, pwd->pw_name); +- if (strcmp(pwd->pw_passwd, hashpass) == 0) { +- return 1; +- } +- } +- } +- return 0; +-} +- +-static void su_sighandler(int sig) +-{ +-#ifndef SA_RESETHAND +- /* emulate the behaviour of the SA_RESETHAND flag */ +- if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) +- signal(sig, SIG_DFL); +-#endif +- if (sig > 0) { +- _log_err(LOG_NOTICE, "caught signal %d.", sig); +- exit(sig); +- } +-} +- +-static void setup_signals(void) +-{ +- struct sigaction action; /* posix signal structure */ +- +- /* +- * Setup signal handlers +- */ +- (void) memset((void *) &action, 0, sizeof(action)); +- action.sa_handler = su_sighandler; +-#ifdef SA_RESETHAND +- action.sa_flags = SA_RESETHAND; +-#endif +- (void) sigaction(SIGILL, &action, NULL); +- (void) sigaction(SIGTRAP, &action, NULL); +- (void) sigaction(SIGBUS, &action, NULL); +- (void) sigaction(SIGSEGV, &action, NULL); +- action.sa_handler = SIG_IGN; +- action.sa_flags = 0; +- (void) sigaction(SIGTERM, &action, NULL); +- (void) sigaction(SIGHUP, &action, NULL); +- (void) sigaction(SIGINT, &action, NULL); +- (void) sigaction(SIGQUIT, &action, NULL); +-} +- +-static int _verify_account(const char * const uname) +-{ +- struct spwd *spent; +- struct passwd *pwent; +- +- pwent = getpwnam(uname); +- if (!pwent) { +- _log_err(LOG_ALERT, "could not identify user (from getpwnam(%s))", uname); +- return PAM_USER_UNKNOWN; +- } +- +- spent = getspnam( uname ); +- if (!spent) { +- _log_err(LOG_ALERT, "could not get username from shadow (%s))", uname); +- return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */ +- } +- printf("%ld:%ld:%ld:%ld:%ld:%ld", +- spent->sp_lstchg, /* last password change */ +- spent->sp_min, /* days until change allowed. */ +- spent->sp_max, /* days before change required */ +- spent->sp_warn, /* days warning for expiration */ +- spent->sp_inact, /* days before account inactive */ +- spent->sp_expire); /* date when account expires */ +- +- return PAM_SUCCESS; +-} +- +-static int _unix_verify_password(const char *name, const char *p, int nullok) +-{ +- struct passwd *pwd = NULL; +- struct spwd *spwdent = NULL; +- char *salt = NULL; +- char *pp = NULL; +- int retval = PAM_AUTH_ERR; +- size_t salt_len; +- +- /* UNIX passwords area */ +- setpwent(); +- pwd = getpwnam(name); /* Get password file entry... */ +- endpwent(); +- if (pwd != NULL) { +- if (_unix_shadowed(pwd)) { +- /* +- * ...and shadow password file entry for this user, +- * if shadowing is enabled +- */ +- setspent(); +- spwdent = getspnam(name); +- endspent(); +- if (spwdent != NULL) +- salt = x_strdup(spwdent->sp_pwdp); +- else +- pwd = NULL; +- } else { +- if (strcmp(pwd->pw_passwd, "*NP*") == 0) { /* NIS+ */ +- uid_t save_uid; +- +- save_uid = geteuid(); +- seteuid(pwd->pw_uid); +- spwdent = getspnam(name); +- seteuid(save_uid); +- +- salt = x_strdup(spwdent->sp_pwdp); +- } else { +- salt = x_strdup(pwd->pw_passwd); +- } +- } +- } +- if (pwd == NULL || salt == NULL) { +- _log_err(LOG_ALERT, "check pass; user unknown"); +- p = NULL; +- return PAM_USER_UNKNOWN; +- } +- +- salt_len = strlen(salt); +- if (salt_len == 0) { +- return (nullok == 0) ? PAM_AUTH_ERR : PAM_SUCCESS; +- } +- if (p == NULL || strlen(p) == 0) { +- _pam_overwrite(salt); +- _pam_drop(salt); +- return PAM_AUTHTOK_ERR; +- } +- +- /* the moment of truth -- do we agree with the password? */ +- retval = PAM_AUTH_ERR; +- if (!strncmp(salt, "$1$", 3)) { +- pp = Goodcrypt_md5(p, salt); +- if (pp && strcmp(pp, salt) == 0) { +- retval = PAM_SUCCESS; +- } else { +- _pam_overwrite(pp); +- _pam_drop(pp); +- pp = Brokencrypt_md5(p, salt); +- if (pp && strcmp(pp, salt) == 0) +- retval = PAM_SUCCESS; +- } +- } else if (*salt == '$') { +- /* +- * Ok, we don't know the crypt algorithm, but maybe +- * libcrypt nows about it? We should try it. +- */ +- pp = x_strdup (crypt(p, salt)); +- if (pp && strcmp(pp, salt) == 0) { +- retval = PAM_SUCCESS; +- } +- } else if (*salt == '*' || *salt == '!' || salt_len < 13) { +- retval = PAM_AUTH_ERR; +- } else { +- pp = bigcrypt(p, salt); +- /* +- * Note, we are comparing the bigcrypt of the password with +- * the contents of the password field. If the latter was +- * encrypted with regular crypt (and not bigcrypt) it will +- * have been truncated for storage relative to the output +- * of bigcrypt here. As such we need to compare only the +- * stored string with the subset of bigcrypt's result. +- * Bug 521314. +- */ +- if (pp && salt_len == 13 && strlen(pp) > salt_len) { +- _pam_overwrite(pp+salt_len); +- } +- +- if (pp && strcmp(pp, salt) == 0) { +- retval = PAM_SUCCESS; +- } +- } +- p = NULL; /* no longer needed here */ +- +- /* clean up */ +- _pam_overwrite(pp); +- _pam_drop(pp); +- +- return retval; +-} +- +-static char *getuidname(uid_t uid) +-{ +- struct passwd *pw; +- static char username[32]; +- +- pw = getpwuid(uid); +- if (pw == NULL) +- return NULL; +- +- strncpy(username, pw->pw_name, sizeof(username)); +- username[sizeof(username) - 1] = '\0'; +- +- return username; +-} +- +-#define SH_TMPFILE "/etc/nshadow" +-static int _update_shadow(const char *forwho) +-{ +- struct spwd *spwdent = NULL, *stmpent = NULL; +- FILE *pwfile, *opwfile; +- int err = 1; +- int oldmask; +- struct stat st; +- char pass[MAXPASS + 1]; +- char towhat[MAXPASS + 1]; +- int npass=0; +- +- /* read the password from stdin (a pipe from the pam_unix module) */ +- +- npass = read(STDIN_FILENO, pass, MAXPASS); +- +- if (npass < 0) { /* is it a valid password? */ +- +- _log_err(LOG_DEBUG, "no password supplied"); +- return PAM_AUTHTOK_ERR; +- +- } else if (npass >= MAXPASS) { +- +- _log_err(LOG_DEBUG, "password too long"); +- return PAM_AUTHTOK_ERR; +- +- } else { +- /* does pass agree with the official one? */ +- int retval=0; +- pass[npass] = '\0'; /* NUL terminate */ +- retval = _unix_verify_password(forwho, pass, 0); +- if (retval != PAM_SUCCESS) { +- return retval; +- } +- } +- +- /* read the password from stdin (a pipe from the pam_unix module) */ +- +- npass = read(STDIN_FILENO, towhat, MAXPASS); +- +- if (npass < 0) { /* is it a valid password? */ +- +- _log_err(LOG_DEBUG, "no new password supplied"); +- return PAM_AUTHTOK_ERR; +- +- } else if (npass >= MAXPASS) { +- +- _log_err(LOG_DEBUG, "new password too long"); +- return PAM_AUTHTOK_ERR; +- +- } +- +- towhat[npass] = '\0'; /* NUL terminate */ +- spwdent = getspnam(forwho); +- if (spwdent == NULL) { +- return PAM_USER_UNKNOWN; +- } +- oldmask = umask(077); +- +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- security_context_t shadow_context=NULL; +- if (getfilecon("/etc/shadow",&shadow_context)<0) { +- return PAM_AUTHTOK_ERR; +- }; +- if (getfscreatecon(&prev_context)<0) { +- freecon(shadow_context); +- return PAM_AUTHTOK_ERR; +- } +- if (setfscreatecon(shadow_context)) { +- freecon(shadow_context); +- freecon(prev_context); +- return PAM_AUTHTOK_ERR; +- } +- freecon(shadow_context); +- } +-#endif +- pwfile = fopen(SH_TMPFILE, "w"); +- umask(oldmask); +- if (pwfile == NULL) { +- err = 1; +- goto done; +- } +- +- opwfile = fopen("/etc/shadow", "r"); +- if (opwfile == NULL) { +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fstat(fileno(opwfile), &st) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- if (fchmod(fileno(pwfile), st.st_mode) == -1) { +- fclose(opwfile); +- fclose(pwfile); +- err = 1; +- goto done; +- } +- +- stmpent = fgetspent(opwfile); +- while (stmpent) { +- +- if (!strcmp(stmpent->sp_namp, forwho)) { +- stmpent->sp_pwdp = towhat; +- stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); +- err = 0; +- D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); +- } +- +- if (putspent(stmpent, pwfile)) { +- D(("error writing entry to shadow file: %m")); +- err = 1; +- break; +- } +- +- stmpent = fgetspent(opwfile); +- } +- fclose(opwfile); +- +- if (fclose(pwfile)) { +- D(("error writing entries to shadow file: %m")); +- err = 1; +- } +- +- done: +- if (!err) { +- if (rename(SH_TMPFILE, "/etc/shadow")) +- err = 1; +- } +- +-#ifdef WITH_SELINUX +- if (SELINUX_ENABLED) { +- if (setfscreatecon(prev_context)) { +- err = 1; +- } +- if (prev_context) +- freecon(prev_context); +- prev_context=NULL; +- } +-#endif +- +- if (!err) { +- return PAM_SUCCESS; +- } else { +- unlink(SH_TMPFILE); +- return PAM_AUTHTOK_ERR; +- } +-} ++const char app_name[] = "unix_chkpwd"; + + int main(int argc, char *argv[]) + { +@@ -430,6 +53,7 @@ int main(int argc, char *argv[]) + int force_failure = 0; + int retval = PAM_AUTH_ERR; + char *user; ++ char *passwords[] = { pass }; + + /* + * Catch or ignore as many signal as possible. +@@ -476,49 +100,24 @@ int main(int argc, char *argv[]) + + option=argv[2]; + +- if (strncmp(argv[2], "verify", 8) == 0) { +- /* Get the account information from the shadow file */ +- return _verify_account(argv[1]); +- } +- +- if (strncmp(option, "shadow", 8) == 0) { +- /* Attempting to change the password */ +- return _update_shadow(argv[1]); +- } +- + /* read the nullok/nonull option */ + if (strncmp(option, "nullok", 8) == 0) + nullok = 1; +- else ++ else if (strncmp(option, "nonull", 8) == 0) + nullok = 0; ++ else ++ return PAM_SYSTEM_ERR; + + /* read the password from stdin (a pipe from the pam_unix module) */ + +- npass = read(STDIN_FILENO, pass, MAXPASS); +- +- if (npass < 0) { /* is it a valid password? */ +- +- _log_err(LOG_DEBUG, "no password supplied"); ++ npass = read_passwords(STDIN_FILENO, 1, passwords); + +- } else if (npass >= MAXPASS) { +- +- _log_err(LOG_DEBUG, "password too long"); +- +- } else { +- if (npass == 0) { +- /* the password is NULL */ +- +- retval = _unix_verify_password(user, NULL, nullok); +- +- } else { +- /* does pass agree with the official one? */ +- +- pass[npass] = '\0'; /* NUL terminate */ +- retval = _unix_verify_password(user, pass, nullok); +- +- } ++ if (npass != 1) { /* is it a valid password? */ ++ _log_err(LOG_DEBUG, "no valid password supplied"); + } + ++ retval = _unix_verify_password(user, pass, nullok); ++ + memset(pass, '\0', MAXPASS); /* clear memory of the password */ + + /* return pass or fail */ +@@ -533,6 +132,7 @@ int main(int argc, char *argv[]) + + /* + * Copyright (c) Andrew G. Morgan, 1996. All rights reserved ++ * Copyright (c) Red Hat, Inc., 2007. All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h +--- /dev/null 2007-09-17 08:57:19.474470099 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h 2007-09-18 10:13:25.000000000 +0200 +@@ -0,0 +1,62 @@ ++/* ++ * This program is designed to run setuid(root) or with sufficient ++ * privilege to read all of the unix password databases. It is designed ++ * to provide a mechanism for the current user (defined by this ++ * process' uid) to verify their own password. ++ * ++ * The password is read from the standard input. The exit status of ++ * this program indicates whether the user is authenticated or not. ++ * ++ * Copyright information is located at the end of the file. ++ * ++ */ ++ ++#define MAXPASS 200 /* the maximum length of a password */ ++ ++extern const char app_name[]; ++ ++void _log_err(int err, const char *format,...); ++ ++void setup_signals(void); ++ ++int read_passwords(int fd, int npass, char **passwords); ++ ++int _unix_verify_password(const char *name, const char *p, int nullok); ++ ++char *getuidname(uid_t uid); ++ ++/* ++ * Copyright (c) Andrew G. Morgan, 1996. All rights reserved ++ * Copyright (c) Red Hat, Inc. 2007. All rights reserved ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU Public License, in which case the provisions of the GPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ++ * OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ +diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_acct.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_acct.c +--- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_acct.c.update-helper 2006-06-27 10:38:14.000000000 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_acct.c 2007-09-18 13:02:52.000000000 +0200 +@@ -124,11 +124,11 @@ struct spwd *_unix_run_verify_binary(pam + } + + /* exec binary helper */ +- args[0] = x_strdup(CHKPWD_HELPER); ++ args[0] = x_strdup(UPDATE_HELPER); + args[1] = x_strdup(user); + args[2] = x_strdup("verify"); + +- execve(CHKPWD_HELPER, args, envp); ++ execve(UPDATE_HELPER, args, envp); + + pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m"); + /* should not get here: exit with error */ +@@ -142,11 +142,11 @@ struct spwd *_unix_run_verify_binary(pam + int rc=0; + rc=waitpid(child, &retval, 0); /* wait for helper to complete */ + if (rc<0) { +- pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); ++ pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m"); + retval = PAM_AUTH_ERR; + } else { + retval = WEXITSTATUS(retval); +- if (retval != PAM_AUTHINFO_UNAVAIL) { ++ if (retval == PAM_SUCCESS) { + rc = pam_modutil_read(fds[0], buf, sizeof(buf) - 1); + if(rc > 0) { + buf[rc] = '\0'; +@@ -157,15 +157,15 @@ struct spwd *_unix_run_verify_binary(pam + &spwd.sp_warn, /* days warning for expiration */ + &spwd.sp_inact, /* days before account inactive */ + &spwd.sp_expire) /* date when account expires */ != 6 ) retval = PAM_AUTH_ERR; +- } +- else { +- pam_syslog(pamh, LOG_ERR, " ERROR %d: %m", rc); retval = PAM_AUTH_ERR; ++ } else { ++ pam_syslog(pamh, LOG_ERR, "read failed: %m"); retval = PAM_AUTH_ERR; + } ++ } else { ++ pam_syslog(pamh, LOG_ERR, "unix_update returned error %d", retval); + } + } + } else { +- pam_syslog(pamh, LOG_ERR, "Fork failed: %m"); +- D(("fork failed")); ++ pam_syslog(pamh, LOG_ERR, "fork failed: %m"); + retval = PAM_AUTH_ERR; + } + close(fds[0]); +@@ -247,15 +247,17 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_hand + setreuid( -1, save_euid ); + } + +- } else if (_unix_shadowed (pwent)) +- spent = pam_modutil_getspnam (pamh, uname); +- else +- return PAM_SUCCESS; +- ++ } else if (geteuid() != 0) { /* cannot read shadow when non root */ ++ return PAM_IGNORE; ++ } else if (_unix_shadowed (pwent)) { + #ifdef WITH_SELINUX +- if (!spent && SELINUX_ENABLED ) +- spent = _unix_run_verify_binary(pamh, ctrl, uname); ++ if (SELINUX_ENABLED) ++ spent = _unix_run_verify_binary(pamh, ctrl, uname); ++ else + #endif ++ spent = pam_modutil_getspnam (pamh, uname); ++ } else ++ return PAM_SUCCESS; + + if (!spent) + if (on(UNIX_BROKEN_SHADOW,ctrl)) +diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/passupdate.c +--- /dev/null 2007-09-17 08:57:19.474470099 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/passupdate.c 2007-09-18 09:52:43.000000000 +0200 @@ -0,0 +1,560 @@ +/* + * Main coding by Elliot Lee , Red Hat Software. @@ -561,1377 +1953,10 @@ + return PAM_AUTHTOK_ERR; + } +} ---- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_acct.c.update-helper 2006-06-27 10:38:14.000000000 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_acct.c 2007-07-23 13:40:56.000000000 +0200 -@@ -124,11 +124,11 @@ - } - - /* exec binary helper */ -- args[0] = x_strdup(CHKPWD_HELPER); -+ args[0] = x_strdup(UPDATE_HELPER); - args[1] = x_strdup(user); - args[2] = x_strdup("verify"); - -- execve(CHKPWD_HELPER, args, envp); -+ execve(UPDATE_HELPER, args, envp); - - pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m"); - /* should not get here: exit with error */ -@@ -142,11 +142,11 @@ - int rc=0; - rc=waitpid(child, &retval, 0); /* wait for helper to complete */ - if (rc<0) { -- pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); -+ pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m"); - retval = PAM_AUTH_ERR; - } else { - retval = WEXITSTATUS(retval); -- if (retval != PAM_AUTHINFO_UNAVAIL) { -+ if (retval == PAM_SUCCESS) { - rc = pam_modutil_read(fds[0], buf, sizeof(buf) - 1); - if(rc > 0) { - buf[rc] = '\0'; -@@ -157,15 +157,15 @@ - &spwd.sp_warn, /* days warning for expiration */ - &spwd.sp_inact, /* days before account inactive */ - &spwd.sp_expire) /* date when account expires */ != 6 ) retval = PAM_AUTH_ERR; -- } -- else { -- pam_syslog(pamh, LOG_ERR, " ERROR %d: %m", rc); retval = PAM_AUTH_ERR; -+ } else { -+ pam_syslog(pamh, LOG_ERR, "read failed: %m"); retval = PAM_AUTH_ERR; - } -+ } else { -+ pam_syslog(pamh, LOG_ERR, "unix_update returned error %d", retval); - } - } - } else { -- pam_syslog(pamh, LOG_ERR, "Fork failed: %m"); -- D(("fork failed")); -+ pam_syslog(pamh, LOG_ERR, "fork failed: %m"); - retval = PAM_AUTH_ERR; - } - close(fds[0]); -@@ -247,6 +247,8 @@ - setreuid( -1, save_euid ); - } - -+ } else if (geteuid() != 0) { /* cannot read shadow when non root */ -+ return PAM_IGNORE; - } else if (_unix_shadowed (pwent)) - spent = pam_modutil_getspnam (pamh, uname); - else ---- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c.update-helper 2007-04-30 12:47:30.000000000 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_passwd.c 2007-07-23 13:54:55.000000000 +0200 -@@ -2,6 +2,7 @@ - * Main coding by Elliot Lee , Red Hat Software. - * Copyright (C) 1996. - * Copyright (c) Jan Rêkorajski, 1999. -+ * Copyright (c) Red Hat, Inc., 2007. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -92,15 +93,6 @@ - #endif /* GNU libc 2.1 */ - - /* -- * PAM framework looks for these entry-points to pass control to the -- * password changing module. -- */ -- --#if defined(USE_LCKPWDF) && !defined(HAVE_LCKPWDF) --# include "./lckpwdf.-c" --#endif -- --/* - How it works: - Gets in username (has to be done) from the calling program - Does authentication of user (only if we are not running as root) -@@ -108,82 +100,15 @@ - Sets it. - */ - --/* passwd/salt conversion macros */ -- --#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') --#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') -- - /* data tokens */ - - #define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS" - #define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS" - - #define MAX_PASSWD_TRIES 3 --#define PW_TMPFILE "/etc/npasswd" --#define SH_TMPFILE "/etc/nshadow" - #ifndef CRACKLIB_DICTS - #define CRACKLIB_DICTS NULL - #endif --#define OPW_TMPFILE "/etc/security/nopasswd" --#define OLD_PASSWORDS_FILE "/etc/security/opasswd" -- --/* -- * i64c - convert an integer to a radix 64 character -- */ --static int i64c(int i) --{ -- if (i < 0) -- return ('.'); -- else if (i > 63) -- return ('z'); -- if (i == 0) -- return ('.'); -- if (i == 1) -- return ('/'); -- if (i >= 2 && i <= 11) -- return ('0' - 2 + i); -- if (i >= 12 && i <= 37) -- return ('A' - 12 + i); -- if (i >= 38 && i <= 63) -- return ('a' - 38 + i); -- return ('\0'); --} -- --static char *crypt_md5_wrapper(const char *pass_new) --{ -- /* -- * Code lifted from Marek Michalkiewicz's shadow suite. (CG) -- * removed use of static variables (AGM) -- */ -- -- struct timeval tv; -- MD5_CTX ctx; -- unsigned char result[16]; -- char *cp = (char *) result; -- unsigned char tmp[16]; -- int i; -- char *x = NULL; -- -- GoodMD5Init(&ctx); -- gettimeofday(&tv, (struct timezone *) 0); -- GoodMD5Update(&ctx, (void *) &tv, sizeof tv); -- i = getpid(); -- GoodMD5Update(&ctx, (void *) &i, sizeof i); -- i = clock(); -- GoodMD5Update(&ctx, (void *) &i, sizeof i); -- GoodMD5Update(&ctx, result, sizeof result); -- GoodMD5Final(tmp, &ctx); -- strcpy(cp, "$1$"); /* magic for the MD5 */ -- cp += strlen(cp); -- for (i = 0; i < 8; i++) -- *cp++ = i64c(tmp[i] & 077); -- *cp = '\0'; -- -- /* no longer need cleartext */ -- x = Goodcrypt_md5(pass_new, (const char *) result); -- -- return x; --} - - static char *getNISserver(pam_handle_t *pamh) - { -@@ -217,7 +142,8 @@ - - #ifdef WITH_SELINUX - --static int _unix_run_shadow_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, const char *fromwhat, const char *towhat) -+static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, -+ const char *fromwhat, const char *towhat, int remember) - { - int retval, child, fds[2]; - void (*sighandler)(int) = NULL; -@@ -247,7 +173,8 @@ - size_t i=0; - struct rlimit rlim; - static char *envp[] = { NULL }; -- char *args[] = { NULL, NULL, NULL, NULL }; -+ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; -+ char buffer[16]; - - /* XXX - should really tidy up PAM here too */ - -@@ -270,11 +197,18 @@ - } - - /* exec binary helper */ -- args[0] = x_strdup(CHKPWD_HELPER); -+ args[0] = x_strdup(UPDATE_HELPER); - args[1] = x_strdup(user); -- args[2] = x_strdup("shadow"); -+ args[2] = x_strdup("update"); -+ if (on(UNIX_SHADOW, ctrl)) -+ args[3] = x_strdup("1"); -+ else -+ args[3] = x_strdup("0"); - -- execve(CHKPWD_HELPER, args, envp); -+ snprintf(buffer, sizeof(buffer), "%d", remember); -+ args[4] = x_strdup(buffer); -+ -+ execve(UPDATE_HELPER, args, envp); - - /* should not get here: exit with error */ - D(("helper binary is not available")); -@@ -297,7 +231,7 @@ - close(fds[1]); - rc=waitpid(child, &retval, 0); /* wait for helper to complete */ - if (rc<0) { -- pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); -+ pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m"); - retval = PAM_AUTH_ERR; - } else { - retval = WEXITSTATUS(retval); -@@ -315,8 +249,56 @@ - - return retval; - } -+ -+static int selinux_confined(void) -+{ -+ static int confined = -1; -+ int fd; -+ char tempfile[]="/etc/.pwdXXXXXX"; -+ -+ if (confined != -1) -+ return confined; -+ -+ /* cannot be confined without SELinux enabled */ -+ if (!SELINUX_ENABLED){ -+ confined = 0; -+ return confined; -+ } -+ -+ /* let's try opening shadow read only */ -+ if ((fd=open("/etc/shadow", O_RDONLY)) != -1) { -+ close(fd); -+ confined = 0; -+ return confined; -+ } -+ -+ if (errno == EACCES) { -+ confined = 1; -+ return confined; -+ } -+ -+ /* shadow opening failed because of other reasons let's try -+ creating a file in /etc */ -+ if ((fd=mkstemp(tempfile)) != -1) { -+ unlink(tempfile); -+ close(fd); -+ confined = 0; -+ return confined; -+ } -+ -+ confined = 1; -+ return confined; -+} -+ -+#else -+static int selinux_confined(void) -+{ -+ return 0; -+} - #endif - -+#include "passupdate.c" -+ - static int check_old_password(const char *forwho, const char *newpass) - { - static char buf[16384]; -@@ -354,393 +336,6 @@ - return retval; - } - --static int save_old_password(pam_handle_t *pamh, -- const char *forwho, const char *oldpass, -- int howmany) --{ -- static char buf[16384]; -- static char nbuf[16384]; -- char *s_luser, *s_uid, *s_npas, *s_pas, *pass; -- int npas; -- FILE *pwfile, *opwfile; -- int err = 0; -- int oldmask; -- int found = 0; -- struct passwd *pwd = NULL; -- struct stat st; -- -- if (howmany < 0) { -- return PAM_SUCCESS; -- } -- -- if (oldpass == NULL) { -- return PAM_SUCCESS; -- } -- -- oldmask = umask(077); -- --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- security_context_t passwd_context=NULL; -- if (getfilecon("/etc/passwd",&passwd_context)<0) { -- return PAM_AUTHTOK_ERR; -- }; -- if (getfscreatecon(&prev_context)<0) { -- freecon(passwd_context); -- return PAM_AUTHTOK_ERR; -- } -- if (setfscreatecon(passwd_context)) { -- freecon(passwd_context); -- freecon(prev_context); -- return PAM_AUTHTOK_ERR; -- } -- freecon(passwd_context); -- } --#endif -- pwfile = fopen(OPW_TMPFILE, "w"); -- umask(oldmask); -- if (pwfile == NULL) { -- err = 1; -- goto done; -- } -- -- opwfile = fopen(OLD_PASSWORDS_FILE, "r"); -- if (opwfile == NULL) { -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fstat(fileno(opwfile), &st) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- if (fchmod(fileno(pwfile), st.st_mode) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- while (fgets(buf, 16380, opwfile)) { -- if (!strncmp(buf, forwho, strlen(forwho))) { -- char *sptr; -- buf[strlen(buf) - 1] = '\0'; -- s_luser = strtok_r(buf, ":", &sptr); -- s_uid = strtok_r(NULL, ":", &sptr); -- s_npas = strtok_r(NULL, ":", &sptr); -- s_pas = strtok_r(NULL, ":", &sptr); -- npas = strtol(s_npas, NULL, 10) + 1; -- while (npas > howmany) { -- s_pas = strpbrk(s_pas, ","); -- if (s_pas != NULL) -- s_pas++; -- npas--; -- } -- pass = crypt_md5_wrapper(oldpass); -- if (s_pas == NULL) -- snprintf(nbuf, sizeof(nbuf), "%s:%s:%d:%s\n", -- s_luser, s_uid, npas, pass); -- else -- snprintf(nbuf, sizeof(nbuf),"%s:%s:%d:%s,%s\n", -- s_luser, s_uid, npas, s_pas, pass); -- _pam_delete(pass); -- if (fputs(nbuf, pwfile) < 0) { -- err = 1; -- break; -- } -- found = 1; -- } else if (fputs(buf, pwfile) < 0) { -- err = 1; -- break; -- } -- } -- fclose(opwfile); -- -- if (!found) { -- pwd = pam_modutil_getpwnam(pamh, forwho); -- if (pwd == NULL) { -- err = 1; -- } else { -- pass = crypt_md5_wrapper(oldpass); -- snprintf(nbuf, sizeof(nbuf), "%s:%lu:1:%s\n", -- forwho, (unsigned long)pwd->pw_uid, pass); -- _pam_delete(pass); -- if (fputs(nbuf, pwfile) < 0) { -- err = 1; -- } -- } -- } -- -- if (fclose(pwfile)) { -- D(("error writing entries to old passwords file: %m")); -- err = 1; -- } -- --done: -- if (!err) { -- if (rename(OPW_TMPFILE, OLD_PASSWORDS_FILE)) -- err = 1; -- } --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- if (setfscreatecon(prev_context)) { -- err = 1; -- } -- if (prev_context) -- freecon(prev_context); -- prev_context=NULL; -- } --#endif -- if (!err) { -- return PAM_SUCCESS; -- } else { -- unlink(OPW_TMPFILE); -- return PAM_AUTHTOK_ERR; -- } --} -- --static int _update_passwd(pam_handle_t *pamh, -- const char *forwho, const char *towhat) --{ -- struct passwd *tmpent = NULL; -- struct stat st; -- FILE *pwfile, *opwfile; -- int err = 1; -- int oldmask; -- -- oldmask = umask(077); --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- security_context_t passwd_context=NULL; -- if (getfilecon("/etc/passwd",&passwd_context)<0) { -- return PAM_AUTHTOK_ERR; -- }; -- if (getfscreatecon(&prev_context)<0) { -- freecon(passwd_context); -- return PAM_AUTHTOK_ERR; -- } -- if (setfscreatecon(passwd_context)) { -- freecon(passwd_context); -- freecon(prev_context); -- return PAM_AUTHTOK_ERR; -- } -- freecon(passwd_context); -- } --#endif -- pwfile = fopen(PW_TMPFILE, "w"); -- umask(oldmask); -- if (pwfile == NULL) { -- err = 1; -- goto done; -- } -- -- opwfile = fopen("/etc/passwd", "r"); -- if (opwfile == NULL) { -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fstat(fileno(opwfile), &st) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- if (fchmod(fileno(pwfile), st.st_mode) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- tmpent = fgetpwent(opwfile); -- while (tmpent) { -- if (!strcmp(tmpent->pw_name, forwho)) { -- /* To shut gcc up */ -- union { -- const char *const_charp; -- char *charp; -- } assigned_passwd; -- assigned_passwd.const_charp = towhat; -- -- tmpent->pw_passwd = assigned_passwd.charp; -- err = 0; -- } -- if (putpwent(tmpent, pwfile)) { -- D(("error writing entry to password file: %m")); -- err = 1; -- break; -- } -- tmpent = fgetpwent(opwfile); -- } -- fclose(opwfile); -- -- if (fclose(pwfile)) { -- D(("error writing entries to password file: %m")); -- err = 1; -- } -- --done: -- if (!err) { -- if (!rename(PW_TMPFILE, "/etc/passwd")) -- pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho); -- else -- err = 1; -- } --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- if (setfscreatecon(prev_context)) { -- err = 1; -- } -- if (prev_context) -- freecon(prev_context); -- prev_context=NULL; -- } --#endif -- if (!err) { -- return PAM_SUCCESS; -- } else { -- unlink(PW_TMPFILE); -- return PAM_AUTHTOK_ERR; -- } --} -- --static int _update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) --{ -- struct spwd *spwdent = NULL, *stmpent = NULL; -- struct stat st; -- FILE *pwfile, *opwfile; -- int err = 1; -- int oldmask; -- -- spwdent = getspnam(forwho); -- if (spwdent == NULL) { -- return PAM_USER_UNKNOWN; -- } -- oldmask = umask(077); -- --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- security_context_t shadow_context=NULL; -- if (getfilecon("/etc/shadow",&shadow_context)<0) { -- return PAM_AUTHTOK_ERR; -- }; -- if (getfscreatecon(&prev_context)<0) { -- freecon(shadow_context); -- return PAM_AUTHTOK_ERR; -- } -- if (setfscreatecon(shadow_context)) { -- freecon(shadow_context); -- freecon(prev_context); -- return PAM_AUTHTOK_ERR; -- } -- freecon(shadow_context); -- } --#endif -- pwfile = fopen(SH_TMPFILE, "w"); -- umask(oldmask); -- if (pwfile == NULL) { -- err = 1; -- goto done; -- } -- -- opwfile = fopen("/etc/shadow", "r"); -- if (opwfile == NULL) { -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fstat(fileno(opwfile), &st) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- if (fchmod(fileno(pwfile), st.st_mode) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- stmpent = fgetspent(opwfile); -- while (stmpent) { -- -- if (!strcmp(stmpent->sp_namp, forwho)) { -- stmpent->sp_pwdp = towhat; -- stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); -- err = 0; -- D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); -- } -- -- if (putspent(stmpent, pwfile)) { -- D(("error writing entry to shadow file: %m")); -- err = 1; -- break; -- } -- -- stmpent = fgetspent(opwfile); -- } -- fclose(opwfile); -- -- if (fclose(pwfile)) { -- D(("error writing entries to shadow file: %m")); -- err = 1; -- } -- -- done: -- if (!err) { -- if (!rename(SH_TMPFILE, "/etc/shadow")) -- pam_syslog(pamh, LOG_NOTICE, "password changed for %s", forwho); -- else -- err = 1; -- } -- --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- if (setfscreatecon(prev_context)) { -- err = 1; -- } -- if (prev_context) -- freecon(prev_context); -- prev_context=NULL; -- } --#endif -- -- if (!err) { -- return PAM_SUCCESS; -- } else { -- unlink(SH_TMPFILE); -- return PAM_AUTHTOK_ERR; -- } --} -- - static int _do_setpass(pam_handle_t* pamh, const char *forwho, - const char *fromwhat, - char *towhat, unsigned int ctrl, int remember) -@@ -769,7 +364,7 @@ - - /* Unlock passwd file to avoid deadlock */ - #ifdef USE_LCKPWDF -- ulckpwdf(); -+ unlock_pwdf(); - #endif - unlocked = 1; - -@@ -832,33 +427,22 @@ - if (_unix_comesfromsource(pamh, forwho, 1, 0)) { - #ifdef USE_LCKPWDF - if(unlocked) { -- int i = 0; -- /* These values for the number of attempts and the sleep time -- are, of course, completely arbitrary. -- My reading of the PAM docs is that, once pam_chauthtok() has been -- called with PAM_UPDATE_AUTHTOK, we are obliged to take any -- reasonable steps to make sure the token is updated; so retrying -- for 1/10 sec. isn't overdoing it. */ -- while((retval = lckpwdf()) != 0 && i < 100) { -- usleep(1000); -- i++; -- } -- if(retval != 0) { -+ if (lock_pwdf() != PAM_SUCCESS) { - return PAM_AUTHTOK_LOCK_BUSY; - } - } - #endif -+#ifdef WITH_SELINUX -+ if (selinux_confined()) -+ return _unix_run_update_binary(pamh, ctrl, forwho, fromwhat, towhat, remember); -+#endif - /* first, save old password */ -- if (save_old_password(pamh, forwho, fromwhat, remember)) { -+ if (save_old_password(forwho, fromwhat, remember)) { - retval = PAM_AUTHTOK_ERR; - goto done; - } - if (on(UNIX_SHADOW, ctrl) || _unix_shadowed(pwd)) { - retval = _update_shadow(pamh, forwho, towhat); --#ifdef WITH_SELINUX -- if (retval != PAM_SUCCESS && SELINUX_ENABLED) -- retval = _unix_run_shadow_binary(pamh, ctrl, forwho, fromwhat, towhat); --#endif - if (retval == PAM_SUCCESS) - if (!_unix_shadowed(pwd)) - retval = _update_passwd(pamh, forwho, "x"); -@@ -870,7 +454,7 @@ - - done: - #ifdef USE_LCKPWDF -- ulckpwdf(); -+ unlock_pwdf(); - #endif - - return retval; -@@ -891,13 +475,17 @@ - if (_unix_shadowed(pwd)) { - /* ...and shadow password file entry for this user, if shadowing - is enabled */ -- setspent(); -- spwdent = getspnam(user); -- endspent(); -- - #ifdef WITH_SELINUX -- if (spwdent == NULL && SELINUX_ENABLED ) -- spwdent = _unix_run_verify_binary(pamh, ctrl, user); -+ if (selinux_confined()) -+ spwdent = _unix_run_verify_binary(pamh, ctrl, user); -+ else -+ { -+#endif -+ setspent(); -+ spwdent = getspnam(user); -+ endspent(); -+#ifdef WITH_SELINUX -+ } - #endif - if (spwdent == NULL) - return PAM_AUTHINFO_UNAVAIL; -@@ -1020,7 +608,7 @@ - int argc, const char **argv) - { - unsigned int ctrl, lctrl; -- int retval, i; -+ int retval; - int remember = -1; - - /* */ -@@ -1240,49 +828,40 @@ - return retval; - } - #ifdef USE_LCKPWDF -- /* These values for the number of attempts and the sleep time -- are, of course, completely arbitrary. -- My reading of the PAM docs is that, once pam_chauthtok() has been -- called with PAM_UPDATE_AUTHTOK, we are obliged to take any -- reasonable steps to make sure the token is updated; so retrying -- for 1/10 sec. isn't overdoing it. */ -- i=0; -- while((retval = lckpwdf()) != 0 && i < 100) { -- usleep(1000); -- i++; -- } -- if(retval != 0) { -+ if (lock_pwdf() != PAM_SUCCESS) { - return PAM_AUTHTOK_LOCK_BUSY; - } - #endif - -- if (pass_old) { -+ if (!selinux_confined() && pass_old) { - retval = _unix_verify_password(pamh, user, pass_old, ctrl); - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, "user password changed by another process"); - #ifdef USE_LCKPWDF -- ulckpwdf(); -+ unlock_pwdf(); - #endif - return retval; - } - } - -- retval = _unix_verify_shadow(pamh, user, ctrl); -- if (retval != PAM_SUCCESS) { -+ -+ if (!selinux_confined() && -+ (retval=_unix_verify_shadow(pamh, user, ctrl)) != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, "user not authenticated 2"); - #ifdef USE_LCKPWDF -- ulckpwdf(); -+ unlock_pwdf(); - #endif - return retval; - } - -- retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); -- if (retval != PAM_SUCCESS) { -+ -+ if (!selinux_confined() && -+ (retval=_pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new)) != PAM_SUCCESS) { - pam_syslog(pamh, LOG_NOTICE, - "new password not acceptable 2"); - pass_new = pass_old = NULL; /* tidy up */ - #ifdef USE_LCKPWDF -- ulckpwdf(); -+ unlock_pwdf(); - #endif - return retval; - } -@@ -1326,7 +905,7 @@ - "out of memory for password"); - pass_new = pass_old = NULL; /* tidy up */ - #ifdef USE_LCKPWDF -- ulckpwdf(); -+ unlock_pwdf(); - #endif - return PAM_BUF_ERR; - } -@@ -1349,7 +928,7 @@ - - retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, - remember); -- /* _do_setpass has called ulckpwdf for us */ -+ /* _do_setpass has called unlock_pwdf for us */ - - _pam_delete(tpass); - pass_old = pass_new = NULL; ---- /dev/null 2007-07-08 21:11:04.052436262 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h 2007-07-23 13:40:56.000000000 +0200 -@@ -0,0 +1,60 @@ -+/* -+ * This program is designed to run setuid(root) or with sufficient -+ * privilege to read all of the unix password databases. It is designed -+ * to provide a mechanism for the current user (defined by this -+ * process' uid) to verify their own password. -+ * -+ * The password is read from the standard input. The exit status of -+ * this program indicates whether the user is authenticated or not. -+ * -+ * Copyright information is located at the end of the file. -+ * -+ */ -+ -+#define MAXPASS 200 /* the maximum length of a password */ -+ -+void _log_err(int err, const char *format,...); -+ -+void setup_signals(void); -+ -+int read_passwords(int fd, int npass, char **passwords); -+ -+int _unix_verify_password(const char *name, const char *p, int nullok); -+ -+char *getuidname(uid_t uid); -+ -+/* -+ * Copyright (c) Andrew G. Morgan, 1996. All rights reserved -+ * Copyright (c) Red Hat, Inc. 2007. All rights reserved -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, and the entire permission notice in its entirety, -+ * including the disclaimer of warranties. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote -+ * products derived from this software without specific prior -+ * written permission. -+ * -+ * ALTERNATIVELY, this product may be distributed under the terms of -+ * the GNU Public License, in which case the provisions of the GPL are -+ * required INSTEAD OF the above restrictions. (This clause is -+ * necessary due to a potential bad interaction between the GPL and -+ * the restrictions contained in a BSD-style copyright.) -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -+ * OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ ---- Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c.update-helper 2007-03-12 15:35:14.000000000 +0100 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_chkpwd.c 2007-07-23 13:40:56.000000000 +0200 -@@ -41,386 +41,7 @@ - - #include "md5.h" - #include "bigcrypt.h" -- --/* syslogging function for errors and other information */ -- --static void _log_err(int err, const char *format,...) --{ -- va_list args; -- -- va_start(args, format); -- openlog("unix_chkpwd", LOG_CONS | LOG_PID, LOG_AUTHPRIV); -- vsyslog(err, format, args); -- va_end(args); -- closelog(); --} -- --static int _unix_shadowed(const struct passwd *pwd) --{ -- char hashpass[1024]; -- if (pwd != NULL) { -- if (strcmp(pwd->pw_passwd, "x") == 0) { -- return 1; -- } -- if (strlen(pwd->pw_name) < sizeof(hashpass) - 2) { -- strcpy(hashpass, "##"); -- strcpy(hashpass + 2, pwd->pw_name); -- if (strcmp(pwd->pw_passwd, hashpass) == 0) { -- return 1; -- } -- } -- } -- return 0; --} -- --static void su_sighandler(int sig) --{ --#ifndef SA_RESETHAND -- /* emulate the behaviour of the SA_RESETHAND flag */ -- if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) -- signal(sig, SIG_DFL); --#endif -- if (sig > 0) { -- _log_err(LOG_NOTICE, "caught signal %d.", sig); -- exit(sig); -- } --} -- --static void setup_signals(void) --{ -- struct sigaction action; /* posix signal structure */ -- -- /* -- * Setup signal handlers -- */ -- (void) memset((void *) &action, 0, sizeof(action)); -- action.sa_handler = su_sighandler; --#ifdef SA_RESETHAND -- action.sa_flags = SA_RESETHAND; --#endif -- (void) sigaction(SIGILL, &action, NULL); -- (void) sigaction(SIGTRAP, &action, NULL); -- (void) sigaction(SIGBUS, &action, NULL); -- (void) sigaction(SIGSEGV, &action, NULL); -- action.sa_handler = SIG_IGN; -- action.sa_flags = 0; -- (void) sigaction(SIGTERM, &action, NULL); -- (void) sigaction(SIGHUP, &action, NULL); -- (void) sigaction(SIGINT, &action, NULL); -- (void) sigaction(SIGQUIT, &action, NULL); --} -- --static int _verify_account(const char * const uname) --{ -- struct spwd *spent; -- struct passwd *pwent; -- -- pwent = getpwnam(uname); -- if (!pwent) { -- _log_err(LOG_ALERT, "could not identify user (from getpwnam(%s))", uname); -- return PAM_USER_UNKNOWN; -- } -- -- spent = getspnam( uname ); -- if (!spent) { -- _log_err(LOG_ALERT, "could not get username from shadow (%s))", uname); -- return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */ -- } -- printf("%ld:%ld:%ld:%ld:%ld:%ld", -- spent->sp_lstchg, /* last password change */ -- spent->sp_min, /* days until change allowed. */ -- spent->sp_max, /* days before change required */ -- spent->sp_warn, /* days warning for expiration */ -- spent->sp_inact, /* days before account inactive */ -- spent->sp_expire); /* date when account expires */ -- -- return PAM_SUCCESS; --} -- --static int _unix_verify_password(const char *name, const char *p, int nullok) --{ -- struct passwd *pwd = NULL; -- struct spwd *spwdent = NULL; -- char *salt = NULL; -- char *pp = NULL; -- int retval = PAM_AUTH_ERR; -- size_t salt_len; -- -- /* UNIX passwords area */ -- setpwent(); -- pwd = getpwnam(name); /* Get password file entry... */ -- endpwent(); -- if (pwd != NULL) { -- if (_unix_shadowed(pwd)) { -- /* -- * ...and shadow password file entry for this user, -- * if shadowing is enabled -- */ -- setspent(); -- spwdent = getspnam(name); -- endspent(); -- if (spwdent != NULL) -- salt = x_strdup(spwdent->sp_pwdp); -- else -- pwd = NULL; -- } else { -- if (strcmp(pwd->pw_passwd, "*NP*") == 0) { /* NIS+ */ -- uid_t save_uid; -- -- save_uid = geteuid(); -- seteuid(pwd->pw_uid); -- spwdent = getspnam(name); -- seteuid(save_uid); -- -- salt = x_strdup(spwdent->sp_pwdp); -- } else { -- salt = x_strdup(pwd->pw_passwd); -- } -- } -- } -- if (pwd == NULL || salt == NULL) { -- _log_err(LOG_ALERT, "check pass; user unknown"); -- p = NULL; -- return PAM_USER_UNKNOWN; -- } -- -- salt_len = strlen(salt); -- if (salt_len == 0) { -- return (nullok == 0) ? PAM_AUTH_ERR : PAM_SUCCESS; -- } -- if (p == NULL || strlen(p) == 0) { -- _pam_overwrite(salt); -- _pam_drop(salt); -- return PAM_AUTHTOK_ERR; -- } -- -- /* the moment of truth -- do we agree with the password? */ -- retval = PAM_AUTH_ERR; -- if (!strncmp(salt, "$1$", 3)) { -- pp = Goodcrypt_md5(p, salt); -- if (pp && strcmp(pp, salt) == 0) { -- retval = PAM_SUCCESS; -- } else { -- _pam_overwrite(pp); -- _pam_drop(pp); -- pp = Brokencrypt_md5(p, salt); -- if (pp && strcmp(pp, salt) == 0) -- retval = PAM_SUCCESS; -- } -- } else if (*salt == '$') { -- /* -- * Ok, we don't know the crypt algorithm, but maybe -- * libcrypt nows about it? We should try it. -- */ -- pp = x_strdup (crypt(p, salt)); -- if (pp && strcmp(pp, salt) == 0) { -- retval = PAM_SUCCESS; -- } -- } else if (*salt == '*' || *salt == '!' || salt_len < 13) { -- retval = PAM_AUTH_ERR; -- } else { -- pp = bigcrypt(p, salt); -- /* -- * Note, we are comparing the bigcrypt of the password with -- * the contents of the password field. If the latter was -- * encrypted with regular crypt (and not bigcrypt) it will -- * have been truncated for storage relative to the output -- * of bigcrypt here. As such we need to compare only the -- * stored string with the subset of bigcrypt's result. -- * Bug 521314. -- */ -- if (pp && salt_len == 13 && strlen(pp) > salt_len) { -- _pam_overwrite(pp+salt_len); -- } -- -- if (pp && strcmp(pp, salt) == 0) { -- retval = PAM_SUCCESS; -- } -- } -- p = NULL; /* no longer needed here */ -- -- /* clean up */ -- _pam_overwrite(pp); -- _pam_drop(pp); -- -- return retval; --} -- --static char *getuidname(uid_t uid) --{ -- struct passwd *pw; -- static char username[32]; -- -- pw = getpwuid(uid); -- if (pw == NULL) -- return NULL; -- -- strncpy(username, pw->pw_name, sizeof(username)); -- username[sizeof(username) - 1] = '\0'; -- -- return username; --} -- --#define SH_TMPFILE "/etc/nshadow" --static int _update_shadow(const char *forwho) --{ -- struct spwd *spwdent = NULL, *stmpent = NULL; -- FILE *pwfile, *opwfile; -- int err = 1; -- int oldmask; -- struct stat st; -- char pass[MAXPASS + 1]; -- char towhat[MAXPASS + 1]; -- int npass=0; -- -- /* read the password from stdin (a pipe from the pam_unix module) */ -- -- npass = read(STDIN_FILENO, pass, MAXPASS); -- -- if (npass < 0) { /* is it a valid password? */ -- -- _log_err(LOG_DEBUG, "no password supplied"); -- return PAM_AUTHTOK_ERR; -- -- } else if (npass >= MAXPASS) { -- -- _log_err(LOG_DEBUG, "password too long"); -- return PAM_AUTHTOK_ERR; -- -- } else { -- /* does pass agree with the official one? */ -- int retval=0; -- pass[npass] = '\0'; /* NUL terminate */ -- retval = _unix_verify_password(forwho, pass, 0); -- if (retval != PAM_SUCCESS) { -- return retval; -- } -- } -- -- /* read the password from stdin (a pipe from the pam_unix module) */ -- -- npass = read(STDIN_FILENO, towhat, MAXPASS); -- -- if (npass < 0) { /* is it a valid password? */ -- -- _log_err(LOG_DEBUG, "no new password supplied"); -- return PAM_AUTHTOK_ERR; -- -- } else if (npass >= MAXPASS) { -- -- _log_err(LOG_DEBUG, "new password too long"); -- return PAM_AUTHTOK_ERR; -- -- } -- -- towhat[npass] = '\0'; /* NUL terminate */ -- spwdent = getspnam(forwho); -- if (spwdent == NULL) { -- return PAM_USER_UNKNOWN; -- } -- oldmask = umask(077); -- --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- security_context_t shadow_context=NULL; -- if (getfilecon("/etc/shadow",&shadow_context)<0) { -- return PAM_AUTHTOK_ERR; -- }; -- if (getfscreatecon(&prev_context)<0) { -- freecon(shadow_context); -- return PAM_AUTHTOK_ERR; -- } -- if (setfscreatecon(shadow_context)) { -- freecon(shadow_context); -- freecon(prev_context); -- return PAM_AUTHTOK_ERR; -- } -- freecon(shadow_context); -- } --#endif -- pwfile = fopen(SH_TMPFILE, "w"); -- umask(oldmask); -- if (pwfile == NULL) { -- err = 1; -- goto done; -- } -- -- opwfile = fopen("/etc/shadow", "r"); -- if (opwfile == NULL) { -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fstat(fileno(opwfile), &st) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- if (fchmod(fileno(pwfile), st.st_mode) == -1) { -- fclose(opwfile); -- fclose(pwfile); -- err = 1; -- goto done; -- } -- -- stmpent = fgetspent(opwfile); -- while (stmpent) { -- -- if (!strcmp(stmpent->sp_namp, forwho)) { -- stmpent->sp_pwdp = towhat; -- stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24); -- err = 0; -- D(("Set password %s for %s", stmpent->sp_pwdp, forwho)); -- } -- -- if (putspent(stmpent, pwfile)) { -- D(("error writing entry to shadow file: %m")); -- err = 1; -- break; -- } -- -- stmpent = fgetspent(opwfile); -- } -- fclose(opwfile); -- -- if (fclose(pwfile)) { -- D(("error writing entries to shadow file: %m")); -- err = 1; -- } -- -- done: -- if (!err) { -- if (rename(SH_TMPFILE, "/etc/shadow")) -- err = 1; -- } -- --#ifdef WITH_SELINUX -- if (SELINUX_ENABLED) { -- if (setfscreatecon(prev_context)) { -- err = 1; -- } -- if (prev_context) -- freecon(prev_context); -- prev_context=NULL; -- } --#endif -- -- if (!err) { -- return PAM_SUCCESS; -- } else { -- unlink(SH_TMPFILE); -- return PAM_AUTHTOK_ERR; -- } --} -+#include "passverify.h" - - int main(int argc, char *argv[]) - { -@@ -430,6 +51,7 @@ - int force_failure = 0; - int retval = PAM_AUTH_ERR; - char *user; -+ char *passwords[] = { pass }; - - /* - * Catch or ignore as many signal as possible. -@@ -476,49 +98,24 @@ - - option=argv[2]; - -- if (strncmp(argv[2], "verify", 8) == 0) { -- /* Get the account information from the shadow file */ -- return _verify_account(argv[1]); -- } -- -- if (strncmp(option, "shadow", 8) == 0) { -- /* Attempting to change the password */ -- return _update_shadow(argv[1]); -- } -- - /* read the nullok/nonull option */ - if (strncmp(option, "nullok", 8) == 0) - nullok = 1; -- else -+ else if (strncmp(option, "nonull", 8) == 0) - nullok = 0; -+ else -+ return PAM_SYSTEM_ERR; - - /* read the password from stdin (a pipe from the pam_unix module) */ - -- npass = read(STDIN_FILENO, pass, MAXPASS); -- -- if (npass < 0) { /* is it a valid password? */ -- -- _log_err(LOG_DEBUG, "no password supplied"); -+ npass = read_passwords(STDIN_FILENO, 1, passwords); - -- } else if (npass >= MAXPASS) { -- -- _log_err(LOG_DEBUG, "password too long"); -- -- } else { -- if (npass == 0) { -- /* the password is NULL */ -- -- retval = _unix_verify_password(user, NULL, nullok); -- -- } else { -- /* does pass agree with the official one? */ -- -- pass[npass] = '\0'; /* NUL terminate */ -- retval = _unix_verify_password(user, pass, nullok); -- -- } -+ if (npass != 1) { /* is it a valid password? */ -+ _log_err(LOG_DEBUG, "no valid password supplied"); - } - -+ retval = _unix_verify_password(user, pass, nullok); -+ - memset(pass, '\0', MAXPASS); /* clear memory of the password */ - - /* return pass or fail */ -@@ -533,6 +130,7 @@ - - /* - * Copyright (c) Andrew G. Morgan, 1996. All rights reserved -+ * Copyright (c) Red Hat, Inc., 2007. All rights reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions ---- /dev/null 2007-07-08 21:11:04.052436262 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_update.c 2007-07-23 13:40:56.000000000 +0200 -@@ -0,0 +1,262 @@ +diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/unix_update.c +--- /dev/null 2007-09-17 08:57:19.474470099 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_update.c 2007-09-18 10:16:36.000000000 +0200 +@@ -0,0 +1,264 @@ +/* + * This program is designed to run setuid(root) or with sufficient + * privilege to read all of the unix password databases. It is designed @@ -1984,6 +2009,8 @@ + _pam_drop(xx); \ +} + ++const char app_name[] = "unix_update"; ++ +static int +_unix_shadowed(const struct passwd *pwd) +{ @@ -2194,8 +2221,9 @@ + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ ---- /dev/null 2007-07-08 21:11:04.052436262 +0200 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c 2007-07-23 13:40:56.000000000 +0200 +diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c +--- /dev/null 2007-09-17 08:57:19.474470099 +0200 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c 2007-09-18 10:15:19.000000000 +0200 @@ -0,0 +1,308 @@ +/* + * This program is designed to run setuid(root) or with sufficient @@ -2242,7 +2270,7 @@ + va_list args; + + va_start(args, format); -+ openlog("unix_chkpwd", LOG_CONS | LOG_PID, LOG_AUTHPRIV); ++ openlog(app_name, LOG_CONS | LOG_PID, LOG_AUTHPRIV); + vsyslog(err, format, args); + va_end(args); + closelog(); @@ -2505,9 +2533,40 @@ + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +diff -up Linux-PAM-0.99.8.1/modules/pam_unix/support.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/support.c +--- Linux-PAM-0.99.8.1/modules/pam_unix/support.c.update-helper 2007-02-06 17:06:45.000000000 +0100 ++++ Linux-PAM-0.99.8.1/modules/pam_unix/support.c 2007-09-18 12:05:31.000000000 +0200 +@@ -36,6 +36,8 @@ + #define SELINUX_ENABLED 0 + #endif + ++const char app_name[]="pam_unix"; ++ + /* this is a front-end for module-application conversations */ + + int _make_remark(pam_handle_t * pamh, unsigned int ctrl, +@@ -627,7 +629,7 @@ int _unix_verify_password(pam_handle_t * + setreuid( save_uid, -1 ); + setreuid( -1, save_euid ); + } +- } else if (_unix_shadowed(pwd)) { ++ } else if (_unix_shadowed(pwd) && !SELINUX_ENABLED) { + /* + * ...and shadow password file entry for this user, + * if shadowing is enabled +diff -up Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am --- Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am.update-helper 2006-12-18 19:50:50.000000000 +0100 -+++ Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am 2007-07-23 13:40:56.000000000 +0200 -@@ -16,7 +16,8 @@ ++++ Linux-PAM-0.99.8.1/modules/pam_unix/Makefile.am 2007-09-18 12:54:44.000000000 +0200 +@@ -4,7 +4,7 @@ + + CLEANFILES = *~ + +-EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c $(MANS) CHANGELOG \ ++EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c passupdate.c $(MANS) CHANGELOG \ + tst-pam_unix $(XMLS) + + man_MANS = pam_unix.8 unix_chkpwd.8 +@@ -16,7 +16,8 @@ securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ @@ -2517,7 +2576,7 @@ if HAVE_LIBSELINUX AM_CFLAGS += -D"WITH_SELINUX" -@@ -34,9 +35,9 @@ +@@ -34,9 +35,9 @@ endif securelib_LTLIBRARIES = pam_unix.la @@ -2529,7 +2588,7 @@ noinst_PROGRAMS = bigcrypt -@@ -48,11 +49,16 @@ +@@ -48,11 +49,16 @@ bigcrypt_SOURCES = bigcrypt.c bigcrypt_m bigcrypt_CFLAGS = $(AM_CFLAGS) bigcrypt_LDFLAGS = @LIBCRYPT@ diff --git a/pam.spec b/pam.spec index bca32fa..176c1c1 100644 --- a/pam.spec +++ b/pam.spec @@ -11,7 +11,7 @@ Summary: A security tool which provides authentication for applications Name: pam Version: 0.99.8.1 -Release: 6%{?dist} +Release: 7%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+, # pam_rhosts_auth module is BSD with advertising @@ -397,6 +397,10 @@ fi %doc doc/adg/*.txt doc/adg/html %changelog +* Tue Sep 18 2007 Tomas Mraz 0.99.8.1-7 +- when SELinux enabled always run the helper binary instead of + direct shadow access (#293181) + * Fri Aug 24 2007 Tomas Mraz 0.99.8.1-6 - do not ask for blank password when SELinux confined (#254044) - initialize homedirs in namespace init script (original patch by dwalsh)