diff --git a/.cvsignore b/.cvsignore
index 8aec19f..7928361 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,5 +1,5 @@
*.src.rpm
*.tar.bz2
pam-redhat-0.99.8-1.tar.bz2
-Linux-PAM-0.99.8.1.tar.bz2
db-4.6.19.tar.gz
+Linux-PAM-0.99.10.0.tar.bz2
diff --git a/90-nproc.conf b/90-nproc.conf
new file mode 100644
index 0000000..9b57c1b
--- /dev/null
+++ b/90-nproc.conf
@@ -0,0 +1,5 @@
+# Default limit for number of user's processes to prevent
+# accidental fork bombs.
+# See rhbz #432903 for reasoning.
+
+* soft nproc 1024
diff --git a/Linux-PAM-0.99.8.1.tar.bz2.sign b/Linux-PAM-0.99.10.0.tar.bz2.sign
similarity index 61%
rename from Linux-PAM-0.99.8.1.tar.bz2.sign
rename to Linux-PAM-0.99.10.0.tar.bz2.sign
index ff2b338..ee81ed0 100644
--- a/Linux-PAM-0.99.8.1.tar.bz2.sign
+++ b/Linux-PAM-0.99.10.0.tar.bz2.sign
@@ -2,7 +2,7 @@
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: See http://www.kernel.org/signature.html for info
-iD8DBQBGneVeyGugalF9Dw4RAkclAJ4lTnGnONrVg01e1Zk5K2tfFZxhQACeITvP
-P+lEUXjXsjLVoZ1EOJn7Lts=
-=Q5X1
+iD8DBQBHtBCvyGugalF9Dw4RAkscAKCAir9EhJ5VxjIog6Vs+N6Sr27n6ACcD0Iy
+ycgdOs9Ea8z8pqgPZMmocyY=
+=djTw
-----END PGP SIGNATURE-----
diff --git a/Linux-PAM-0.99.7.1.tar.bz2.sign b/Linux-PAM-0.99.7.1.tar.bz2.sign
deleted file mode 100644
index 5fe6660..0000000
--- a/Linux-PAM-0.99.7.1.tar.bz2.sign
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-Comment: See http://www.kernel.org/signature.html for info
-
-iD8DBQBFtgDAyGugalF9Dw4RArOyAJ0duc7/WqnlX1+LfjYsUOQsJhICOgCfdWDb
-aMzAtzhCqvu+IxJTFwXx/kk=
-=I+NT
------END PGP SIGNATURE-----
diff --git a/pam-0.99.7.1-namespace-homedir.patch b/pam-0.99.7.1-namespace-homedir.patch
deleted file mode 100644
index 597bf98..0000000
--- a/pam-0.99.7.1-namespace-homedir.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.homedir Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init
---- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.homedir 2007-09-19 19:37:26.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init 2007-09-21 14:13:52.000000000 +0200
-@@ -1,26 +1,24 @@
- #!/bin/sh -p
--# This is only a boilerplate for the instance initialization script.
- # It receives polydir path as $1, the instance path as $2,
- # a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
- # and user name in $4.
- #
--# If you intend to polyinstantiate /tmp and you also want to use the X windows
--# environment, you will have to use this script to bind mount the socket that
--# is used by the X server to communicate with its clients. X server places
--# this socket in /tmp/.X11-unix directory, which will get obscured by
--# polyinstantiation. Uncommenting the following lines will bind mount
--# the relevant directory at an alternative location (/.tmp/.X11-unix) such
--# that the X server, window manager and X clients, can still find the
--# socket X0 at the polyinstanted /tmp/.X11-unix.
--#
--#if [ $1 = /tmp ]; then
--# if [ ! -f /.tmp/.X11-unix ]; then
--# mkdir -p /.tmp/.X11-unix
--# fi
--# mount --bind /tmp/.X11-unix /.tmp/.X11-unix
--# cp -fp -- /tmp/.X0-lock "$2/.X0-lock"
--# mkdir -- "$2/.X11-unix"
--# ln -fs -- /.tmp/.X11-unix/X0 "$2/.X11-unix/X0"
--#fi
-+# The following section will copy the contents of /etc/skel if this is a
-+# newly created home directory.
-+if [ "$3" = 1 ]; then
-+ # This line will fix the labeling on all newly created directories
-+ [ -x /sbin/restorecon ] && /sbin/restorecon "$1"
-+ user="$4"
-+ passwd=$(getent passwd "$user")
-+ homedir=$(echo "$passwd" | cut -f6 -d":")
-+ if [ "$1" = "$homedir" ]; then
-+ gid=$(echo "$passwd" | cut -f4 -d":")
-+ cp -rT /etc/skel "$homedir"
-+ chown -R "$user":"$gid" "$homedir"
-+ mode=$(awk '/^UMASK/{gsub("#.*$", "", $2); printf "%o", and(0777,compl(strtonum("0" $2))); exit}' /etc/login.defs)
-+ chmod ${mode:-700} "$homedir"
-+ [ -x /sbin/restorecon ] && /sbin/restorecon -R "$homedir"
-+ fi
-+fi
-
- exit 0
diff --git a/pam-0.99.7.1-namespace-temp-logon.patch b/pam-0.99.7.1-namespace-temp-logon.patch
deleted file mode 100644
index f42ae0f..0000000
--- a/pam-0.99.7.1-namespace-temp-logon.patch
+++ /dev/null
@@ -1,465 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml
---- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml.temp-logon 2007-06-18 12:46:47.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.conf.5.xml 2007-08-06 13:16:56.000000000 +0200
-@@ -72,10 +72,13 @@
-
-
- The third field, method, is the method
-- used for polyinstantiation. It can take 3 different values; "user"
-+ used for polyinstantiation. It can take these values; "user"
- for polyinstantiation based on user name, "level" for
-- polyinstantiation based on process MLS level and user name, and "context" for
-- polyinstantiation based on process security context and user name
-+ polyinstantiation based on process MLS level and user name, "context" for
-+ polyinstantiation based on process security context and user name,
-+ "tmpfs" for mounting tmpfs filesystem as an instance dir, and
-+ "tmpdir" for creating temporary directory as an instance dir which is
-+ removed when the user's session is closed.
- Methods "context" and "level" are only available with SELinux. This
- field cannot be blank.
-
-@@ -84,7 +87,8 @@
- The fourth field, list_of_uids, is
- a comma separated list of user names for whom the polyinstantiation
- is not performed. If left blank, polyinstantiation will be performed
-- for all users.
-+ for all users. If the list is preceded with a single "~" character,
-+ polyinstantiation is performed only for users in the list.
-
-
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h
---- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h.temp-logon 2007-06-18 12:46:47.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.h 2007-08-06 11:41:46.000000000 +0200
-@@ -90,6 +90,7 @@
- #define PAMNS_NO_UNMOUNT_ON_CLOSE 0x00010000 /* no unmount at session close */
-
- #define NAMESPACE_MAX_DIR_LEN 80
-+#define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data"
-
- /*
- * Polyinstantiation method options, based on user, security context
-@@ -100,6 +101,8 @@ enum polymethod {
- USER,
- CONTEXT,
- LEVEL,
-+ TMPDIR,
-+ TMPFS
- };
-
- /*
-@@ -128,6 +131,7 @@ struct polydir_s {
- enum polymethod method; /* method used to polyinstantiate */
- unsigned int num_uids; /* number of override uids */
- uid_t *uid; /* list of override uids */
-+ int exclusive; /* polyinstatiate exclusively for override uids */
- struct polydir_s *next; /* pointer to the next polydir entry */
- };
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.temp-logon Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c
---- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.temp-logon 2007-06-18 12:46:47.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c 2007-08-06 11:41:46.000000000 +0200
-@@ -43,6 +43,7 @@ static int copy_ent(const struct polydir
- strcpy(pent->instance_prefix, ent->instance_prefix);
- pent->method = ent->method;
- pent->num_uids = ent->num_uids;
-+ pent->exclusive = ent->exclusive;
- if (ent->num_uids) {
- uid_t *pptr, *eptr;
-
-@@ -120,6 +121,10 @@ static void del_polydir_list(struct poly
- }
- }
-
-+static void cleanup_data(pam_handle_t *pamh, void *data, int err)
-+{
-+ del_polydir_list(data);
-+}
-
- /*
- * Called from parse_config_file, this function processes a single line
-@@ -140,6 +145,7 @@ static int process_line(char *line, cons
-
- poly.uid = NULL;
- poly.num_uids = 0;
-+ poly.exclusive = 0;
-
- /*
- * skip the leading white space
-@@ -223,24 +229,13 @@ static int process_line(char *line, cons
- }
-
- /*
-- * Ensure that all pathnames are absolute path names.
-- */
-- if ((dir[0] != '/') || (instance_prefix[0] != '/')) {
-- pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must start with '/'");
-- goto skipping;
-- }
-- if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
-- pam_syslog(idata->pamh, LOG_NOTICE,"Pathnames must not contain '..'");
-- goto skipping;
-- }
--
-- /*
- * Populate polyinstantiated directory structure with appropriate
- * pathnames and the method with which to polyinstantiate.
- */
- if (strlen(dir) >= sizeof(poly.dir)
- || strlen(instance_prefix) >= sizeof(poly.instance_prefix)) {
- pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
-+ goto skipping;
- }
- strcpy(poly.dir, dir);
- strcpy(poly.instance_prefix, instance_prefix);
-@@ -248,6 +243,18 @@ static int process_line(char *line, cons
- poly.method = NONE;
- if (strcmp(method, "user") == 0)
- poly.method = USER;
-+
-+ if (strcmp(method, "tmpdir") == 0) {
-+ poly.method = TMPDIR;
-+ if (sizeof(poly.instance_prefix) - strlen(poly.instance_prefix) < 7) {
-+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long");
-+ goto skipping;
-+ }
-+ strcat(poly.instance_prefix, "XXXXXX");
-+ }
-+
-+ if (strcmp(method, "tmpfs") == 0)
-+ poly.method = TMPFS;
-
- #ifdef WITH_SELINUX
- if (strcmp(method, "level") == 0) {
-@@ -266,12 +273,24 @@ static int process_line(char *line, cons
-
- #endif
-
-- if ( poly.method == NONE) {
-+ if (poly.method == NONE) {
- pam_syslog(idata->pamh, LOG_NOTICE, "Illegal method");
- goto skipping;
- }
-
- /*
-+ * Ensure that all pathnames are absolute path names.
-+ */
-+ if ((dir[0] != '/') || (poly.method != TMPFS && instance_prefix[0] != '/')) {
-+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must start with '/'");
-+ goto skipping;
-+ }
-+ if (strstr(dir, "..") || strstr(instance_prefix, "..")) {
-+ pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must not contain '..'");
-+ goto skipping;
-+ }
-+
-+ /*
- * If the line in namespace.conf for a directory to polyinstantiate
- * contains a list of override users (users for whom polyinstantiation
- * is not performed), read the user ids, convert names into uids, and
-@@ -281,7 +300,11 @@ static int process_line(char *line, cons
- uid_t *uidptr;
- const char *ustr, *sstr;
- int count, i;
--
-+
-+ if (*uids == '~') {
-+ poly.exclusive = 1;
-+ uids++;
-+ }
- for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++)
- sstr = strchr(ustr, ',');
-
-@@ -419,6 +442,7 @@ static int parse_config_file(struct inst
- * directory's list of override uids. If the uid is one of the override
- * uids for the polyinstantiated directory, polyinstantiation is not
- * performed for that user for that directory.
-+ * If exclusive is set the returned values are opposite.
- */
- static int ns_override(struct polydir_s *polyptr, struct instance_data *idata,
- uid_t uid)
-@@ -432,11 +456,11 @@ static int ns_override(struct polydir_s
-
- for (i = 0; i < polyptr->num_uids; i++) {
- if (uid == polyptr->uid[i]) {
-- return 1;
-+ return !polyptr->exclusive;
- }
- }
-
-- return 0;
-+ return polyptr->exclusive;
- }
-
- /*
-@@ -622,6 +646,12 @@ static int poly_name(const struct polydi
-
- #endif /* WITH_SELINUX */
-
-+ case TMPDIR:
-+ case TMPFS:
-+ if ((*i_name=strdup("")) == NULL)
-+ goto fail;
-+ return PAM_SUCCESS;
-+
- default:
- if (idata->flags & PAMNS_DEBUG)
- pam_syslog(idata->pamh, LOG_ERR, "Unknown method");
-@@ -725,7 +755,7 @@ static int check_inst_parent(char *ipath
- * execute it and pass directory to polyinstantiate and instance
- * directory as arguments.
- */
--static int inst_init(const struct polydir_s *polyptr, char *ipath,
-+static int inst_init(const struct polydir_s *polyptr, const char *ipath,
- struct instance_data *idata)
- {
- pid_t rc, pid;
-@@ -791,11 +821,11 @@ out:
- * Create polyinstantiated instance directory (ipath).
- */
- #ifdef WITH_SELINUX
--static int create_dirs(const struct polydir_s *polyptr, char *ipath,
-+static int create_dirs(struct polydir_s *polyptr, char *ipath,
- security_context_t icontext, security_context_t ocontext,
- struct instance_data *idata)
- #else
--static int create_dirs(const struct polydir_s *polyptr, char *ipath,
-+static int create_dirs(struct polydir_s *polyptr, char *ipath,
- struct instance_data *idata)
- #endif
- {
-@@ -834,7 +864,17 @@ static int create_dirs(const struct poly
- * attributes to match that of the original directory that is being
- * polyinstantiated.
- */
-- if (mkdir(ipath, S_IRUSR) < 0) {
-+
-+ if (polyptr->method == TMPDIR) {
-+ if (mkdtemp(polyptr->instance_prefix) == NULL) {
-+ pam_syslog(idata->pamh, LOG_ERR, "Error creating temporary instance %s, %m",
-+ polyptr->instance_prefix);
-+ polyptr->method = NONE; /* do not clean up! */
-+ return PAM_SESSION_ERR;
-+ }
-+ /* copy the actual directory name to ipath */
-+ strcpy(ipath, polyptr->instance_prefix);
-+ } else if (mkdir(ipath, S_IRUSR) < 0) {
- if (errno == EEXIST)
- goto inst_init;
- else {
-@@ -920,13 +960,12 @@ inst_init:
- * security attributes, and performs bind mount to setup the process
- * namespace.
- */
--static int ns_setup(const struct polydir_s *polyptr,
-+static int ns_setup(struct polydir_s *polyptr,
- struct instance_data *idata)
- {
- int retval = 0;
- char *inst_dir = NULL;
- char *instname = NULL;
-- char *dir;
- #ifdef WITH_SELINUX
- security_context_t instcontext = NULL, origcontext = NULL;
- #endif
-@@ -935,9 +974,15 @@ static int ns_setup(const struct polydir
- pam_syslog(idata->pamh, LOG_DEBUG,
- "Set namespace for directory %s", polyptr->dir);
-
-- dir = strrchr(polyptr->dir, '/');
-- if (dir && strlen(dir) > 1)
-- dir++;
-+ if (polyptr->method == TMPFS) {
-+ if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) {
-+ pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
-+ polyptr->dir);
-+ return PAM_SESSION_ERR;
-+ }
-+ /* we must call inst_init after the mount in this case */
-+ return inst_init(polyptr, "tmpfs", idata);
-+ }
-
- /*
- * Obtain the name of instance pathname based on the
-@@ -1043,6 +1088,58 @@ static int cwd_in(char *dir, struct inst
- return retval;
- }
-
-+static int cleanup_tmpdirs(struct instance_data *idata)
-+{
-+ struct polydir_s *pptr;
-+ pid_t rc, pid;
-+ sighandler_t osighand = NULL;
-+ int status;
-+
-+ osighand = signal(SIGCHLD, SIG_DFL);
-+ if (osighand == SIG_ERR) {
-+ pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
-+ rc = PAM_SESSION_ERR;
-+ goto out;
-+ }
-+
-+ for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) {
-+ if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) {
-+ pid = fork();
-+ if (pid == 0) {
-+#ifdef WITH_SELINUX
-+ if (idata->flags & PAMNS_SELINUX_ENABLED) {
-+ if (setexeccon(NULL) < 0)
-+ exit(1);
-+ }
-+#endif
-+ if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0)
-+ exit(1);
-+ } else if (pid > 0) {
-+ while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
-+ (errno == EINTR));
-+ if (rc == (pid_t)-1) {
-+ pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
-+ rc = PAM_SESSION_ERR;
-+ goto out;
-+ }
-+ if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
-+ pam_syslog(idata->pamh, LOG_ERR,
-+ "Error removing %s", pptr->instance_prefix);
-+ }
-+ } else if (pid < 0) {
-+ pam_syslog(idata->pamh, LOG_ERR,
-+ "Cannot fork to run namespace init script, %m");
-+ rc = PAM_SESSION_ERR;
-+ goto out;
-+ }
-+ }
-+ }
-+
-+ rc = PAM_SUCCESS;
-+out:
-+ signal(SIGCHLD, osighand);
-+ return rc;
-+}
-
- /*
- * This function checks to see if polyinstantiation is needed for any
-@@ -1111,13 +1208,22 @@ static int setup_namespace(struct instan
- * disassociate from the parent namespace.
- */
- if (need_poly) {
-+ if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr,
-+ cleanup_data) != PAM_SUCCESS) {
-+ pam_syslog(idata->pamh, LOG_ERR,
-+ "Unable to set namespace data");
-+ return PAM_SYSTEM_ERR;
-+ }
- if (unshare(CLONE_NEWNS) < 0) {
-- pam_syslog(idata->pamh, LOG_ERR,
-+ pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
-+ pam_syslog(idata->pamh, LOG_ERR,
- "Unable to unshare from parent namespace, %m");
- return PAM_SESSION_ERR;
- }
-- } else
-+ } else {
-+ del_polydir_list(idata->polydirs_ptr);
- return PAM_SUCCESS;
-+ }
-
- /*
- * Again cycle through all polyinstantiated directories, this time,
-@@ -1144,7 +1250,8 @@ static int setup_namespace(struct instan
- * umount
- */
- if ((changing_dir = cwd_in(pptr->dir, idata)) < 0) {
-- return PAM_SESSION_ERR;
-+ retval = PAM_SESSION_ERR;
-+ goto out;
- } else if (changing_dir) {
- if (idata->flags & PAMNS_DEBUG)
- pam_syslog(idata->pamh, LOG_DEBUG, "changing cwd");
-@@ -1172,8 +1279,10 @@ static int setup_namespace(struct instan
- int saved_errno = errno;
- pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m",
- pptr->dir);
-- if (saved_errno != EINVAL)
-- return PAM_SESSION_ERR;
-+ if (saved_errno != EINVAL) {
-+ retval = PAM_SESSION_ERR;
-+ goto out;
-+ }
- } else if (idata->flags & PAMNS_DEBUG)
- pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s",
- pptr->dir);
-@@ -1185,7 +1294,9 @@ static int setup_namespace(struct instan
- break;
- }
- }
--
-+out:
-+ if (retval != PAM_SUCCESS)
-+ cleanup_tmpdirs(idata);
- return retval;
- }
-
-@@ -1224,8 +1335,10 @@ static int orig_namespace(struct instanc
- } else if (idata->flags & PAMNS_DEBUG)
- pam_syslog(idata->pamh, LOG_DEBUG, "Unmount of %s succeeded",
- pptr->dir);
-- }
-+ }
- }
-+
-+ cleanup_tmpdirs(idata);
- return 0;
- }
-
-@@ -1350,7 +1463,8 @@ PAM_EXTERN int pam_sm_open_session(pam_h
- } else if (idata.flags & PAMNS_DEBUG)
- pam_syslog(idata.pamh, LOG_DEBUG, "Nothing to polyinstantiate");
-
-- del_polydir_list(idata.polydirs_ptr);
-+ if (retval != PAM_SUCCESS)
-+ del_polydir_list(idata.polydirs_ptr);
- return retval;
- }
-
-@@ -1365,6 +1479,7 @@ PAM_EXTERN int pam_sm_close_session(pam_
- struct instance_data idata;
- char *user_name;
- struct passwd *pwd;
-+ const void *polyptr;
-
- /* init instance data */
- idata.flags = 0;
-@@ -1428,16 +1543,12 @@ PAM_EXTERN int pam_sm_close_session(pam_
- strncat(idata.user, user_name, sizeof(idata.user) - 1);
- idata.uid = pwd->pw_uid;
-
-- /*
-- * Parse namespace configuration file which lists directories that
-- * are polyinstantiated, directories where instance directories are
-- * created and the method used for polyinstantiation.
-- */
-- retval = parse_config_file(&idata);
-- if ((retval != PAM_SUCCESS) || !idata.polydirs_ptr) {
-- del_polydir_list(idata.polydirs_ptr);
-- return PAM_SESSION_ERR;
-- }
-+ retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, &polyptr);
-+ if (retval != PAM_SUCCESS || polyptr == NULL)
-+ /* nothing to reset */
-+ return PAM_SUCCESS;
-+
-+ idata.polydirs_ptr = polyptr;
-
- if (idata.flags & PAMNS_DEBUG)
- pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d",
-@@ -1452,7 +1563,9 @@ PAM_EXTERN int pam_sm_close_session(pam_
- pam_syslog(idata.pamh, LOG_DEBUG,
- "resetting namespace ok for pid %d", getpid());
- }
-- del_polydir_list(idata.polydirs_ptr);
-+
-+ pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL);
-+
- return PAM_SUCCESS;
- }
-
diff --git a/pam-0.99.8.1-audit-failed.patch b/pam-0.99.8.1-audit-failed.patch
deleted file mode 100644
index 33580b1..0000000
--- a/pam-0.99.8.1-audit-failed.patch
+++ /dev/null
@@ -1,838 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed Linux-PAM-0.99.8.1/libpam/libpam.map
---- Linux-PAM-0.99.8.1/libpam/libpam.map.audit-failed 2006-06-14 17:28:44.000000000 +0200
-+++ Linux-PAM-0.99.8.1/libpam/libpam.map 2008-01-22 22:24:05.000000000 +0100
-@@ -45,3 +45,7 @@ LIBPAM_MODUTIL_1.0 {
- pam_modutil_read;
- pam_modutil_write;
- };
-+LIBPAM_MODUTIL_1.1 {
-+ global:
-+ pam_modutil_audit_write;
-+} LIBPAM_MODUTIL_1.0;
-diff -up Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed Linux-PAM-0.99.8.1/libpam/pam_audit.c
---- Linux-PAM-0.99.8.1/libpam/pam_audit.c.audit-failed 2008-01-22 22:24:05.000000000 +0100
-+++ Linux-PAM-0.99.8.1/libpam/pam_audit.c 2008-01-22 22:24:05.000000000 +0100
-@@ -42,39 +42,53 @@ _pam_audit_writelog(pam_handle_t *pamh,
- best to fix it. */
- errno = -rc;
-
-+ if (rc < 0 && errno != old_errno)
-+ {
-+ old_errno = errno;
-+ pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
-+ }
-+
- pamh->audit_state |= PAMAUDIT_LOGGED;
-
-- if (rc < 0) {
-- if (rc == -EPERM && getuid() != 0)
-- return 0;
-- if (errno != old_errno) {
-- old_errno = errno;
-- pam_syslog (pamh, LOG_CRIT, "audit_log_acct_message() failed: %m");
-- }
-- }
-- return rc;
-+ if (rc == -EPERM && getuid () != 0)
-+ return 0;
-+ else
-+ return rc;
- }
-
--int
--_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
-+static int
-+_pam_audit_open(pam_handle_t *pamh)
- {
-- const char *message;
-- int type;
- int audit_fd;
--
- audit_fd = audit_open();
- if (audit_fd < 0) {
- /* You get these error codes only when the kernel doesn't have
- * audit compiled in. */
- if (errno == EINVAL || errno == EPROTONOSUPPORT ||
- errno == EAFNOSUPPORT)
-- return retval;
-+ return -2;
-
- /* this should only fail in case of extreme resource shortage,
- * need to prevent login in that case for CAPP compliance.
- */
- pam_syslog(pamh, LOG_CRIT, "audit_open() failed: %m");
-+ return -1;
-+ }
-+
-+ return audit_fd;
-+}
-+
-+int
-+_pam_auditlog(pam_handle_t *pamh, int action, int retval, int flags)
-+{
-+ const char *message;
-+ int type;
-+ int audit_fd;
-+
-+ if ((audit_fd=_pam_audit_open(pamh)) == -1) {
- return PAM_SYSTEM_ERR;
-+ } else if (audit_fd == -2) {
-+ return retval;
- }
-
- switch (action) {
-@@ -141,4 +155,30 @@ _pam_audit_end(pam_handle_t *pamh, int s
- return 0;
- }
-
-+int
-+pam_modutil_audit_write(pam_handle_t *pamh, int type,
-+ const char *message, int retval)
-+{
-+ int audit_fd;
-+ int rc;
-+
-+ if ((audit_fd=_pam_audit_open(pamh)) == -1) {
-+ return PAM_SYSTEM_ERR;
-+ } else if (audit_fd == -2) {
-+ return retval;
-+ }
-+
-+ rc = _pam_audit_writelog(pamh, audit_fd, type, message, retval);
-+
-+ audit_close(audit_fd);
-+
-+ return rc < 0 ? PAM_SYSTEM_ERR : PAM_SUCCESS;
-+}
-+
-+#else
-+int pam_modutil_audit_write(pam_handle_t *pamh UNUSED, int type UNUSED,
-+ const char *message UNUSED, int retval UNUSED)
-+{
-+ return PAM_SUCCESS;
-+}
- #endif /* HAVE_LIBAUDIT */
-diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml
---- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml.audit-failed 2007-06-22 10:03:29.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.8.xml 2008-01-22 22:24:05.000000000 +0100
-@@ -29,6 +29,9 @@
- nodefgroup
-
-
-+ noaudit
-+
-+
- accessfile=file
-
-
-@@ -54,6 +57,10 @@
- /etc/security/access.conf if you don't specify
- another file.
-
-+
-+ If Linux PAM is compiled with audit support the module will report
-+ when it denies access based on origin (host or tty).
-+
-
-
-
-@@ -87,6 +94,17 @@
-
-
-
-+
-+
-+
-+
-+ Do not report logins from disallowed hosts and ttys to the audit subsystem.
-+
-+
-+
-+
-+
-+
-
-
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c
---- Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c.audit-failed 2007-06-25 11:59:11.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_access/pam_access.c 2008-01-22 22:24:05.000000000 +0100
-@@ -46,6 +46,10 @@
- #include
- #include
-
-+#ifdef HAVE_LIBAUDIT
-+#include
-+#endif
-+
- /*
- * here, we make definitions for the externally accessible functions
- * in this file (these definitions are required for static modules
-@@ -81,17 +85,11 @@
-
- /* Delimiters for fields and for lists of users, ttys or hosts. */
-
--static const char *fs = ":"; /* field separator */
--static const char *sep = ", \t"; /* list-element separator */
--
-- /* Constants to be used in assignments only, not in comparisons... */
-
-+#define ALL 2
- #define YES 1
- #define NO 0
-
--/* Only allow group entries of the form "(xyz)" */
--static int only_new_group_syntax = NO;
--
- /*
- * A structure to bundle up all login-related information to keep the
- * functional interfaces as generic as possible.
-@@ -100,12 +98,13 @@ struct login_info {
- const struct passwd *user;
- const char *from;
- const char *config_file;
-+ int debug; /* Print debugging messages. */
-+ int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
-+ int noaudit; /* Do not audit denials */
-+ const char *fs; /* field separator */
-+ const char *sep; /* list-element separator */
- };
-
--/* Print debugging messages.
-- Default is NO which means don't print debugging messages. */
--static char pam_access_debug = NO;
--
- /* Parse module config arguments */
-
- static int
-@@ -113,17 +112,22 @@ parse_args(pam_handle_t *pamh, struct lo
- int argc, const char **argv)
- {
- int i;
--
-+
-+ loginfo->noaudit = NO;
-+ loginfo->debug = NO;
-+ loginfo->only_new_group_syntax = NO;
-+ loginfo->fs = ":";
-+ loginfo->sep = ", \t";
- for (i=0; ifs = argv[i]+9;
-
- } else if (!strncmp("listsep=", argv[i], 8)) {
-
- /* the admin wants to override the default list separators */
-- sep = argv[i]+8;
-+ loginfo->sep = argv[i]+8;
-
- } else if (!strncmp("accessfile=", argv[i], 11)) {
- FILE *fp = fopen(11 + argv[i], "r");
-@@ -138,9 +142,11 @@ parse_args(pam_handle_t *pamh, struct lo
- }
-
- } else if (strcmp (argv[i], "debug") == 0) {
-- pam_access_debug = YES;
-+ loginfo->debug = YES;
- } else if (strcmp (argv[i], "nodefgroup") == 0) {
-- only_new_group_syntax = YES;
-+ loginfo->only_new_group_syntax = YES;
-+ } else if (strcmp (argv[i], "noaudit") == 0) {
-+ loginfo->noaudit = YES;
- } else {
- pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
- }
-@@ -153,13 +159,13 @@ parse_args(pam_handle_t *pamh, struct lo
-
- typedef int match_func (pam_handle_t *, char *, struct login_info *);
-
--static int list_match (pam_handle_t *, char *, struct login_info *,
-+static int list_match (pam_handle_t *, char *, char *, struct login_info *,
- match_func *);
- static int user_match (pam_handle_t *, char *, struct login_info *);
--static int group_match (pam_handle_t *, const char *, const char *);
-+static int group_match (pam_handle_t *, const char *, const char *, int);
- static int from_match (pam_handle_t *, char *, struct login_info *);
--static int string_match (pam_handle_t *, const char *, const char *);
--static int network_netmask_match (pam_handle_t *, const char *, const char *);
-+static int string_match (pam_handle_t *, const char *, const char *, int);
-+static int network_netmask_match (pam_handle_t *, const char *, const char *, int);
-
-
- /* isipaddr - find out if string provided is an IP address or not */
-@@ -325,11 +331,12 @@ login_access (pam_handle_t *pamh, struct
- char *users; /* becomes list of login names */
- char *froms; /* becomes list of terminals or hosts */
- int match = NO;
-+ int nonall_match = NO;
- int end;
- int lineno = 0; /* for diagnostics */
- char *sptr;
-
-- if (pam_access_debug)
-+ if (item->debug)
- pam_syslog (pamh, LOG_DEBUG,
- "login_access: user=%s, from=%s, file=%s",
- item->user->pw_name,
-@@ -361,8 +368,8 @@ login_access (pam_handle_t *pamh, struct
- continue;
-
- /* Allow field seperator in last field of froms */
-- if (!(perm = strtok_r(line, fs, &sptr))
-- || !(users = strtok_r(NULL, fs, &sptr))
-+ if (!(perm = strtok_r(line, item->fs, &sptr))
-+ || !(users = strtok_r(NULL, item->fs, &sptr))
- || !(froms = strtok_r(NULL, "\n", &sptr))) {
- pam_syslog(pamh, LOG_ERR, "%s: line %d: bad field count",
- item->config_file, lineno);
-@@ -373,17 +380,22 @@ login_access (pam_handle_t *pamh, struct
- item->config_file, lineno);
- continue;
- }
-- if (pam_access_debug)
-+ if (item->debug)
- pam_syslog (pamh, LOG_DEBUG,
- "line %d: %s : %s : %s", lineno, perm, users, froms);
-- match = list_match(pamh, froms, item, from_match);
-- if (pam_access_debug)
-- pam_syslog (pamh, LOG_DEBUG,
-- "from_match=%d, \"%s\"", match, item->from);
-- match = match && list_match (pamh, users, item, user_match);
-- if (pam_access_debug)
-+ match = list_match(pamh, users, NULL, item, user_match);
-+ if (item->debug)
- pam_syslog (pamh, LOG_DEBUG, "user_match=%d, \"%s\"",
- match, item->user->pw_name);
-+ if (match) {
-+ match = list_match(pamh, froms, NULL, item, from_match);
-+ if (!match && perm[0] == '+') {
-+ nonall_match = YES;
-+ }
-+ if (item->debug)
-+ pam_syslog (pamh, LOG_DEBUG,
-+ "from_match=%d, \"%s\"", match, item->from);
-+ }
- }
- (void) fclose(fp);
- } else if (errno == ENOENT) {
-@@ -394,20 +406,27 @@ login_access (pam_handle_t *pamh, struct
- pam_syslog(pamh, LOG_ERR, "cannot open %s: %m", item->config_file);
- return NO;
- }
-+#ifdef HAVE_LIBAUDIT
-+ if (!item->noaudit && line[0] == '-' && (match == YES || (match == ALL &&
-+ nonall_match == YES))) {
-+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_LOCATION,
-+ "pam_access", 0);
-+ }
-+#endif
- return (match == NO || (line[0] == '+'));
- }
-
-
- /* list_match - match an item against a list of tokens with exceptions */
-
--static int list_match(pam_handle_t *pamh,
-- char *list, struct login_info *item, match_func *match_fn)
-+static int
-+list_match(pam_handle_t *pamh, char *list, char *sptr,
-+ struct login_info *item, match_func *match_fn)
- {
- char *tok;
- int match = NO;
-- char *sptr;
-
-- if (pam_access_debug)
-+ if (item->debug && list != NULL)
- pam_syslog (pamh, LOG_DEBUG,
- "list_match: list=%s, item=%s", list, item->user->pw_name);
-
-@@ -418,8 +437,8 @@ static int list_match(pam_handle_t *pamh
- * the match is affected by any exceptions.
- */
-
-- for (tok = strtok_r(list, sep, &sptr); tok != 0;
-- tok = strtok_r(NULL, sep, &sptr)) {
-+ for (tok = strtok_r(list, item->sep, &sptr); tok != 0;
-+ tok = strtok_r(NULL, item->sep, &sptr)) {
- if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
- break;
- if ((match = (*match_fn) (pamh, tok, item))) /* YES */
-@@ -428,10 +447,12 @@ static int list_match(pam_handle_t *pamh
- /* Process exceptions to matches. */
-
- if (match != NO) {
-- while ((tok = strtok_r(NULL, sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
-+ while ((tok = strtok_r(NULL, item->sep, &sptr)) && strcasecmp(tok, "EXCEPT"))
- /* VOID */ ;
-- if (tok == 0 || list_match(pamh, sptr, item, match_fn) == NO)
-- return (match);
-+ if (tok == 0)
-+ return match;
-+ if (list_match(pamh, NULL, sptr, item, match_fn) == NO)
-+ return YES; /* drop special meaning of ALL */
- }
- return (NO);
- }
-@@ -453,7 +474,7 @@ static char *myhostname(void)
-
- static int
- netgroup_match (pam_handle_t *pamh, const char *netgroup,
-- const char *machine, const char *user)
-+ const char *machine, const char *user, int debug)
- {
- char *mydomain = NULL;
- int retval;
-@@ -462,7 +483,7 @@ netgroup_match (pam_handle_t *pamh, cons
-
-
- retval = innetgr (netgroup, machine, user, mydomain);
-- if (pam_access_debug == YES)
-+ if (debug == YES)
- pam_syslog (pamh, LOG_DEBUG,
- "netgroup_match: %d (netgroup=%s, machine=%s, user=%s, domain=%s)",
- retval, netgroup ? netgroup : "NULL",
-@@ -480,8 +501,9 @@ user_match (pam_handle_t *pamh, char *to
- char *string = item->user->pw_name;
- struct login_info fake_item;
- char *at;
-+ int rv;
-
-- if (pam_access_debug)
-+ if (item->debug)
- pam_syslog (pamh, LOG_DEBUG,
- "user_match: tok=%s, item=%s", tok, string);
-
-@@ -500,12 +522,12 @@ user_match (pam_handle_t *pamh, char *to
- return (user_match (pamh, tok, item) &&
- from_match (pamh, at + 1, &fake_item));
- } else if (tok[0] == '@') /* netgroup */
-- return (netgroup_match (pamh, tok + 1, (char *) 0, string));
-+ return (netgroup_match (pamh, tok + 1, (char *) 0, string, item->debug));
- else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')')
-- return (group_match (pamh, tok, string));
-- else if (string_match (pamh, tok, string)) /* ALL or exact match */
-- return YES;
-- else if (only_new_group_syntax == NO &&
-+ return (group_match (pamh, tok, string, item->debug));
-+ else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
-+ return rv;
-+ else if (item->only_new_group_syntax == NO &&
- pam_modutil_user_in_group_nam_nam (pamh,
- item->user->pw_name, tok))
- /* try group membership */
-@@ -518,11 +540,12 @@ user_match (pam_handle_t *pamh, char *to
- /* group_match - match a username against token named group */
-
- static int
--group_match (pam_handle_t *pamh, const char *tok, const char* usr)
-+group_match (pam_handle_t *pamh, const char *tok, const char* usr,
-+ int debug)
- {
- char grptok[BUFSIZ];
-
-- if (pam_access_debug)
-+ if (debug)
- pam_syslog (pamh, LOG_DEBUG,
- "group_match: grp=%s, user=%s", grptok, usr);
-
-@@ -548,8 +571,9 @@ from_match (pam_handle_t *pamh UNUSED, c
- const char *string = item->from;
- int tok_len;
- int str_len;
-+ int rv;
-
-- if (pam_access_debug)
-+ if (item->debug)
- pam_syslog (pamh, LOG_DEBUG,
- "from_match: tok=%s, item=%s", tok, string);
-
-@@ -565,10 +589,10 @@ from_match (pam_handle_t *pamh UNUSED, c
- if (string == NULL) {
- return NO;
- } else if (tok[0] == '@') { /* netgroup */
-- return (netgroup_match (pamh, tok + 1, string, (char *) 0));
-- } else if (string_match(pamh, tok, string)) {
-+ return (netgroup_match (pamh, tok + 1, string, (char *) 0, item->debug));
-+ } else if ((rv = string_match(pamh, tok, string, item->debug)) != NO) {
- /* ALL or exact match */
-- return (YES);
-+ return rv;
- } else if (tok[0] == '.') { /* domain: match last fields */
- if ((str_len = strlen(string)) > (tok_len = strlen(tok))
- && strcasecmp(tok, string + str_len - tok_len) == 0)
-@@ -614,7 +638,7 @@ from_match (pam_handle_t *pamh UNUSED, c
- }
- } else if (isipaddr(string, NULL, NULL) == YES) {
- /* Assume network/netmask with a IP of a host. */
-- if (network_netmask_match(pamh, tok, string))
-+ if (network_netmask_match(pamh, tok, string, item->debug))
- return YES;
- } else {
- /* Assume network/netmask with a name of a host. */
-@@ -641,7 +665,7 @@ from_match (pam_handle_t *pamh UNUSED, c
- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
- buf, sizeof (buf));
-
-- if (network_netmask_match(pamh, tok, buf))
-+ if (network_netmask_match(pamh, tok, buf, item->debug))
- {
- freeaddrinfo (res);
- return YES;
-@@ -658,10 +682,11 @@ from_match (pam_handle_t *pamh UNUSED, c
- /* string_match - match a string against one token */
-
- static int
--string_match (pam_handle_t *pamh, const char *tok, const char *string)
-+string_match (pam_handle_t *pamh, const char *tok, const char *string,
-+ int debug)
- {
-
-- if (pam_access_debug)
-+ if (debug)
- pam_syslog (pamh, LOG_DEBUG,
- "string_match: tok=%s, item=%s", tok, string);
-
-@@ -672,7 +697,7 @@ string_match (pam_handle_t *pamh, const
- */
-
- if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
-- return (YES);
-+ return (ALL);
- } else if (string != NULL) {
- if (strcasecmp(tok, string) == 0) { /* try exact match */
- return (YES);
-@@ -690,9 +715,9 @@ string_match (pam_handle_t *pamh, const
- */
- static int
- network_netmask_match (pam_handle_t *pamh,
-- const char *tok, const char *string)
-+ const char *tok, const char *string, int debug)
- {
-- if (pam_access_debug)
-+ if (debug)
- pam_syslog (pamh, LOG_DEBUG,
- "network_netmask_match: tok=%s, item=%s", tok, string);
-
-@@ -771,6 +796,22 @@ pam_sm_authenticate (pam_handle_t *pamh,
- return PAM_USER_UNKNOWN;
- }
-
-+ if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
-+ return (PAM_USER_UNKNOWN);
-+
-+ /*
-+ * Bundle up the arguments to avoid unnecessary clumsiness later on.
-+ */
-+ loginfo.user = user_pw;
-+ loginfo.config_file = PAM_ACCESS_CONFIG;
-+
-+ /* parse the argument list */
-+
-+ if (!parse_args(pamh, &loginfo, argc, argv)) {
-+ pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
-+ return PAM_ABORT;
-+ }
-+
- /* remote host name */
-
- if (pam_get_item(pamh, PAM_RHOST, &void_from)
-@@ -799,7 +840,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
- return PAM_ABORT;
- }
- from = void_from;
-- if (pam_access_debug)
-+ if (loginfo.debug)
- pam_syslog (pamh, LOG_DEBUG,
- "cannot determine tty or remote hostname, using service %s",
- from);
-@@ -817,22 +858,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
- }
- }
-
-- if ((user_pw=pam_modutil_getpwnam(pamh, user))==NULL)
-- return (PAM_USER_UNKNOWN);
--
-- /*
-- * Bundle up the arguments to avoid unnecessary clumsiness later on.
-- */
-- loginfo.user = user_pw;
- loginfo.from = from;
-- loginfo.config_file = PAM_ACCESS_CONFIG;
--
-- /* parse the argument list */
--
-- if (!parse_args(pamh, &loginfo, argc, argv)) {
-- pam_syslog(pamh, LOG_ERR, "failed to parse the module arguments");
-- return PAM_ABORT;
-- }
-
- if (login_access(pamh, &loginfo)) {
- return (PAM_SUCCESS);
-diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c
---- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c.audit-failed 2006-06-16 08:35:16.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.c 2008-01-22 22:24:05.000000000 +0100
-@@ -22,9 +22,16 @@
- #include
- #include
-
-+#ifdef HAVE_LIBAUDIT
-+#include
-+#endif
-+
- #define PAM_TIME_BUFLEN 1000
- #define FIELD_SEPARATOR ';' /* this is new as of .02 */
-
-+#define PAM_DEBUG_ARG 0x0001
-+#define PAM_NO_AUDIT 0x0002
-+
- #ifndef TRUE
- # define TRUE 1
- #endif
-@@ -46,6 +53,29 @@ typedef enum { AND, OR } operator;
- #include
- #include
- #include
-+#include
-+
-+static int
-+_pam_parse (const pam_handle_t *pamh, int argc, const char **argv)
-+{
-+ int ctrl = 0;
-+
-+ /* step through arguments */
-+ for (; argc-- > 0; ++argv) {
-+
-+ /* generic options */
-+
-+ if (!strcmp(*argv, "debug")) {
-+ ctrl |= PAM_DEBUG_ARG;
-+ } else if (!strcmp(*argv, "noaudit")) {
-+ ctrl |= PAM_NO_AUDIT;
-+ } else {
-+ pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
-+ }
-+ }
-+
-+ return ctrl;
-+}
-
- /* --- static functions for checking whether the user should be let in --- */
-
-@@ -59,7 +89,7 @@ shift_bytes(char *mem, int from, int by)
- }
-
- static int
--read_field(pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
-+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
- {
- /* is buf set ? */
-
-@@ -137,6 +167,7 @@ read_field(pam_handle_t *pamh, int fd, c
- switch ((*buf)[i]) {
- int j,c;
- case '#':
-+ c = 0;
- for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
- if (j >= *to) {
- (*buf)[*to = ++i] = '\0';
-@@ -324,6 +355,13 @@ is_same(pam_handle_t *pamh UNUSED, const
- return FALSE;
- }
- }
-+
-+ /* Ok, we know that b is a substring from A and does not contain
-+ wildcards, but now the length of both strings must be the same,
-+ too. */
-+ if (strlen (a) != strlen(b))
-+ return FALSE;
-+
- return ( !len );
- }
-
-@@ -559,11 +597,15 @@ check_account(pam_handle_t *pamh, const
-
- PAM_EXTERN int
- pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
-- int argc UNUSED, const char **argv UNUSED)
-+ int argc, const char **argv)
- {
- const void *service=NULL, *void_tty=NULL;
- const char *tty;
- const char *user=NULL;
-+ int ctrl;
-+ int rv;
-+
-+ ctrl = _pam_parse(pamh, argc, argv);
-
- /* set service name */
-
-@@ -612,7 +654,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
- D(("user=%s", user));
- D(("tty=%s", tty));
-
-- return check_account(pamh, service, tty, user);
-+ rv = check_account(pamh, service, tty, user);
-+ if (rv != PAM_SUCCESS) {
-+#ifdef HAVE_LIBAUDIT
-+ if (!(ctrl & PAM_NO_AUDIT)) {
-+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_TIME,
-+ "pam_time", rv); /* ignore return value as we fail anyway */
-+ }
-+#endif
-+ if (ctrl & PAM_DEBUG_ARG) {
-+ pam_syslog(pamh, LOG_DEBUG, "user %s rejected", user);
-+ }
-+ }
-+ return rv;
- }
-
- /* end of module definition */
-diff -up Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml
---- Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml.audit-failed 2006-06-22 21:44:30.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_time/pam_time.8.xml 2008-01-22 22:24:05.000000000 +0100
-@@ -22,6 +22,12 @@
-
-
- pam_time.so
-+
-+ debug
-+
-+
-+ noaudit
-+
-
-
-
-@@ -41,11 +47,40 @@
- By default rules for time/port access are taken from config file
- /etc/security/time.conf.
-
-+
-+ If Linux PAM is compiled with audit support the module will report
-+ when it denies access.
-+
-
-
-
- OPTIONS
-- This module does not recognice any options.
-+
-+
-+
-+
-+
-+
-+
-+
-+ Some debug informations are printed with
-+ syslog3.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Do not report logins at disallowed time to the audit subsystem.
-+
-+
-+
-+
-+
-
-
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c
---- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c.audit-failed 2007-07-10 12:10:56.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.c 2008-01-22 22:41:40.000000000 +0100
-@@ -41,6 +41,10 @@
- #include
- #include
-
-+#ifdef HAVE_LIBAUDIT
-+#include
-+#endif
-+
- /* Module defines */
- #define LINE_LENGTH 1024
-
-@@ -101,6 +105,7 @@ struct pam_limit_s {
- #define PAM_DEBUG_ARG 0x0001
- #define PAM_DO_SETREUID 0x0002
- #define PAM_UTMP_EARLY 0x0004
-+#define PAM_NO_AUDIT 0x0008
-
- /* Limits from globbed files. */
- #define LIMITS_CONF_GLOB LIMITS_FILE_DIR
-@@ -126,6 +131,8 @@ _pam_parse (const pam_handle_t *pamh, in
- ctrl |= PAM_DO_SETREUID;
- } else if (!strcmp(*argv,"utmp_early")) {
- ctrl |= PAM_UTMP_EARLY;
-+ } else if (!strcmp(*argv,"noaudit")) {
-+ ctrl |= PAM_NO_AUDIT;
- } else {
- pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
- }
-@@ -599,6 +606,13 @@ static int setup_limits(pam_handle_t *pa
- D(("skip login limit check for uid=0"));
- } else if (pl->login_limit > 0) {
- if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
-+#ifdef HAVE_LIBAUDIT
-+ if (!(ctrl & PAM_NO_AUDIT)) {
-+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_SESSIONS,
-+ "pam_limits", PAM_PERM_DENIED);
-+ /* ignore return value as we fail anyway */
-+ }
-+#endif
- retval |= LOGIN_ERR;
- }
- } else if (pl->login_limit == 0) {
-diff -up Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml
---- Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml.audit-failed 2007-04-30 12:47:26.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_limits/pam_limits.8.xml 2008-01-22 22:24:05.000000000 +0100
-@@ -34,6 +34,9 @@
-
- utmp_early
-
-+
-+ noaudit
-+
-
-
-
-@@ -57,6 +60,11 @@
-
- The module must not be called by a multithreaded application.
-
-+
-+ If Linux PAM is compiled with audit support the module will report
-+ when it denies access based on limit of maximum number of concurrent
-+ login sessions.
-+
-
-
-
-@@ -111,6 +119,16 @@
-
-
-
-+
-+
-+
-+
-+
-+
-+ Do not report exceeded maximum logins count to the audit subsystem.
-+
-+
-+
-
-
-
diff --git a/pam-0.99.8.1-namespace-init.patch b/pam-0.99.8.1-namespace-init.patch
deleted file mode 100644
index 95ce1d3..0000000
--- a/pam-0.99.8.1-namespace-init.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.ns-init Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c
---- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c.ns-init 2007-08-06 13:57:56.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.c 2007-08-06 14:06:52.000000000 +0200
-@@ -672,7 +672,7 @@ static int poly_name(const struct polydi
- hash = NULL;
- } else {
- char *newname;
-- if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-strlen(hash),
-+ if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-(int)strlen(hash),
- *i_name, hash) < 0) {
- goto fail;
- }
-@@ -756,7 +756,7 @@ static int check_inst_parent(char *ipath
- * directory as arguments.
- */
- static int inst_init(const struct polydir_s *polyptr, const char *ipath,
-- struct instance_data *idata)
-+ struct instance_data *idata, int newdir)
- {
- pid_t rc, pid;
- sighandler_t osighand = NULL;
-@@ -786,7 +786,7 @@ static int inst_init(const struct polydi
- }
- #endif
- if (execl(NAMESPACE_INIT_SCRIPT, NAMESPACE_INIT_SCRIPT,
-- polyptr->dir, ipath, (char *)NULL) < 0)
-+ polyptr->dir, ipath, newdir?"1":"0", idata->user, (char *)NULL) < 0)
- exit(1);
- } else if (pid > 0) {
- while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
-@@ -831,6 +831,7 @@ static int create_dirs(struct polydir_s
- {
- struct stat statbuf, newstatbuf;
- int rc, fd;
-+ int newdir = 0;
-
- /*
- * stat the directory to polyinstantiate, so its owner-group-mode
-@@ -884,6 +885,7 @@ static int create_dirs(struct polydir_s
- }
- }
-
-+ newdir = 1;
- /* Open a descriptor to it to prevent races */
- fd = open(ipath, O_DIRECTORY | O_RDONLY);
- if (fd < 0) {
-@@ -948,7 +950,7 @@ static int create_dirs(struct polydir_s
- */
-
- inst_init:
-- rc = inst_init(polyptr, ipath, idata);
-+ rc = inst_init(polyptr, ipath, idata, newdir);
- return rc;
- }
-
-@@ -981,7 +983,7 @@ static int ns_setup(struct polydir_s *po
- return PAM_SESSION_ERR;
- }
- /* we must call inst_init after the mount in this case */
-- return inst_init(polyptr, "tmpfs", idata);
-+ return inst_init(polyptr, "tmpfs", idata, 1);
- }
-
- /*
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml.ns-init Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml
---- Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml.ns-init 2007-06-18 12:46:47.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/pam_namespace.8.xml 2007-08-06 13:57:56.000000000 +0200
-@@ -60,7 +60,9 @@
- script /etc/security/namespace.init exists, it
- is used to initialize the namespace every time a new instance
- directory is setup. The script receives the polyinstantiated
-- directory path and the instance directory path as its arguments.
-+ directory path, the instance directory path, flag whether the instance
-+ directory was newly created (0 for no, 1 for yes), and the user name
-+ as its arguments.
-
-
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.ns-init Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init
---- Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init.ns-init 2007-06-18 12:46:47.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_namespace/namespace.init 2007-08-06 13:57:56.000000000 +0200
-@@ -1,6 +1,8 @@
- #!/bin/sh -p
- # This is only a boilerplate for the instance initialization script.
--# It receives polydir path as $1 and the instance path as $2.
-+# It receives polydir path as $1, the instance path as $2,
-+# a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
-+# and user name in $4.
- #
- # If you intend to polyinstantiate /tmp and you also want to use the X windows
- # environment, you will have to use this script to bind mount the socket that
diff --git a/pam-0.99.8.1-selinux-permit.patch b/pam-0.99.8.1-selinux-permit.patch
deleted file mode 100644
index 4488826..0000000
--- a/pam-0.99.8.1-selinux-permit.patch
+++ /dev/null
@@ -1,473 +0,0 @@
-Written-by: Tomas Mraz
-Reviewed-by: Karel Zak
-
-diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml
---- /dev/null 2007-09-17 08:57:19.474470099 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml 2007-09-19 19:37:26.000000000 +0200
-@@ -0,0 +1,182 @@
-+
-+
-+
-+
-+
-+
-+ pam_selinux_permit
-+ 8
-+ Linux-PAM Manual
-+
-+
-+
-+ pam_selinux_permit
-+ PAM module to allow/deny login depending on SELinux enforcement state
-+
-+
-+
-+
-+ pam_selinux_permit.so
-+
-+ debug
-+
-+
-+ conf=/path/to/config/file
-+
-+
-+
-+
-+
-+ DESCRIPTION
-+
-+ The pam_selinux module allows or denies login depending on SELinux enforcement
-+ state.
-+
-+
-+ When the user which is logging in matches an entry in the config file
-+ he is allowed access only when the SELinux is in enforcing mode. Otherwise
-+ he is denied access. For users not matching any entry in the config file
-+ the pam_selinux_permit module returns PAM_IGNORE return value.
-+
-+
-+ The config file contains a simple list of user names one per line. If the
-+ name is prefixed with @ character it means that all
-+ users in the group name match. If it is prefixed
-+ with a % character the SELinux user is used to match against the name
-+ instead of the account name. Note that when SELinux is disabled the
-+ SELinux user assigned to the account cannot be determined. This means that
-+ such entries are never matched when SELinux is disabled and pam_selinux_permit
-+ will return PAM_IGNORE.
-+
-+
-+
-+
-+ OPTIONS
-+
-+
-+
-+
-+
-+
-+
-+ Turns on debugging via
-+
-+ syslog3
-+ .
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Path to alternative config file overriding the default.
-+
-+
-+
-+
-+
-+
-+
-+ MODULE SERVICES PROVIDED
-+
-+ Only the and
-+ services are supported.
-+
-+
-+
-+
-+ RETURN VALUES
-+
-+
-+ PAM_AUTH_ERR
-+
-+
-+ SELinux is disabled or in the permissive mode and the user
-+ matches.
-+
-+
-+
-+
-+ PAM_SUCCESS
-+
-+
-+ SELinux is in the enforcing mode and the user matches.
-+
-+
-+
-+
-+ PAM_IGNORE
-+
-+
-+ The user does not match any entry in the config file.
-+
-+
-+
-+
-+ PAM_USER_UNKNOWN
-+
-+
-+ The module was unable to determine the user's name.
-+
-+
-+
-+
-+ PAM_SERVICE_ERR
-+
-+
-+ Error during reading or parsing the config file.
-+
-+
-+
-+
-+
-+
-+
-+ FILES
-+
-+
-+ /etc/security/sepermit.conf
-+
-+ Default configuration file
-+
-+
-+
-+
-+
-+
-+ EXAMPLES
-+
-+auth [success=done ignore=ignore default=bad] pam_selinux_permit.so
-+auth required pam_unix.so
-+account required pam_unix.so
-+session required pam_permit.so
-+
-+
-+
-+
-+ SEE ALSO
-+
-+
-+ pam.conf5
-+ ,
-+
-+ pam.d8
-+ ,
-+
-+ pam8
-+
-+
-+
-+
-+
-+ AUTHOR
-+
-+ pam_selinux_permit was written by Tomas Mraz <tmraz@redhat.com>.
-+
-+
-+
-+
-diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c
---- /dev/null 2007-09-17 08:57:19.474470099 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c 2007-09-19 20:29:47.000000000 +0200
-@@ -0,0 +1,222 @@
-+/******************************************************************************
-+ * A module for Linux-PAM that allows/denies acces based on SELinux state.
-+ *
-+ * Copyright (c) 2007 Red Hat, Inc.
-+ * Written by Tomas Mraz
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#include "config.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#define PAM_SM_AUTH
-+#define PAM_SM_ACCOUNT
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+
-+/* return 0 when matched, -1 when unmatched, pam error otherwise */
-+static int
-+sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
-+ const char *seuser, int debug)
-+{
-+ FILE *f;
-+ char *line = NULL;
-+ char *start;
-+ size_t len = 0;
-+ int matched = 0;
-+
-+ f = fopen(cfgfile, "r");
-+
-+ if (!f) {
-+ pam_syslog(pamh, LOG_ERR, "Failed to open config file %s: %m", cfgfile);
-+ return PAM_SERVICE_ERR;
-+ }
-+
-+ while (!matched && getline(&line, &len, f) != -1) {
-+ size_t n;
-+
-+ if (line[0] == '#')
-+ continue;
-+
-+ start = line;
-+ while (isspace(*start))
-+ ++start;
-+ n = strlen(start);
-+ while (n > 0 && isspace(start[n-1])) {
-+ --n;
-+ }
-+ if (n == 0)
-+ continue;
-+
-+ start[n] = '\0';
-+
-+ switch (start[0]) {
-+ case '@':
-+ ++start;
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "Matching user %s against group %s", user, start);
-+ if (pam_modutil_user_in_group_nam_nam(pamh, user, start)) {
-+ matched = 1;
-+ }
-+ break;
-+ case '%':
-+ ++start;
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "Matching seuser %s against seuser %s", seuser, start);
-+ if (strcmp(seuser, start) == 0) {
-+ matched = 1;
-+ }
-+ break;
-+ default:
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "Matching user %s against user %s", user, start);
-+ if (strcmp(user, start) == 0) {
-+ matched = 1;
-+ }
-+ }
-+ }
-+
-+ free(line);
-+ fclose(f);
-+ return matched ? 0 : -1;
-+}
-+
-+PAM_EXTERN int
-+pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
-+ int argc, const char **argv)
-+{
-+ int i;
-+ int rv;
-+ int debug = 0;
-+ int sense = PAM_AUTH_ERR;
-+ const char *user = NULL;
-+ char *seuser = NULL;
-+ char *level = NULL;
-+ const char *cfgfile = SEPERMIT_CONF_FILE;
-+
-+ /* Parse arguments. */
-+ for (i = 0; i < argc; i++) {
-+ if (strcmp(argv[i], "debug") == 0) {
-+ debug = 1;
-+ }
-+ if (strcmp(argv[i], "conf=") == 0) {
-+ cfgfile = argv[i] + 5;
-+ }
-+ }
-+
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "Parsing config file: %s", cfgfile);
-+
-+ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
-+ || *user == '\0') {
-+ pam_syslog(pamh, LOG_ERR, "Cannot determine the user's name");
-+ return PAM_USER_UNKNOWN;
-+ }
-+
-+ if (is_selinux_enabled() > 0) {
-+ if (security_getenforce() == 1) {
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "Enforcing mode, access will be allowed on match");
-+ sense = PAM_SUCCESS;
-+ }
-+
-+ if (getseuserbyname(user, &seuser, &level) != 0) {
-+ seuser = NULL;
-+ level = NULL;
-+ pam_syslog(pamh, LOG_ERR, "getseuserbyname failed: %m");
-+ }
-+ }
-+
-+ if (debug && sense != PAM_SUCCESS)
-+ pam_syslog(pamh, LOG_NOTICE, "Access will not be allowed on match");
-+
-+ rv = sepermit_match(pamh, cfgfile, user, seuser, debug);
-+
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "sepermit_match returned: %d", rv);
-+
-+ free(seuser);
-+ free(level);
-+
-+ switch (rv) {
-+ case -1:
-+ return PAM_IGNORE;
-+ case 0:
-+ return sense;
-+ }
-+
-+ return rv;
-+}
-+
-+PAM_EXTERN int
-+pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
-+ int argc UNUSED, const char **argv UNUSED)
-+{
-+ return PAM_IGNORE;
-+}
-+
-+PAM_EXTERN int
-+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
-+ int argc, const char **argv)
-+{
-+ return pam_sm_authenticate(pamh, flags, argc, argv);
-+}
-+
-+#ifdef PAM_STATIC
-+
-+/* static module data */
-+
-+struct pam_module _pam_access_modstruct = {
-+ "pam_access",
-+ pam_sm_authenticate,
-+ pam_sm_setcred,
-+ pam_sm_acct_mgmt,
-+ NULL,
-+ NULL,
-+ NULL
-+};
-+#endif
-+
-diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf
---- /dev/null 2007-09-17 08:57:19.474470099 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf 2007-09-19 19:37:26.000000000 +0200
-@@ -0,0 +1,6 @@
-+# /etc/security/sepermit.conf
-+#
-+# Each line contains either:
-+# - an user name
-+# - a group name, with @group syntax
-+# - a SELinux user name, with %seuser syntax
-diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.permit Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am
---- Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.permit 2007-01-23 11:09:25.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am 2007-09-19 19:37:26.000000000 +0200
-@@ -5,20 +5,21 @@
- CLEANFILES = *~
-
- EXTRA_DIST = README $(XMLS) pam_selinux.8 pam_selinux_check.8 \
-- tst-pam_selinux
-+ pam_seliux_permit.8 sepermit.conf tst-pam_selinux
-
- if HAVE_LIBSELINUX
- TESTS = tst-pam_selinux
-- man_MANS = pam_selinux.8
-+ man_MANS = pam_selinux.8 pam_selinux_permit.8
- endif
-
--XMLS = README.xml pam_selinux.8.xml
-+XMLS = README.xml pam_selinux.8.xml pam_selinux_permit.8.xml
-
- securelibdir = $(SECUREDIR)
- secureconfdir = $(SCONFIGDIR)
-
- AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-- -I$(top_srcdir)/libpam_misc/include
-+ -I$(top_srcdir)/libpam_misc/include \
-+ -D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\"
- AM_LDFLAGS = -no-undefined \
- -L$(top_builddir)/libpam -lpam @LIBSELINUX@
-
-@@ -30,12 +31,16 @@ if HAVE_VERSIONING
- -Wl,--version-script=$(srcdir)/../modules.map
- endif
-
-+pam_selinux_permit_la_LDFLAGS= $(pam_selinux_la_LDFLAGS)
-+
-+secureconf_DATA = sepermit.conf
-+
- if HAVE_LIBSELINUX
-- securelib_LTLIBRARIES = pam_selinux.la
-+ securelib_LTLIBRARIES = pam_selinux.la pam_selinux_permit.la
- noinst_PROGRAMS = pam_selinux_check
- endif
- if ENABLE_REGENERATE_MAN
--noinst_DATA = README pam_selinux.8
-+noinst_DATA = README pam_selinux.8 pam_selinux_permit.8
- README: pam_selinux.8.xml
- -include $(top_srcdir)/Make.xml.rules
- endif
diff --git a/pam-0.99.8.1-sepermit-kill-user.patch b/pam-0.99.8.1-sepermit-kill-user.patch
deleted file mode 100644
index b33d81a..0000000
--- a/pam-0.99.8.1-sepermit-kill-user.patch
+++ /dev/null
@@ -1,318 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c
---- Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c.kill-user 2008-01-28 18:34:18.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.c 2008-01-28 18:34:18.000000000 +0100
-@@ -1,7 +1,7 @@
- /******************************************************************************
- * A module for Linux-PAM that allows/denies acces based on SELinux state.
- *
-- * Copyright (c) 2007 Red Hat, Inc.
-+ * Copyright (c) 2007, 2008 Red Hat, Inc.
- * Written by Tomas Mraz
- *
- * Redistribution and use in source and binary forms, with or without
-@@ -46,6 +46,14 @@
- #include
- #include
- #include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-
- #define PAM_SM_AUTH
- #define PAM_SM_ACCOUNT
-@@ -57,6 +65,165 @@
-
- #include
-
-+#define MODULE "pam_selinux_permit"
-+#define OPT_DELIM ":"
-+
-+struct lockfd {
-+ uid_t uid;
-+ int fd;
-+ int debug;
-+};
-+
-+#define PROC_BASE "/proc"
-+#define MAX_NAMES (int)(sizeof(unsigned long)*8)
-+
-+static int
-+match_process_uid(pid_t pid, uid_t uid)
-+{
-+ char buf[128];
-+ uid_t puid;
-+ FILE *f;
-+ int re = 0;
-+
-+ snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid);
-+ if (!(f = fopen (buf, "r")))
-+ return 0;
-+
-+ while (fgets(buf, sizeof buf, f)) {
-+ if (sscanf (buf, "Uid:\t%d", &puid)) {
-+ re = uid == puid;
-+ break;
-+ }
-+ }
-+ fclose(f);
-+ return re;
-+}
-+
-+static int
-+check_running (pam_handle_t *pamh, uid_t uid, int killall, int debug)
-+{
-+ DIR *dir;
-+ struct dirent *de;
-+ pid_t *pid_table, pid, self;
-+ int i;
-+ int pids, max_pids;
-+ int running = 0;
-+ self = getpid();
-+ if (!(dir = opendir(PROC_BASE))) {
-+ pam_syslog(pamh, LOG_ERR, "Failed to open proc directory file %s:", PROC_BASE);
-+ return -1;
-+ }
-+ max_pids = 256;
-+ pid_table = malloc(max_pids * sizeof (pid_t));
-+ if (!pid_table) {
-+ pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
-+ return -1;
-+ }
-+ pids = 0;
-+ while ((de = readdir (dir)) != NULL) {
-+ if (!(pid = (pid_t)atoi(de->d_name)) || pid == self)
-+ continue;
-+
-+ if (pids == max_pids) {
-+ if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
-+ pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
-+ return -1;
-+ }
-+ max_pids *= 2;
-+ }
-+ pid_table[pids++] = pid;
-+ }
-+
-+ (void)closedir(dir);
-+
-+ for (i = 0; i < pids; i++) {
-+ pid_t id;
-+
-+ if (match_process_uid(pid_table[i], uid) == 0)
-+ continue;
-+ id = pid_table[i];
-+
-+ if (killall) {
-+ if (debug)
-+ pam_syslog(pamh, LOG_NOTICE, "Attempting to kill %d", id);
-+ kill(id, SIGKILL);
-+ }
-+ running++;
-+ }
-+
-+ free(pid_table);
-+ return running;
-+}
-+
-+static void
-+sepermit_unlock(pam_handle_t *pamh, void *plockfd, int error_status UNUSED)
-+{
-+ struct lockfd *lockfd = plockfd;
-+ struct flock fl;
-+
-+ memset(&fl, 0, sizeof(fl));
-+ fl.l_type = F_UNLCK;
-+ fl.l_whence = SEEK_SET;
-+
-+ if (lockfd->debug)
-+ pam_syslog(pamh, LOG_ERR, "Unlocking fd: %d uid: %d", lockfd->fd, lockfd->uid);
-+
-+ /* Don't kill uid==0 */
-+ if (lockfd->uid)
-+ /* This is a DOS but it prevents an app from forking to prevent killing */
-+ while(check_running(pamh, lockfd->uid, 1, lockfd->debug) > 0)
-+ continue;
-+
-+ fcntl(lockfd->fd, F_SETLK, &fl);
-+ close(lockfd->fd);
-+ free(lockfd);
-+}
-+
-+static int
-+sepermit_lock(pam_handle_t *pamh, const char *user, int debug)
-+{
-+ char buf[PATH_MAX];
-+ struct flock fl;
-+
-+ memset(&fl, 0, sizeof(fl));
-+ fl.l_type = F_WRLCK;
-+ fl.l_whence = SEEK_SET;
-+
-+ struct passwd *pw = pam_modutil_getpwnam( pamh, user );
-+ if (!pw) {
-+ pam_syslog(pamh, LOG_ERR, "Unable to find uid for user %s", user);
-+ return -1;
-+ }
-+ if (check_running(pamh, pw->pw_uid, 0, debug) > 0) {
-+ pam_syslog(pamh, LOG_ERR, "User %s processes are running. Exclusive login not allowed", user);
-+ return -1;
-+ }
-+
-+ snprintf(buf, sizeof(buf), "%s/%d.lock", SEPERMIT_LOCKDIR, pw->pw_uid);
-+ int fd = open(buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
-+ if (fd < 0) {
-+ pam_syslog(pamh, LOG_ERR, "Unable to open lock file %s/%d.lock", SEPERMIT_LOCKDIR, pw->pw_uid);
-+ return -1;
-+ }
-+
-+ if (fcntl(fd, F_SETLK, &fl) == -1) {
-+ pam_syslog(pamh, LOG_ERR, "User %s with exclusive login already logged in", user);
-+ close(fd);
-+ return -1;
-+ }
-+ struct lockfd *lockfd=calloc(1, sizeof(struct lockfd));
-+ if (!lockfd) {
-+ close(fd);
-+ pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
-+ return -1;
-+ }
-+ lockfd->uid = pw->pw_uid;
-+ lockfd->debug = debug;
-+ lockfd->fd=fd;
-+ pam_set_data(pamh, "pam_selinux_permit", lockfd, sepermit_unlock);
-+ return 0;
-+}
-+
- /* return 0 when matched, -1 when unmatched, pam error otherwise */
- static int
- sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
-@@ -67,6 +234,7 @@ sepermit_match(pam_handle_t *pamh, const
- char *start;
- size_t len = 0;
- int matched = 0;
-+ int exclusive = 0;
-
- f = fopen(cfgfile, "r");
-
-@@ -77,6 +245,8 @@ sepermit_match(pam_handle_t *pamh, const
-
- while (!matched && getline(&line, &len, f) != -1) {
- size_t n;
-+ char *sptr;
-+ char *opt;
-
- if (line[0] == '#')
- continue;
-@@ -92,6 +262,7 @@ sepermit_match(pam_handle_t *pamh, const
- continue;
-
- start[n] = '\0';
-+ start = strtok_r(start, OPT_DELIM, &sptr);
-
- switch (start[0]) {
- case '@':
-@@ -117,11 +288,22 @@ sepermit_match(pam_handle_t *pamh, const
- matched = 1;
- }
- }
-+ if (matched)
-+ while ((opt=strtok_r(NULL, OPT_DELIM, &sptr)) != NULL) {
-+ if (strcmp(opt, "exclusive") == 0)
-+ exclusive = 1;
-+ else if (debug) {
-+ pam_syslog(pamh, LOG_NOTICE, "Unknown user option: %s", opt);
-+ }
-+ }
- }
-
- free(line);
- fclose(f);
-- return matched ? 0 : -1;
-+ if (matched)
-+ return exclusive ? sepermit_lock(pamh, user, debug) : 0;
-+ else
-+ return -1;
- }
-
- PAM_EXTERN int
-diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml
---- Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml.kill-user 2008-01-28 18:34:18.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/pam_selinux_permit.8.xml 2008-01-28 18:34:18.000000000 +0100
-@@ -30,8 +30,8 @@
-
- DESCRIPTION
-
-- The pam_selinux module allows or denies login depending on SELinux enforcement
-- state.
-+ The pam_selinux_permit module allows or denies login depending on SELinux
-+ enforcement state.
-
-
- When the user which is logging in matches an entry in the config file
-@@ -41,14 +41,21 @@
-
-
- The config file contains a simple list of user names one per line. If the
-- name is prefixed with @ character it means that all
-+ name is prefixed with @ character it means that all
- users in the group name match. If it is prefixed
-- with a % character the SELinux user is used to match against the name
-+ with a % character the SELinux user is used to match against the name
- instead of the account name. Note that when SELinux is disabled the
- SELinux user assigned to the account cannot be determined. This means that
- such entries are never matched when SELinux is disabled and pam_selinux_permit
- will return PAM_IGNORE.
-
-+
-+ Each user name in the configuration file can have optional arguments separated
-+ by : character. The only currently recognized argument is exclusive.
-+ The pam_selinux_permit module will allow only single concurrent user session for
-+ the user with this argument specified and it will attempt to kill all processes
-+ of the user after logout.
-+
-
-
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am
---- Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am.kill-user 2008-01-28 18:34:18.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/Makefile.am 2008-01-28 18:35:01.000000000 +0100
-@@ -16,10 +16,13 @@ XMLS = README.xml pam_selinux.8.xml pam_
-
- securelibdir = $(SECUREDIR)
- secureconfdir = $(SCONFIGDIR)
-+sepermitlockdir = /var/run/sepermit
-
- AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- -I$(top_srcdir)/libpam_misc/include \
-- -D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\"
-+ -D SEPERMIT_CONF_FILE=\"$(SCONFIGDIR)/sepermit.conf\" \
-+ -D SEPERMIT_LOCKDIR=\"$(sepermitlockdir)\"
-+
- AM_LDFLAGS = -no-undefined \
- -L$(top_builddir)/libpam -lpam @LIBSELINUX@
-
-@@ -34,6 +37,7 @@ endif
- pam_selinux_permit_la_LDFLAGS= $(pam_selinux_la_LDFLAGS)
-
- secureconf_DATA = sepermit.conf
-+sepermitlock_DATA =
-
- if HAVE_LIBSELINUX
- securelib_LTLIBRARIES = pam_selinux.la pam_selinux_permit.la
-diff -up Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf.kill-user Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf
---- Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf.kill-user 2008-01-28 18:34:18.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_selinux/sepermit.conf 2008-01-28 18:34:18.000000000 +0100
-@@ -4,3 +4,8 @@
- # - an user name
- # - a group name, with @group syntax
- # - a SELinux user name, with %seuser syntax
-+# Each line can contain optional arguments separated by :
-+# The possible arguments are:
-+# - exclusive - only single login session will
-+# be allowed for the user and the user's processes
-+# will be killed on logout
diff --git a/pam-0.99.8.1-setkeycreatecon.patch b/pam-0.99.8.1-setkeycreatecon.patch
deleted file mode 100644
index a9bedff..0000000
--- a/pam-0.99.8.1-setkeycreatecon.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/configure.in.setkeycreatecon Linux-PAM-0.99.8.1/configure.in
---- Linux-PAM-0.99.8.1/configure.in.setkeycreatecon 2008-01-28 17:22:40.000000000 +0100
-+++ Linux-PAM-0.99.8.1/configure.in 2008-01-28 17:26:25.000000000 +0100
-@@ -379,6 +379,7 @@ AC_SUBST(LIBDB)
- AM_CONDITIONAL([HAVE_LIBDB], [test ! -z "$LIBDB"])
-
- AC_CHECK_LIB([nsl],[yp_get_default_domain], LIBNSL="-lnsl", LIBNSL="")
-+BACKUP_LIBS=$LIBS
- LIBS="$LIBS $LIBNSL"
- AC_CHECK_FUNCS(yp_get_default_domain)
- LIBS=$BACKUP_LIBS
-@@ -396,6 +397,10 @@ AC_SUBST(LIBSELINUX)
- AM_CONDITIONAL([HAVE_LIBSELINUX], [test ! -z "$LIBSELINUX"])
- if test ! -z "$LIBSELINUX" ; then
- AC_DEFINE([WITH_SELINUX], 1, [Defined if SE Linux support is compiled in])
-+ BACKUP_LIBS=$LIBS
-+ LIBS="$LIBS $LIBSELINUX"
-+ AC_CHECK_FUNCS(setkeycreatecon)
-+ LIBS=$BACKUP_LIBS
- fi
-
- dnl Checks for header files.
-@@ -428,7 +433,7 @@ AC_CHECK_FUNCS(fseeko gethostname gettim
- AC_CHECK_FUNCS(strcspn strdup strspn strstr strtol uname)
- AC_CHECK_FUNCS(getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
- AC_CHECK_FUNCS(getgrouplist getline getdelim)
--AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af setkeycreatecon)
-+AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af)
-
- AC_CHECK_FUNCS(unshare, [UNSHARE=yes], [UNSHARE=no])
- AM_CONDITIONAL([HAVE_UNSHARE], [test "$UNSHARE" = yes])
diff --git a/pam-0.99.8.1-substack.patch b/pam-0.99.8.1-substack.patch
deleted file mode 100644
index 912df83..0000000
--- a/pam-0.99.8.1-substack.patch
+++ /dev/null
@@ -1,784 +0,0 @@
-Index: libpam/pam_dispatch.c
-===================================================================
-RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_dispatch.c,v
-retrieving revision 1.11
-diff -u -p -r1.11 pam_dispatch.c
---- libpam/pam_dispatch.c 1 Aug 2006 08:54:57 -0000 1.11
-+++ libpam/pam_dispatch.c 12 Oct 2007 16:23:37 -0000
-@@ -34,7 +34,8 @@
- static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
- _pam_boolean resumed, int use_cached_chain)
- {
-- int depth, impression, status, skip_depth;
-+ int depth, impression, status, skip_depth, prev_level, stack_level;
-+ struct _pam_substack_state *substates = NULL;
-
- IF_NO_PAMH("_pam_dispatch_aux", pamh, PAM_SYSTEM_ERR);
-
-@@ -54,27 +55,51 @@ static int _pam_dispatch_aux(pam_handle_
- skip_depth = pamh->former.depth;
- status = pamh->former.status;
- impression = pamh->former.impression;
-+ substates = pamh->former.substates;
- /* forget all that */
- pamh->former.impression = _PAM_UNDEF;
- pamh->former.status = PAM_MUST_FAIL_CODE;
- pamh->former.depth = 0;
-+ pamh->former.substates = NULL;
- } else {
- skip_depth = 0;
-- impression = _PAM_UNDEF;
-- status = PAM_MUST_FAIL_CODE;
-+ substates = malloc(PAM_SUBSTACK_MAX_LEVEL * sizeof(*substates));
-+ if (substates == NULL) {
-+ pam_syslog(pamh, LOG_CRIT,
-+ "_pam_dispatch_aux: no memory for substack states");
-+ return PAM_BUF_ERR;
-+ }
-+ substates[0].impression = impression = _PAM_UNDEF;
-+ substates[0].status = status = PAM_MUST_FAIL_CODE;
- }
-
-+ prev_level = 0;
-+
- /* Loop through module logic stack */
-- for (depth=0 ; h != NULL ; h = h->next, ++depth) {
-+ for (depth=0 ; h != NULL ; prev_level = stack_level, h = h->next, ++depth) {
- int retval, cached_retval, action;
-
-+ stack_level = h->stack_level;
-+
- /* skip leading modules if they have already returned */
- if (depth < skip_depth) {
- continue;
- }
-
-+ /* remember state if we are entering a substack */
-+ if (prev_level < stack_level) {
-+ substates[stack_level].impression = impression;
-+ substates[stack_level].status = status;
-+ }
-+
- /* attempt to call the module */
-- if (h->func == NULL) {
-+ if (h->handler_type == PAM_HT_MUST_FAIL) {
-+ D(("module poorly listed in PAM config; forcing failure"));
-+ retval = PAM_MUST_FAIL_CODE;
-+ } else if (h->handler_type == PAM_HT_SUBSTACK) {
-+ D(("skipping substack handler"));
-+ continue;
-+ } else if (h->func == NULL) {
- D(("module function is not defined, indicating failure"));
- retval = PAM_MODULE_UNKNOWN;
- } else {
-@@ -83,10 +108,6 @@ static int _pam_dispatch_aux(pam_handle_
- retval = h->func(pamh, flags, h->argc, h->argv);
- pamh->mod_name=NULL;
- D(("module returned: %s", pam_strerror(pamh, retval)));
-- if (h->must_fail) {
-- D(("module poorly listed in PAM config; forcing failure"));
-- retval = PAM_MUST_FAIL_CODE;
-- }
- }
-
- /*
-@@ -100,6 +121,7 @@ static int _pam_dispatch_aux(pam_handle_
- pamh->former.impression = impression;
- pamh->former.status = status;
- pamh->former.depth = depth;
-+ pamh->former.substates = substates;
-
- D(("module %d returned PAM_INCOMPLETE", depth));
- return retval;
-@@ -176,8 +198,8 @@ static int _pam_dispatch_aux(pam_handle_
- switch (action) {
- case _PAM_ACTION_RESET:
-
-- impression = _PAM_UNDEF;
-- status = PAM_MUST_FAIL_CODE;
-+ impression = substates[stack_level].impression;
-+ status = substates[stack_level].status;
- break;
-
- case _PAM_ACTION_OK:
-@@ -244,9 +266,13 @@ static int _pam_dispatch_aux(pam_handle_
- }
-
- /* this means that we need to skip #action stacked modules */
-- do {
-- h = h->next;
-- } while ( --action > 0 && h != NULL );
-+ while (h->next != NULL && h->next->stack_level >= stack_level && action > 0) {
-+ do {
-+ h = h->next;
-+ ++depth;
-+ } while (h->next != NULL && h->next->stack_level > stack_level);
-+ --action;
-+ }
-
- /* note if we try to skip too many modules action is
- still non-zero and we snag the next if. */
-@@ -254,14 +280,19 @@ static int _pam_dispatch_aux(pam_handle_
-
- /* this case is a syntax error: we can't succeed */
- if (action) {
-- D(("action syntax error"));
-+ pam_syslog(pamh, LOG_ERR, "bad jump in stack");
- impression = _PAM_NEGATIVE;
- status = PAM_MUST_FAIL_CODE;
- }
- }
-- }
--
-+ continue;
-+
- decision_made: /* by getting here we have made a decision */
-+ while (h->next != NULL && h->next->stack_level >= stack_level) {
-+ h = h->next;
-+ ++depth;
-+ }
-+ }
-
- /* Sanity check */
- if ( status == PAM_SUCCESS && impression != _PAM_POSITIVE ) {
-@@ -269,6 +300,7 @@ decision_made: /* by getting here w
- status = PAM_MUST_FAIL_CODE;
- }
-
-+ free(substates);
- /* We have made a decision about the modules executed */
- return status;
- }
-Index: libpam/pam_end.c
-===================================================================
-RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_end.c,v
-retrieving revision 1.4
-diff -u -p -r1.4 pam_end.c
---- libpam/pam_end.c 12 Jan 2006 10:06:49 -0000 1.4
-+++ libpam/pam_end.c 12 Oct 2007 16:23:37 -0000
-@@ -71,6 +71,8 @@ int pam_end(pam_handle_t *pamh, int pam_
- _pam_drop(pamh->pam_conversation);
- pamh->fail_delay.delay_fn_ptr = NULL;
-
-+ _pam_drop(pamh->former.substates);
-+
- /* and finally liberate the memory for the pam_handle structure */
-
- _pam_drop(pamh);
-Index: libpam/pam_handlers.c
-===================================================================
-RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_handlers.c,v
-retrieving revision 1.24
-diff -u -p -r1.24 pam_handlers.c
---- libpam/pam_handlers.c 14 Jun 2006 11:41:47 -0000 1.24
-+++ libpam/pam_handlers.c 12 Oct 2007 16:23:37 -0000
-@@ -18,7 +18,7 @@
-
- #define BUF_SIZE 1024
- #define MODULE_CHUNK 4
--#define UNKNOWN_MODULE_PATH "<*unknown module path*>"
-+#define UNKNOWN_MODULE "<*unknown module*>"
- #ifndef _PAM_ISA
- #define _PAM_ISA "."
- #endif
-@@ -28,7 +28,7 @@ static int _pam_assemble_line(FILE *f, c
- static void _pam_free_handlers_aux(struct handler **hp);
-
- static int _pam_add_handler(pam_handle_t *pamh
-- , int must_fail, int other, int type
-+ , int must_fail, int other, int stack_level, int type
- , int *actions, const char *mod_path
- , int argc, char **argv, int argvlen);
-
-@@ -43,6 +43,7 @@ static int _pam_add_handler(pam_handle_t
- static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
- , const char *service /* specific file */
- , int module_type /* specific type */
-+ , int stack_level /* level of substack */
- #ifdef PAM_READ_BOTH_CONFS
- , int not_other
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -51,6 +52,7 @@ static int _pam_load_conf_file(pam_handl
- static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
- , const char *known_service /* specific file */
- , int requested_module_type /* specific type */
-+ , int stack_level /* level of substack */
- #ifdef PAM_READ_BOTH_CONFS
- , int not_other
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -68,7 +70,7 @@ static int _pam_parse_conf_file(pam_hand
- int module_type, actions[_PAM_RETURN_VALUES];
- int other; /* set if module is for PAM_DEFAULT_SERVICE */
- int res; /* module added successfully? */
-- int must_fail=0; /* a badly formatted line must fail when used */
-+ int handler_type = PAM_HT_MODULE; /* regular handler from a module */
- int argc;
- char **argv;
- int argvlen;
-@@ -92,6 +94,7 @@ static int _pam_parse_conf_file(pam_hand
- /* accept "service name" or PAM_DEFAULT_SERVICE modules */
- if (!strcasecmp(this_service, pamh->service_name) || other) {
- int pam_include = 0;
-+ int substack = 0;
-
- /* This is a service we are looking for */
- D(("_pam_init_handlers: Found PAM config entry for: %s"
-@@ -105,7 +108,7 @@ static int _pam_parse_conf_file(pam_hand
- "(%s) empty module type", this_service);
- module_type = (requested_module_type != PAM_T_ANY) ?
- requested_module_type : PAM_T_AUTH; /* most sensitive */
-- must_fail = 1; /* install as normal but fail when dispatched */
-+ handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
- } else if (!strcasecmp("auth", tok)) {
- module_type = PAM_T_AUTH;
- } else if (!strcasecmp("session", tok)) {
-@@ -121,9 +124,9 @@ static int _pam_parse_conf_file(pam_hand
- this_service, tok);
- module_type = (requested_module_type != PAM_T_ANY) ?
- requested_module_type : PAM_T_AUTH; /* most sensitive */
-- must_fail = 1; /* install as normal but fail when dispatched */
-+ handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
- }
-- D(("Using %s config entry: %s", must_fail?"BAD ":"", tok));
-+ D(("Using %s config entry: %s", handler_type?"BAD ":"", tok));
- if (requested_module_type != PAM_T_ANY &&
- module_type != requested_module_type) {
- D(("Skipping config entry: %s (requested=%d, found=%d)",
-@@ -145,7 +148,7 @@ static int _pam_parse_conf_file(pam_hand
- pam_syslog(pamh, LOG_ERR,
- "(%s) no control flag supplied", this_service);
- _pam_set_default_control(actions, _PAM_ACTION_BAD);
-- must_fail = 1;
-+ handler_type = PAM_HT_MUST_FAIL;
- } else if (!strcasecmp("required", tok)) {
- D(("*PAM_F_REQUIRED*"));
- actions[PAM_SUCCESS] = _PAM_ACTION_OK;
-@@ -171,6 +174,11 @@ static int _pam_parse_conf_file(pam_hand
- } else if (!strcasecmp("include", tok)) {
- D(("*PAM_F_INCLUDE*"));
- pam_include = 1;
-+ substack = 0;
-+ } else if (!strcasecmp("substack", tok)) {
-+ D(("*PAM_F_SUBSTACK*"));
-+ pam_include = 1;
-+ substack = 1;
- } else {
- D(("will need to parse %s", tok));
- _pam_parse_control(actions, tok);
-@@ -180,7 +188,18 @@ static int _pam_parse_conf_file(pam_hand
-
- tok = _pam_StrTok(NULL, " \n\t", &nexttok);
- if (pam_include) {
-- if (_pam_load_conf_file(pamh, tok, this_service, module_type
-+ if (substack) {
-+ res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
-+ stack_level, module_type, actions, tok,
-+ 0, NULL, 0);
-+ if (res != PAM_SUCCESS) {
-+ pam_syslog(pamh, LOG_ERR, "error adding substack %s", tok);
-+ D(("failed to load module - aborting"));
-+ return PAM_ABORT;
-+ }
-+ }
-+ if (_pam_load_conf_file(pamh, tok, this_service, module_type,
-+ stack_level + substack
- #ifdef PAM_READ_BOTH_CONFS
- , !other
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -188,7 +207,7 @@ static int _pam_parse_conf_file(pam_hand
- continue;
- _pam_set_default_control(actions, _PAM_ACTION_BAD);
- mod_path = NULL;
-- must_fail = 1;
-+ handler_type = PAM_HT_MUST_FAIL;
- nexttok = NULL;
- } else if (tok != NULL) {
- mod_path = tok;
-@@ -199,7 +218,7 @@ static int _pam_parse_conf_file(pam_hand
- pam_syslog(pamh, LOG_ERR,
- "(%s) no module name supplied", this_service);
- mod_path = NULL;
-- must_fail = 1;
-+ handler_type = PAM_HT_MUST_FAIL;
- }
-
- /* nexttok points to remaining arguments... */
-@@ -219,7 +238,7 @@ static int _pam_parse_conf_file(pam_hand
- int y;
-
- D(("CONF%s: %s%s %d %s %d"
-- , must_fail?"<*will fail*>":""
-+ , handler_type==PAM_HT_MUST_FAIL?"<*will fail*>":""
- , this_service, other ? "(backup)":""
- , module_type
- , mod_path, argc));
-@@ -235,7 +254,7 @@ static int _pam_parse_conf_file(pam_hand
- }
- #endif
-
-- res = _pam_add_handler(pamh, must_fail, other
-+ res = _pam_add_handler(pamh, handler_type, other, stack_level
- , module_type, actions, mod_path
- , argc, argv, argvlen);
- if (res != PAM_SUCCESS) {
-@@ -252,6 +271,7 @@ static int _pam_parse_conf_file(pam_hand
- static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
- , const char *service /* specific file */
- , int module_type /* specific type */
-+ , int stack_level /* level of substack */
- #ifdef PAM_READ_BOTH_CONFS
- , int not_other
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -263,6 +283,12 @@ static int _pam_load_conf_file(pam_handl
-
- D(("_pam_load_conf_file called"));
-
-+ if (stack_level >= PAM_SUBSTACK_MAX_LEVEL) {
-+ D(("maximum level of substacks reached"));
-+ pam_syslog(pamh, LOG_ERR, "maximum level of substacks reached");
-+ return PAM_ABORT;
-+ }
-+
- if (config_name == NULL) {
- D(("no config file supplied"));
- pam_syslog(pamh, LOG_ERR, "(%s) no config file supplied", service);
-@@ -280,7 +306,7 @@ static int _pam_load_conf_file(pam_handl
- D(("opening %s", config_name));
- f = fopen(config_name, "r");
- if (f != NULL) {
-- retval = _pam_parse_conf_file(pamh, f, service, module_type
-+ retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level
- #ifdef PAM_READ_BOTH_CONFS
- , not_other
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -379,7 +405,8 @@ int _pam_init_handlers(pam_handle_t *pam
- f = fopen(filename, "r");
- if (f != NULL) {
- /* would test magic here? */
-- retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY
-+ retval = _pam_parse_conf_file(pamh, f, pamh->service_name,
-+ PAM_T_ANY, 0
- #ifdef PAM_READ_BOTH_CONFS
- , 0
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -400,7 +427,7 @@ int _pam_init_handlers(pam_handle_t *pam
- D(("checking %s", PAM_CONFIG));
-
- if ((f = fopen(PAM_CONFIG,"r")) != NULL) {
-- retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 1);
-+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 1);
- fclose(f);
- } else
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -419,9 +446,8 @@ int _pam_init_handlers(pam_handle_t *pam
- f = fopen(PAM_DEFAULT_SERVICE_FILE, "r");
- if (f != NULL) {
- /* would test magic here? */
-- retval = _pam_parse_conf_file(pamh, f
-- , PAM_DEFAULT_SERVICE
-- , PAM_T_ANY
-+ retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE,
-+ PAM_T_ANY, 0
- #ifdef PAM_READ_BOTH_CONFS
- , 0
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -454,7 +480,7 @@ int _pam_init_handlers(pam_handle_t *pam
- return PAM_ABORT;
- }
-
-- retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY
-+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0
- #ifdef PAM_READ_BOTH_CONFS
- , 0
- #endif /* PAM_READ_BOTH_CONFS */
-@@ -581,46 +607,19 @@ extract_modulename(const char *mod_path)
- return retval;
- }
-
--int _pam_add_handler(pam_handle_t *pamh
-- , int must_fail, int other, int type
-- , int *actions, const char *mod_path
-- , int argc, char **argv, int argvlen)
-+static struct loaded_module *
-+_pam_load_module(pam_handle_t *pamh, const char *mod_path)
- {
-- struct loaded_module *mod;
- int x = 0;
-- struct handler **handler_p;
-- struct handler **handler_p2;
-- struct handlers *the_handlers;
-- const char *sym, *sym2;
-- char *mod_full_path=NULL;
-+ int success;
- #ifndef PAM_STATIC
- char *mod_full_isa_path=NULL, *isa=NULL;
- #endif
-- servicefn func, func2;
-- int success;
--
-- D(("called."));
-- IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
--
-- /* if NULL set to something that can be searched for */
-- switch (mod_path != NULL) {
-- default:
-- if (mod_path[0] == '/') {
-- break;
-- }
-- if (asprintf(&mod_full_path, "%s%s",
-- DEFAULT_MODULE_PATH, mod_path) >= 0) {
-- mod_path = mod_full_path;
-- break;
-- }
-- mod_full_path = NULL;
-- pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
-- case 0:
-- mod_path = UNKNOWN_MODULE_PATH;
-- }
-+ struct loaded_module *mod;
-
-- D(("_pam_add_handler: adding type %d, module `%s'",type,mod_path));
-- mod = pamh->handlers.module;
-+ D(("_pam_load_module: loading module `%s'", mod_path));
-+
-+ mod = pamh->handlers.module;
-
- /* First, ensure the module is loaded */
- while (x < pamh->handlers.modules_used) {
-@@ -639,9 +638,8 @@ int _pam_add_handler(pam_handle_t *pamh
- if (tmp == NULL) {
- D(("cannot enlarge module pointer memory"));
- pam_syslog(pamh, LOG_ERR,
-- "realloc returned NULL in _pam_add_handler");
-- _pam_drop(mod_full_path);
-- return PAM_ABORT;
-+ "realloc returned NULL in _pam_load_module");
-+ return NULL;
- }
- pamh->handlers.module = tmp;
- pamh->handlers.modules_allocated += MODULE_CHUNK;
-@@ -654,10 +652,10 @@ int _pam_add_handler(pam_handle_t *pamh
- /* Only load static function if function was not found dynamically.
- * This code should work even if no dynamic loading is available. */
- if (success != PAM_SUCCESS) {
-- D(("_pam_add_handler: open static handler %s", mod_path));
-+ D(("_pam_load_module: open static handler %s", mod_path));
- mod->dl_handle = _pam_open_static_handler(pamh, mod_path);
- if (mod->dl_handle == NULL) {
-- D(("_pam_add_handler: unable to find static handler %s",
-+ D(("_pam_load_module: unable to find static handler %s",
- mod_path));
- pam_syslog(pamh, LOG_ERR,
- "unable to open static handler %s", mod_path);
-@@ -670,15 +668,15 @@ int _pam_add_handler(pam_handle_t *pamh
- }
- }
- #else
-- D(("_pam_add_handler: _pam_dlopen(%s)", mod_path));
-+ D(("_pam_load_module: _pam_dlopen(%s)", mod_path));
- mod->dl_handle = _pam_dlopen(mod_path);
-- D(("_pam_add_handler: _pam_dlopen'ed"));
-- D(("_pam_add_handler: dlopen'ed"));
-+ D(("_pam_load_module: _pam_dlopen'ed"));
-+ D(("_pam_load_module: dlopen'ed"));
- if (mod->dl_handle == NULL) {
- if (strstr(mod_path, "$ISA")) {
- mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1);
- if (mod_full_isa_path == NULL) {
-- D(("_pam_handler: couldn't get memory for mod_path"));
-+ D(("_pam_load_module: couldn't get memory for mod_path"));
- pam_syslog(pamh, LOG_ERR, "no memory for module path");
- success = PAM_ABORT;
- } else {
-@@ -694,9 +692,9 @@ int _pam_add_handler(pam_handle_t *pamh
- }
- }
- if (mod->dl_handle == NULL) {
-- D(("_pam_add_handler: _pam_dlopen(%s) failed", mod_path));
-- pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s)", mod_path);
-- pam_syslog(pamh, LOG_ERR, "[error: %s]", _pam_dlerror());
-+ D(("_pam_load_module: _pam_dlopen(%s) failed", mod_path));
-+ pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s): %s", mod_path,
-+ _pam_dlerror());
- /* Don't abort yet; static code may be able to find function.
- * But defaults to abort if nothing found below... */
- } else {
-@@ -717,7 +715,7 @@ int _pam_add_handler(pam_handle_t *pamh
-
- /* indicate its name - later we will search for it by this */
- if ((mod->name = _pam_strdup(mod_path)) == NULL) {
-- D(("_pam_handler: couldn't get memory for mod_path"));
-+ D(("_pam_load_module: couldn't get memory for mod_path"));
- pam_syslog(pamh, LOG_ERR, "no memory for module path");
- success = PAM_ABORT;
- }
-@@ -726,18 +724,54 @@ int _pam_add_handler(pam_handle_t *pamh
- mod += x; /* the located module */
- success = PAM_SUCCESS;
- }
-+ return success == PAM_SUCCESS ? mod : NULL;
-+}
-+
-+int _pam_add_handler(pam_handle_t *pamh
-+ , int handler_type, int other, int stack_level, int type
-+ , int *actions, const char *mod_path
-+ , int argc, char **argv, int argvlen)
-+{
-+ struct loaded_module *mod = NULL;
-+ struct handler **handler_p;
-+ struct handler **handler_p2;
-+ struct handlers *the_handlers;
-+ const char *sym, *sym2;
-+ char *mod_full_path;
-+ servicefn func, func2;
-+ int mod_type = PAM_MT_FAULTY_MOD;
-+
-+ D(("called."));
-+ IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
-
-- _pam_drop(mod_full_path);
-- mod_path = NULL; /* no longer needed or trusted */
-+ D(("_pam_add_handler: adding type %d, handler_type %d, module `%s'",
-+ type, handler_type, mod_path));
-
-- /* Now return error if necessary after trying all possible ways... */
-- if (success != PAM_SUCCESS)
-- return(success);
-+ if (handler_type == PAM_HT_MODULE && mod_path != NULL) {
-+ if (mod_path[0] == '/') {
-+ mod = _pam_load_module(pamh, mod_path);
-+ } else if (asprintf(&mod_full_path, "%s%s",
-+ DEFAULT_MODULE_PATH, mod_path) >= 0) {
-+ mod = _pam_load_module(pamh, mod_full_path);
-+ _pam_drop(mod_full_path);
-+ } else {
-+ pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
-+ return PAM_ABORT;
-+ }
-+
-+ if (mod == NULL) {
-+ /* if we get here with NULL it means allocation error */
-+ return PAM_ABORT;
-+ }
-+
-+ mod_type = mod->type;
-+ }
-+
-+ if (mod_path == NULL)
-+ mod_path = UNKNOWN_MODULE;
-
- /*
-- * At this point 'mod' points to the stored/loaded module. If its
-- * dl_handle is unknown, then we must be able to indicate dispatch
-- * failure with 'must_fail'
-+ * At this point 'mod' points to the stored/loaded module.
- */
-
- /* Now define the handler(s) based on mod->dlhandle and type */
-@@ -780,43 +814,43 @@ int _pam_add_handler(pam_handle_t *pamh
- /* are the modules reliable? */
- if (
- #ifdef PAM_STATIC
-- mod->type != PAM_MT_STATIC_MOD
-+ mod_type != PAM_MT_STATIC_MOD
- &&
- #else
-- mod->type != PAM_MT_DYNAMIC_MOD
-+ mod_type != PAM_MT_DYNAMIC_MOD
- &&
- #endif
-- mod->type != PAM_MT_FAULTY_MOD
-+ mod_type != PAM_MT_FAULTY_MOD
- ) {
-- D(("_pam_add_handlers: illegal module library type; %d", mod->type));
-+ D(("_pam_add_handlers: illegal module library type; %d", mod_type));
- pam_syslog(pamh, LOG_ERR,
- "internal error: module library type not known: %s;%d",
-- sym, mod->type);
-+ sym, mod_type);
- return PAM_ABORT;
- }
-
- /* now identify this module's functions - for non-faulty modules */
-
- #ifdef PAM_STATIC
-- if ((mod->type == PAM_MT_STATIC_MOD) &&
-+ if ((mod_type == PAM_MT_STATIC_MOD) &&
- (func = (servicefn)_pam_get_static_sym(mod->dl_handle, sym)) == NULL) {
- pam_syslog(pamh, LOG_ERR, "unable to resolve static symbol: %s", sym);
- }
- #else
-- if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
-+ if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
- !(func = _pam_dlsym(mod->dl_handle, sym)) ) {
- pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym);
- }
- #endif
- if (sym2) {
- #ifdef PAM_STATIC
-- if ((mod->type == PAM_MT_STATIC_MOD) &&
-+ if ((mod_type == PAM_MT_STATIC_MOD) &&
- (func2 = (servicefn)_pam_get_static_sym(mod->dl_handle, sym2))
- == NULL) {
- pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
- }
- #else
-- if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
-+ if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
- !(func2 = _pam_dlsym(mod->dl_handle, sym2)) ) {
- pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
- }
-@@ -835,14 +869,15 @@ int _pam_add_handler(pam_handle_t *pamh
- return (PAM_ABORT);
- }
-
-- (*handler_p)->must_fail = must_fail; /* failure forced? */
-+ (*handler_p)->handler_type = handler_type;
-+ (*handler_p)->stack_level = stack_level;
- (*handler_p)->func = func;
- memcpy((*handler_p)->actions,actions,sizeof((*handler_p)->actions));
- (*handler_p)->cached_retval = _PAM_INVALID_RETVAL;
- (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
- (*handler_p)->argc = argc;
- (*handler_p)->argv = argv; /* not a copy */
-- (*handler_p)->mod_name = extract_modulename(mod->name);
-+ (*handler_p)->mod_name = extract_modulename(mod_path);
- (*handler_p)->next = NULL;
-
- /* some of the modules have a second calling function */
-@@ -857,7 +892,8 @@ int _pam_add_handler(pam_handle_t *pamh
- return (PAM_ABORT);
- }
-
-- (*handler_p2)->must_fail = must_fail; /* failure forced? */
-+ (*handler_p2)->handler_type = handler_type;
-+ (*handler_p2)->stack_level = stack_level;
- (*handler_p2)->func = func2;
- memcpy((*handler_p2)->actions,actions,sizeof((*handler_p2)->actions));
- (*handler_p2)->cached_retval = _PAM_INVALID_RETVAL; /* ignored */
-@@ -873,7 +909,7 @@ int _pam_add_handler(pam_handle_t *pamh
- } else {
- (*handler_p2)->argv = NULL; /* no arguments */
- }
-- (*handler_p2)->mod_name = extract_modulename(mod->name);
-+ (*handler_p2)->mod_name = extract_modulename(mod_path);
- (*handler_p2)->next = NULL;
- }
-
-Index: libpam/pam_private.h
-===================================================================
-RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_private.h,v
-retrieving revision 1.19
-diff -u -p -r1.19 pam_private.h
---- libpam/pam_private.h 24 Jul 2006 15:47:40 -0000 1.19
-+++ libpam/pam_private.h 12 Oct 2007 16:23:37 -0000
-@@ -44,7 +44,7 @@
- #define _PAM_INVALID_RETVAL -1 /* default value for cached_retval */
-
- struct handler {
-- int must_fail;
-+ int handler_type;
- int (*func)(pam_handle_t *pamh, int flags, int argc, char **argv);
- int actions[_PAM_RETURN_VALUES];
- /* set by authenticate, open_session, chauthtok(1st)
-@@ -54,8 +54,13 @@ struct handler {
- char **argv;
- struct handler *next;
- char *mod_name;
-+ int stack_level;
- };
-
-+#define PAM_HT_MODULE 0
-+#define PAM_HT_MUST_FAIL 1
-+#define PAM_HT_SUBSTACK 2
-+
- struct loaded_module {
- char *name;
- int type; /* PAM_STATIC_MOD or PAM_DYNAMIC_MOD */
-@@ -76,7 +81,7 @@ struct handlers {
- };
-
- struct service {
-- struct loaded_module *module; /* Only used for dynamic loading */
-+ struct loaded_module *module; /* Array of modules */
- int modules_allocated;
- int modules_used;
- int handlers_loaded;
-@@ -111,6 +116,12 @@ struct _pam_fail_delay {
- const void *delay_fn_ptr;
- };
-
-+/* initial state in substack */
-+struct _pam_substack_state {
-+ int impression;
-+ int status;
-+};
-+
- struct _pam_former_state {
- /* this is known and set by _pam_dispatch() */
- int choice; /* which flavor of module function did we call? */
-@@ -119,6 +130,7 @@ struct _pam_former_state {
- int depth; /* how deep in the stack were we? */
- int impression; /* the impression at that time */
- int status; /* the status before returning incomplete */
-+ struct _pam_substack_state *substates; /* array of initial substack states */
-
- /* state info used by pam_get_user() function */
- int fail_user;
-@@ -175,6 +187,8 @@ struct pam_handle {
- #define _PAM_ACTION_UNDEF -6 /* this is treated as an error
- ( = _PAM_ACTION_BAD) */
-
-+#define PAM_SUBSTACK_MAX_LEVEL 16 /* maximum level of substacks */
-+
- /* character tables for parsing config files */
- extern const char * const _pam_token_actions[-_PAM_ACTION_UNDEF];
- extern const char * const _pam_token_returns[_PAM_RETURN_VALUES+1];
-Index: libpam/pam_start.c
-===================================================================
-RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_start.c,v
-retrieving revision 1.9
-diff -u -p -r1.9 pam_start.c
---- libpam/pam_start.c 24 Jul 2006 15:47:40 -0000 1.9
-+++ libpam/pam_start.c 12 Oct 2007 16:23:37 -0000
-@@ -88,6 +88,7 @@ int pam_start (
- (*pamh)->oldauthtok = NULL;
- (*pamh)->fail_delay.delay_fn_ptr = NULL;
- (*pamh)->former.choice = PAM_NOT_STACKED;
-+ (*pamh)->former.substates = NULL;
- #ifdef HAVE_LIBAUDIT
- (*pamh)->audit_state = 0;
- #endif
-Index: doc/man/pam.conf-syntax.xml
-===================================================================
-RCS file: /cvsroot/pam/Linux-PAM/doc/man/pam.conf-syntax.xml,v
-retrieving revision 1.4
-retrieving revision 1.5
-diff -u -r1.4 -r1.5
---- doc/man/pam.conf-syntax.xml 26 Aug 2007 22:44:51 -0000 1.4
-+++ doc/man/pam.conf-syntax.xml 19 Oct 2007 17:06:30 -0000 1.5
-@@ -180,6 +180,24 @@
-
-
-
-+
-+ substack
-+
-+
-+ include all lines of given type from the configuration
-+ file specified as an argument to this control. This differs from
-+ include in that evaluation of the
-+ done and die actions
-+ in a substack does not cause skipping the rest of the complete
-+ module stack, but only of the substack. Jumps in a substack
-+ also can not make evaluation jump out of it, and the whole substack
-+ is counted as one module when the jump is done in a parent stack.
-+ The reset action will reset the state of a
-+ module stack to the state it was in as of beginning of the substack
-+ evaluation.
-+
-+
-+
-
-
-
diff --git a/pam-0.99.8.1-succif-in-operator.patch b/pam-0.99.8.1-succif-in-operator.patch
deleted file mode 100644
index 50adf76..0000000
--- a/pam-0.99.8.1-succif-in-operator.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-Written-by: Tomas Mraz
-Reviewed-by: Karel Zak
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c.in-operator Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c
---- Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c.in-operator 2006-08-31 12:20:39.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_succeed_if/pam_succeed_if.c 2007-09-19 19:36:22.000000000 +0200
-@@ -191,13 +191,19 @@ static int
- evaluate_inlist(const char *left, const char *right)
- {
- char *p;
-- if ((p=strstr(right, left)) == NULL)
-- return PAM_AUTH_ERR;
-- if (p == right || *(p-1) == ':') { /* ':' is a list separator */
-- p += strlen(left);
-- if (*p == '\0' || *p == ':') {
-- return PAM_SUCCESS;
-+ /* Don't care about left containing ':'. */
-+ while ((p=strstr(right, left)) != NULL) {
-+ if (p == right || *(p-1) == ':') { /* ':' is a list separator */
-+ p += strlen(left);
-+ if (*p == '\0' || *p == ':') {
-+ return PAM_SUCCESS;
-+ }
- }
-+ right = strchr(p, ':');
-+ if (right == NULL)
-+ break;
-+ else
-+ ++right;
- }
- return PAM_AUTH_ERR;
- }
diff --git a/pam-0.99.8.1-tty-audit.patch b/pam-0.99.8.1-tty-audit.patch
deleted file mode 100644
index ead4837..0000000
--- a/pam-0.99.8.1-tty-audit.patch
+++ /dev/null
@@ -1,590 +0,0 @@
-Written-by: Miloslav Trmac
-Reviewed-by: Tomas Mraz
-diff -urN Linux-PAM/configure.in Linux-PAM-0.99.8.1/configure.in
---- Linux-PAM/configure.in 2007-11-28 13:41:14.000000000 +0100
-+++ Linux-PAM-0.99.8.1/configure.in 2007-11-28 14:35:30.000000000 +0100
-@@ -331,7 +331,11 @@
- WITH_LIBAUDIT=$enableval, WITH_LIBAUDIT=yes)
- if test x"$WITH_LIBAUDIT" != xno ; then
- AC_CHECK_HEADER([libaudit.h],
-- [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")]
-+ [AC_CHECK_LIB(audit, audit_log_acct_message, LIBAUDIT=-laudit, LIBAUDIT="")
-+ AC_CHECK_TYPE([struct audit_tty_status],
-+ [HAVE_AUDIT_TTY_STATUS=yes],
-+ [HAVE_AUDIT_TTY_STATUS=""],
-+ [#include ])]
- )
- if test ! -z "$LIBAUDIT" -a "ac_cv_header_libaudit_h" != "no" ; then
- AC_DEFINE([HAVE_LIBAUDIT], 1, [Defined if audit support should be compiled in])
-@@ -340,6 +344,8 @@
- LIBAUDIT=""
- fi
- AC_SUBST(LIBAUDIT)
-+AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS],
-+ [test "x$HAVE_AUDIT_TTY_STATUS" = xyes])
-
- BACKUP_LIBS=$LIBS
- AC_SEARCH_LIBS([crypt],[xcrypt crypt], LIBCRYPT="-l$ac_lib", LIBCRYPT="")
-@@ -517,7 +523,8 @@
- modules/pam_securetty/Makefile modules/pam_selinux/Makefile \
- modules/pam_shells/Makefile modules/pam_stress/Makefile \
- modules/pam_succeed_if/Makefile modules/pam_tally/Makefile \
-- modules/pam_time/Makefile modules/pam_umask/Makefile \
-+ modules/pam_time/Makefile modules/pam_tty_audit/Makefile \
-+ modules/pam_umask/Makefile \
- modules/pam_unix/Makefile modules/pam_userdb/Makefile \
- modules/pam_warn/Makefile modules/pam_wheel/Makefile \
- modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \
-diff -urN Linux-PAM/modules/Makefile.am Linux-PAM-0.99.8.1/modules/Makefile.am
---- Linux-PAM/modules/Makefile.am 2007-11-28 13:41:13.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/Makefile.am 2007-11-28 14:02:48.000000000 +0100
-@@ -9,8 +9,8 @@
- pam_lastlog pam_limits pam_listfile pam_localuser pam_mail \
- pam_mkhomedir pam_motd pam_nologin pam_permit pam_rhosts pam_rootok \
- pam_securetty pam_selinux pam_shells pam_stress pam_succeed_if \
-- pam_tally pam_time pam_umask pam_unix pam_userdb pam_warn \
-- pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \
-+ pam_tally pam_time pam_tty_audit pam_umask pam_unix pam_userdb \
-+ pam_warn pam_wheel pam_xauth pam_exec pam_namespace pam_loginuid \
- pam_faildelay
-
- CLEANFILES = *~
-diff -urN Linux-PAM/modules/pam_tty_audit/Makefile.am Linux-PAM-0.99.8.1/modules/pam_tty_audit/Makefile.am
---- Linux-PAM/modules/pam_tty_audit/Makefile.am 1970-01-01 01:00:00.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/Makefile.am 2007-11-28 16:05:00.000000000 +0100
-@@ -0,0 +1,30 @@
-+#
-+# Copyright (c) 2005, 2006 Thorsten Kukuk
-+#
-+
-+CLEANFILES = *~
-+
-+EXTRA_DIST = README ${MANS} $(XMLS)
-+
-+man_MANS = pam_tty_audit.8
-+XMLS = README.xml pam_tty_audit.8.xml
-+
-+securelibdir = $(SECUREDIR)
-+
-+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
-+AM_LDFLAGS = -no-undefined -avoid-version -module \
-+ -L$(top_builddir)/libpam -lpam
-+if HAVE_VERSIONING
-+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
-+endif
-+
-+if HAVE_AUDIT_TTY_STATUS
-+ securelib_LTLIBRARIES = pam_tty_audit.la
-+endif
-+
-+if ENABLE_REGENERATE_MAN
-+noinst_DATA = README
-+README: pam_tty_audit.8.xml
-+-include $(top_srcdir)/Make.xml.rules
-+endif
-+
-diff -urN Linux-PAM/modules/pam_tty_audit/pam_tty_audit.c Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c
---- Linux-PAM/modules/pam_tty_audit/pam_tty_audit.c 1970-01-01 01:00:00.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c 2007-11-28 16:10:43.000000000 +0100
-@@ -0,0 +1,332 @@
-+/* Copyright © 2007 Red Hat, Inc. All rights reserved.
-+ Red Hat author: Miloslav Trmač
-+
-+ Redistribution and use in source and binary forms of Linux-PAM, with
-+ or without modification, are permitted provided that the following
-+ conditions are met:
-+
-+ 1. Redistributions of source code must retain any existing copyright
-+ notice, and this entire permission notice in its entirety,
-+ including the disclaimer of warranties.
-+
-+ 2. Redistributions in binary form must reproduce all prior and current
-+ copyright notices, this list of conditions, and the following
-+ disclaimer in the documentation and/or other materials provided
-+ with the distribution.
-+
-+ 3. The name of any author may not be used to endorse or promote
-+ products derived from this software without their specific prior
-+ written permission.
-+
-+ ALTERNATIVELY, this product may be distributed under the terms of the
-+ GNU General Public License, in which case the provisions of the GNU
-+ GPL are required INSTEAD OF the above restrictions. (This clause is
-+ necessary due to a potential conflict between the GNU 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(S) 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. */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#define DATANAME "pam_tty_audit_last_state"
-+
-+/* Open an audit netlink socket */
-+static int
-+nl_open (void)
-+{
-+ return socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
-+}
-+
-+static int
-+nl_send (int fd, unsigned type, unsigned flags, const void *data, size_t size)
-+{
-+ struct sockaddr_nl addr;
-+ struct msghdr msg;
-+ struct nlmsghdr nlm;
-+ struct iovec iov[2];
-+ ssize_t res;
-+
-+ nlm.nlmsg_len = NLMSG_LENGTH (size);
-+ nlm.nlmsg_type = type;
-+ nlm.nlmsg_flags = NLM_F_REQUEST | flags;
-+ nlm.nlmsg_seq = 0;
-+ nlm.nlmsg_pid = 0;
-+ iov[0].iov_base = &nlm;
-+ iov[0].iov_len = sizeof (nlm);
-+ iov[1].iov_base = (void *)data;
-+ iov[1].iov_len = size;
-+ addr.nl_family = AF_NETLINK;
-+ addr.nl_pid = 0;
-+ addr.nl_groups = 0;
-+ msg.msg_name = &addr;
-+ msg.msg_namelen = sizeof (addr);
-+ msg.msg_iov = iov;
-+ msg.msg_iovlen = 2;
-+ msg.msg_control = NULL;
-+ msg.msg_controllen = 0;
-+ msg.msg_flags = 0;
-+ res = sendmsg (fd, &msg, 0);
-+ if (res == -1)
-+ return -1;
-+ if ((size_t)res != nlm.nlmsg_len)
-+ {
-+ errno = EIO;
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static int
-+nl_recv (int fd, unsigned type, void *buf, size_t size)
-+{
-+ struct sockaddr_nl addr;
-+ struct msghdr msg;
-+ struct nlmsghdr nlm;
-+ struct iovec iov[2];
-+ ssize_t res;
-+
-+ again:
-+ iov[0].iov_base = &nlm;
-+ iov[0].iov_len = sizeof (nlm);
-+ msg.msg_name = &addr;
-+ msg.msg_namelen = sizeof (addr);
-+ msg.msg_iov = iov;
-+ msg.msg_iovlen = 1;
-+ msg.msg_control = NULL;
-+ msg.msg_controllen = 0;
-+ if (type != NLMSG_ERROR)
-+ {
-+ res = recvmsg (fd, &msg, MSG_PEEK);
-+ if (res == -1)
-+ return -1;
-+ if (res != NLMSG_LENGTH (0))
-+ {
-+ errno = EIO;
-+ return -1;
-+ }
-+ if (nlm.nlmsg_type == NLMSG_ERROR)
-+ {
-+ struct nlmsgerr err;
-+
-+ iov[1].iov_base = &err;
-+ iov[1].iov_len = sizeof (err);
-+ msg.msg_iovlen = 2;
-+ res = recvmsg (fd, &msg, 0);
-+ if (res == -1)
-+ return -1;
-+ if ((size_t)res != NLMSG_LENGTH (sizeof (err))
-+ || nlm.nlmsg_type != NLMSG_ERROR)
-+ {
-+ errno = EIO;
-+ return -1;
-+ }
-+ if (err.error == 0)
-+ goto again;
-+ errno = -err.error;
-+ return -1;
-+ }
-+ }
-+ if (size != 0)
-+ {
-+ iov[1].iov_base = buf;
-+ iov[1].iov_len = size;
-+ msg.msg_iovlen = 2;
-+ }
-+ res = recvmsg (fd, &msg, 0);
-+ if (res == -1)
-+ return -1;
-+ if ((size_t)res != NLMSG_LENGTH (size)
-+ || nlm.nlmsg_type != type)
-+ {
-+ errno = EIO;
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static int
-+nl_recv_ack (int fd)
-+{
-+ struct nlmsgerr err;
-+
-+ if (nl_recv (fd, NLMSG_ERROR, &err, sizeof (err)) != 0)
-+ return -1;
-+ if (err.error != 0)
-+ {
-+ errno = -err.error;
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static void
-+cleanup_old_status (pam_handle_t *pamh, void *data, int error_status)
-+{
-+ (void)pamh;
-+ (void)error_status;
-+ free (data);
-+}
-+
-+int
-+pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
-+{
-+ enum command { CMD_NONE, CMD_ENABLE, CMD_DISABLE };
-+
-+ enum command command;
-+ struct audit_tty_status *old_status, new_status;
-+ const char *user;
-+ uid_t user_uid;
-+ struct passwd *pwd;
-+ int i, fd;
-+
-+ (void)flags;
-+
-+ if (pam_get_user (pamh, &user, NULL) != PAM_SUCCESS)
-+ {
-+ pam_syslog (pamh, LOG_ERR, "error determining target user's name");
-+ return PAM_SESSION_ERR;
-+ }
-+ pwd = pam_modutil_getpwnam (pamh, user);
-+ if (pwd == NULL)
-+ {
-+ pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
-+ return PAM_SESSION_ERR;
-+ }
-+ user_uid = pwd->pw_uid;
-+
-+ command = CMD_NONE;
-+ for (i = 0; i < argc; i++)
-+ {
-+ if (strncmp (argv[i], "enable=", 7) == 0
-+ || strncmp (argv[i], "disable=", 8) == 0)
-+ {
-+ enum command this_command;
-+ char *copy, *tok_data, *tok;
-+
-+ this_command = *argv[i] == 'e' ? CMD_ENABLE : CMD_DISABLE;
-+ copy = strdup (strchr (argv[i], '=') + 1);
-+ if (copy == NULL)
-+ return PAM_SESSION_ERR;
-+ for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
-+ tok = strtok_r (NULL, ",", &tok_data))
-+ {
-+ pwd = pam_modutil_getpwnam (pamh, tok);
-+ if (pwd == NULL)
-+ {
-+ pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
-+ continue;
-+ }
-+ if (pwd->pw_uid == user_uid)
-+ {
-+ command = this_command;
-+ break;
-+ }
-+ }
-+ free (copy);
-+ }
-+ }
-+ if (command == CMD_NONE)
-+ return PAM_SUCCESS;
-+
-+ old_status = malloc (sizeof (*old_status));
-+ if (old_status == NULL)
-+ return PAM_SESSION_ERR;
-+
-+ fd = nl_open ();
-+ if (fd == -1
-+ || nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0
-+ || nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0)
-+ {
-+ pam_syslog (pamh, LOG_ERR, "error reading current audit status: %m");
-+ if (fd != -1)
-+ close (fd);
-+ free (old_status);
-+ return PAM_SESSION_ERR;
-+ }
-+
-+ if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
-+ {
-+ free (old_status);
-+ goto ok_fd;
-+ }
-+
-+ if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
-+ != PAM_SUCCESS)
-+ {
-+ pam_syslog (pamh, LOG_ERR, "error saving old audit status");
-+ close (fd);
-+ free (old_status);
-+ return PAM_SESSION_ERR;
-+ }
-+
-+ new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
-+ if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
-+ sizeof (new_status)) != 0
-+ || nl_recv_ack (fd) != 0)
-+ {
-+ pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
-+ close (fd);
-+ return PAM_SESSION_ERR;
-+ }
-+ /* Fall through */
-+ ok_fd:
-+ close (fd);
-+ pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
-+ old_status->enabled, new_status.enabled);
-+ return PAM_SUCCESS;
-+}
-+
-+int
-+pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
-+ const char **argv)
-+{
-+ const void *status_;
-+
-+ (void)flags;
-+ (void)argc;
-+ (void)argv;
-+ if (pam_get_data (pamh, DATANAME, &status_) == PAM_SUCCESS)
-+ {
-+ const struct audit_tty_status *status;
-+ int fd;
-+
-+ status = status_;
-+
-+ fd = nl_open ();
-+ if (fd == -1
-+ || nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, status,
-+ sizeof (*status)) != 0
-+ || nl_recv_ack (fd) != 0)
-+ {
-+ pam_syslog (pamh, LOG_ERR, "error restoring audit status: %m");
-+ if (fd != -1)
-+ close (fd);
-+ return PAM_SESSION_ERR;
-+ }
-+ close (fd);
-+ pam_syslog (pamh, LOG_ERR, "restored status to %d", status->enabled);
-+ }
-+ return PAM_SUCCESS;
-+}
-diff -urN Linux-PAM/modules/pam_tty_audit/pam_tty_audit.8.xml Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml
---- Linux-PAM/modules/pam_tty_audit/pam_tty_audit.8.xml 1970-01-01 01:00:00.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml 2007-11-28 15:50:22.000000000 +0100
-@@ -0,0 +1,125 @@
-+
-+
-+
-+
-+
-+
-+ pam_tty_audit
-+ 8
-+ Linux-PAM Manual
-+
-+
-+
-+ pam_tty_audit
-+ Enable or disable TTY auditing for specified users
-+
-+
-+
-+
-+ pam_tty_audit.so
-+
-+ disable=usernames
-+
-+
-+ enable=usernames
-+
-+
-+
-+
-+
-+ DESCRIPTION
-+
-+ The pam_tty_audit PAM module is used to enable or disable TTY auditing.
-+ By default, the kernel does not audit input on any TTY.
-+
-+
-+
-+
-+ OPTIONS
-+
-+
-+
-+
-+
-+
-+
-+ For each user matching one of comma-separated
-+ , disable
-+ TTY auditing. This overrides any older
-+ option for the same user name.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ For each user matching one of comma-separated
-+ , enable
-+ TTY auditing. This overrides any older
-+ option for the same user name.
-+
-+
-+
-+
-+
-+
-+
-+ MODULE SERVICES PROVIDED
-+
-+ Only the session service is supported.
-+
-+
-+
-+
-+ RETURN VALUES
-+
-+
-+ PAM_SESSION_ERR
-+
-+
-+ Error reading or modifying the TTY audit flag. See the system log
-+ for more details.
-+
-+
-+
-+
-+
-+ PAM_SUCCESS
-+
-+
-+ Success.
-+
-+
-+
-+
-+
-+
-+
-+
-+ EXAMPLES
-+
-+ Audit all administrative actions.
-+
-+login root required pam_tty_audit.so enable=root
-+su root required pam_tty_audit.so enable=root
-+su-l root required pam_tty_audit.so enable=root
-+sudo root required pam_tty_audit.so enable=root
-+sudo-l root required pam_tty_audit.so enable=root
-+sshd root required pam_tty_audit.so enable=root
-+
-+
-+
-+
-+
-+ AUTHOR
-+
-+ pam_tty_audit was written by Miloslav Trmač
-+ <mitr@redhat.com>.
-+
-+
-+
-+
-diff -urN Linux-PAM/modules/pam_tty_audit/README.xml Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml
---- Linux-PAM/modules/pam_tty_audit/README.xml 1970-01-01 01:00:00.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml 2007-11-28 15:52:50.000000000 +0100
-@@ -0,0 +1,36 @@
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
diff --git a/pam-0.99.8.1-tty-audit2.patch b/pam-0.99.8.1-tty-audit2.patch
deleted file mode 100644
index 4978913..0000000
--- a/pam-0.99.8.1-tty-audit2.patch
+++ /dev/null
@@ -1,233 +0,0 @@
-Written-by: Miloslav Trmac
-Reviewed-by: Tomas Mraz
-diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml
---- Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml.tty-audit2 2008-01-02 11:28:26.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.8.xml 2008-01-02 11:29:55.000000000 +0100
-@@ -19,10 +19,10 @@
-
- pam_tty_audit.so
-
-- disable=usernames
-+ disable=patterns
-
-
-- enable=usernames
-+ enable=patterns
-
-
-
-@@ -40,27 +40,40 @@
-
-
-
--
-+
-
-
-
-- For each user matching one of comma-separated
-- , disable
-- TTY auditing. This overrides any older
-- option for the same user name.
-+ For each user matching one of comma-separated glob
-+ , disable
-+ TTY auditing. This overrides any previous
-+ option matchin the same user name on the command line.
-
-
-
-
-
--
-+
-
-
-
-- For each user matching one of comma-separated
-- , enable
-- TTY auditing. This overrides any older
-- option for the same user name.
-+ For each user matching one of comma-separated glob
-+ , enable
-+ TTY auditing. This overrides any previous
-+ option matching the same user name on the command line.
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+ Set the TTY audit flag when opening the session, but do not restore
-+ it when closing the session. Using this option is necessary for
-+ some services that don't fork() to run the
-+ authenticated session, such as sudo.
-
-
-
-@@ -99,17 +112,24 @@
-
-
-
-+
-+ NOTES
-+
-+ When TTY auditing is enabled, it is inherited by all processes started by
-+ that user. In particular, daemons restarted by an user will still have
-+ TTY auditing enabled, and audit TTY input even by other users unless
-+ auditing for these users is explicitly disabled. Therefore, it is
-+ recommended to use as the first option for
-+ most daemons using PAM.
-+
-+
-+
-
- EXAMPLES
-
- Audit all administrative actions.
-
--login root required pam_tty_audit.so enable=root
--su root required pam_tty_audit.so enable=root
--su-l root required pam_tty_audit.so enable=root
--sudo root required pam_tty_audit.so enable=root
--sudo-l root required pam_tty_audit.so enable=root
--sshd root required pam_tty_audit.so enable=root
-+session required pam_tty_audit.so disable=* enable=root
-
-
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml
---- Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml.tty-audit2 2008-01-02 11:28:26.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/README.xml 2008-01-02 11:28:26.000000000 +0100
-@@ -25,6 +25,11 @@
-
-
-+
-+
-
-diff -up Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c.tty-audit2 Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c
---- Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c.tty-audit2 2008-01-02 11:28:26.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_tty_audit/pam_tty_audit.c 2008-01-02 11:28:26.000000000 +0100
-@@ -1,4 +1,4 @@
--/* Copyright © 2007 Red Hat, Inc. All rights reserved.
-+/* Copyright © 2007, 2008 Red Hat, Inc. All rights reserved.
- Red Hat author: Miloslav Trmač
-
- Redistribution and use in source and binary forms of Linux-PAM, with
-@@ -37,7 +37,7 @@
- DAMAGE. */
-
- #include
--#include
-+#include
- #include
- #include
- #include
-@@ -197,9 +197,7 @@ pam_sm_open_session (pam_handle_t *pamh,
- enum command command;
- struct audit_tty_status *old_status, new_status;
- const char *user;
-- uid_t user_uid;
-- struct passwd *pwd;
-- int i, fd;
-+ int i, fd, open_only;
-
- (void)flags;
-
-@@ -208,15 +206,9 @@ pam_sm_open_session (pam_handle_t *pamh,
- pam_syslog (pamh, LOG_ERR, "error determining target user's name");
- return PAM_SESSION_ERR;
- }
-- pwd = pam_modutil_getpwnam (pamh, user);
-- if (pwd == NULL)
-- {
-- pam_syslog (pamh, LOG_ERR, "error determining target user's UID: %m");
-- return PAM_SESSION_ERR;
-- }
-- user_uid = pwd->pw_uid;
-
- command = CMD_NONE;
-+ open_only = 0;
- for (i = 0; i < argc; i++)
- {
- if (strncmp (argv[i], "enable=", 7) == 0
-@@ -232,13 +224,7 @@ pam_sm_open_session (pam_handle_t *pamh,
- for (tok = strtok_r (copy, ",", &tok_data); tok != NULL;
- tok = strtok_r (NULL, ",", &tok_data))
- {
-- pwd = pam_modutil_getpwnam (pamh, tok);
-- if (pwd == NULL)
-- {
-- pam_syslog (pamh, LOG_WARNING, "unknown user %s", tok);
-- continue;
-- }
-- if (pwd->pw_uid == user_uid)
-+ if (fnmatch (tok, user, 0) == 0)
- {
- command = this_command;
- break;
-@@ -246,6 +232,13 @@ pam_sm_open_session (pam_handle_t *pamh,
- }
- free (copy);
- }
-+ else if (strcmp (argv[i], "open_only") == 0)
-+ open_only = 1;
-+ else
-+ {
-+ pam_syslog (pamh, LOG_ERR, "unknown option `%s'", argv[i]);
-+ return PAM_SESSION_ERR;
-+ }
- }
- if (command == CMD_NONE)
- return PAM_SUCCESS;
-@@ -266,13 +259,15 @@ pam_sm_open_session (pam_handle_t *pamh,
- return PAM_SESSION_ERR;
- }
-
-- if (old_status->enabled == (command == CMD_ENABLE ? 1 : 0))
-+ new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
-+ if (old_status->enabled == new_status.enabled)
- {
- free (old_status);
- goto ok_fd;
- }
-
-- if (pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
-+ if (open_only == 0
-+ && pam_set_data (pamh, DATANAME, old_status, cleanup_old_status)
- != PAM_SUCCESS)
- {
- pam_syslog (pamh, LOG_ERR, "error saving old audit status");
-@@ -281,13 +276,14 @@ pam_sm_open_session (pam_handle_t *pamh,
- return PAM_SESSION_ERR;
- }
-
-- new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
- if (nl_send (fd, AUDIT_TTY_SET, NLM_F_ACK, &new_status,
- sizeof (new_status)) != 0
- || nl_recv_ack (fd) != 0)
- {
- pam_syslog (pamh, LOG_ERR, "error setting current audit status: %m");
- close (fd);
-+ if (open_only != 0)
-+ free (old_status);
- return PAM_SESSION_ERR;
- }
- /* Fall through */
-@@ -295,6 +291,8 @@ pam_sm_open_session (pam_handle_t *pamh,
- close (fd);
- pam_syslog (pamh, LOG_DEBUG, "changed status from %d to %d",
- old_status->enabled, new_status.enabled);
-+ if (open_only != 0)
-+ free (old_status);
- return PAM_SUCCESS;
- }
-
diff --git a/pam-0.99.8.1-unix-hpux-aging.patch b/pam-0.99.8.1-unix-hpux-aging.patch
deleted file mode 100644
index 72966dc..0000000
--- a/pam-0.99.8.1-unix-hpux-aging.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h.unix-hpux-aging Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h
---- Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h.unix-hpux-aging 2008-01-08 14:43:36.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h 2008-01-08 15:49:43.000000000 +0100
-@@ -13,7 +13,7 @@
- #define OLD_PASSWORDS_FILE "/etc/security/opasswd"
-
- int
--verify_pwd_hash(const char *p, const char *hash, unsigned int nullok);
-+verify_pwd_hash(const char *p, char *hash, unsigned int nullok);
-
- int
- is_pwd_shadowed(const struct passwd *pwd);
-diff -up Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c.unix-hpux-aging Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c
---- Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c.unix-hpux-aging 2008-01-08 14:43:36.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c 2008-01-08 15:49:02.000000000 +0100
-@@ -44,14 +44,32 @@
- # include "./lckpwdf.-c"
- #endif
-
-+static void
-+strip_hpux_aging(char *p)
-+{
-+ const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-+ "abcdefghijklmnopqrstuvwxyz"
-+ "0123456789./";
-+ if ((*p != '$') && (strlen(p) > 13)) {
-+ for (p += 13; *p != '\0'; p++) {
-+ if (strchr(valid, *p) == NULL) {
-+ *p = '\0';
-+ break;
-+ }
-+ }
-+ }
-+}
-+
- int
--verify_pwd_hash(const char *p, const char *hash, unsigned int nullok)
-+verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
- {
-- size_t hash_len = strlen(hash);
-+ size_t hash_len;
- char *pp = NULL;
- int retval;
- D(("called"));
-
-+ strip_hpux_aging(hash);
-+ hash_len = strlen(hash);
- if (!hash_len) {
- /* the stored password is NULL */
- if (nullok) { /* this means we've succeeded */
diff --git a/pam-0.99.8.1-unix-update-helper.patch b/pam-0.99.8.1-unix-update-helper.patch
deleted file mode 100644
index c4e1b42..0000000
--- a/pam-0.99.8.1-unix-update-helper.patch
+++ /dev/null
@@ -1,3723 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c
---- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c.update-helper 2006-06-17 18:44:58.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_sess.c 2008-01-07 16:39:07.000000000 +0100
-@@ -73,7 +73,7 @@ PAM_EXTERN int pam_sm_open_session(pam_h
-
- D(("called."));
-
-- ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
-+ ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
-
- retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
- if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
-@@ -107,7 +107,7 @@ PAM_EXTERN int pam_sm_close_session(pam_
-
- D(("called."));
-
-- ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
-+ ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
-
- retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
- if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
-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 2008-01-08 16:17:32.000000000 +0100
-@@ -2,6 +2,7 @@
- * Main coding by Elliot Lee , Red Hat Software.
- * Copyright (C) 1996.
- * Copyright (c) Jan Rkorajski, 1999.
-+ * Copyright (c) Red Hat, Inc., 2007, 2008.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
-@@ -63,7 +64,6 @@
- #ifdef WITH_SELINUX
- static int selinux_enabled=-1;
- #include
--static security_context_t prev_context=NULL;
- #define SELINUX_ENABLED (selinux_enabled!=-1 ? selinux_enabled : (selinux_enabled=is_selinux_enabled()>0))
- #endif
-
-@@ -84,6 +84,7 @@ static security_context_t prev_context=N
- #include "yppasswd.h"
- #include "md5.h"
- #include "support.h"
-+#include "passverify.h"
- #include "bigcrypt.h"
-
- #if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
-@@ -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);
-@@ -354,393 +288,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)
-@@ -768,9 +315,7 @@ static int _do_setpass(pam_handle_t* pam
- enum clnt_stat err;
-
- /* Unlock passwd file to avoid deadlock */
--#ifdef USE_LCKPWDF
-- ulckpwdf();
--#endif
-+ unlock_pwdf();
- unlocked = 1;
-
- /* Initialize password information */
-@@ -830,129 +375,63 @@ 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;
- }
- }
-+#ifdef WITH_SELINUX
-+ if (unix_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 (on(UNIX_SHADOW, ctrl) || is_pwd_shadowed(pwd)) {
-+ retval = unix_update_shadow(pamh, forwho, towhat);
- if (retval == PAM_SUCCESS)
-- if (!_unix_shadowed(pwd))
-- retval = _update_passwd(pamh, forwho, "x");
-+ if (!is_pwd_shadowed(pwd))
-+ retval = unix_update_passwd(pamh, forwho, "x");
- } else {
-- retval = _update_passwd(pamh, forwho, towhat);
-+ retval = unix_update_passwd(pamh, forwho, towhat);
- }
- }
-
-
- done:
--#ifdef USE_LCKPWDF
-- ulckpwdf();
--#endif
-+ unlock_pwdf();
-
- return retval;
- }
-
- static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned int ctrl)
- {
-- struct passwd *pwd = NULL; /* Password and shadow password */
-- struct spwd *spwdent = NULL; /* file entries for the user */
-- time_t curdays;
-- int retval = PAM_SUCCESS;
-+ struct passwd *pwent = NULL; /* Password and shadow password */
-+ struct spwd *spent = NULL; /* file entries for the user */
-+ int daysleft;
-+ int retval;
-
-- /* UNIX passwords area */
-- pwd = getpwnam(user); /* Get password file entry... */
-- if (pwd == NULL)
-- return PAM_AUTHINFO_UNAVAIL; /* We don't need to do the rest... */
--
-- if (_unix_shadowed(pwd)) {
-- /* ...and shadow password file entry for this user, if shadowing
-- is enabled */
-- setspent();
-- spwdent = getspnam(user);
-- endspent();
-+ retval = get_account_info(pamh, user, &pwent, &spent);
-+ if (retval == PAM_USER_UNKNOWN) {
-+ return retval;
-+ }
-
--#ifdef WITH_SELINUX
-- if (spwdent == NULL && SELINUX_ENABLED )
-- spwdent = _unix_run_verify_binary(pamh, ctrl, user);
--#endif
-- if (spwdent == NULL)
-- return PAM_AUTHINFO_UNAVAIL;
-- } else {
-- if (strcmp(pwd->pw_passwd,"*NP*") == 0) { /* NIS+ */
-- uid_t save_uid;
-+ if (retval == PAM_SUCCESS && spent == NULL)
-+ return PAM_SUCCESS;
-
-- save_uid = geteuid();
-- seteuid (pwd->pw_uid);
-- spwdent = getspnam( user );
-- seteuid (save_uid);
--
-- if (spwdent == NULL)
-- return PAM_AUTHINFO_UNAVAIL;
-- } else
-- spwdent = NULL;
-+ if (retval == PAM_UNIX_RUN_HELPER) {
-+ retval = _unix_run_verify_binary(pamh, ctrl, user, &daysleft);
-+ if (retval == PAM_AUTH_ERR || retval == PAM_USER_UNKNOWN)
-+ return retval;
- }
-+ else if (retval == PAM_SUCCESS)
-+ retval = check_shadow_expiry(pamh, spent, &daysleft);
-+
-+ if (on(UNIX__IAMROOT, ctrl) || retval == PAM_NEW_AUTHTOK_REQD)
-+ return PAM_SUCCESS;
-
-- if (spwdent != NULL) {
-- /* We have the user's information, now let's check if their account
-- has expired (60 * 60 * 24 = number of seconds in a day) */
--
-- if (off(UNIX__IAMROOT, ctrl)) {
-- /* Get the current number of days since 1970 */
-- curdays = time(NULL) / (60 * 60 * 24);
-- if (curdays < spwdent->sp_lstchg) {
-- pam_syslog(pamh, LOG_DEBUG,
-- "account %s has password changed in future",
-- user);
-- curdays = spwdent->sp_lstchg;
-- }
-- if ((curdays - spwdent->sp_lstchg < spwdent->sp_min)
-- && (spwdent->sp_min != -1))
-- /*
-- * The last password change was too recent.
-- */
-- retval = PAM_AUTHTOK_ERR;
-- else if ((curdays - spwdent->sp_lstchg > spwdent->sp_max)
-- && (curdays - spwdent->sp_lstchg > spwdent->sp_inact)
-- && (curdays - spwdent->sp_lstchg >
-- spwdent->sp_max + spwdent->sp_inact)
-- && (spwdent->sp_max != -1) && (spwdent->sp_inact != -1)
-- && (spwdent->sp_lstchg != 0))
-- /*
-- * Their password change has been put off too long,
-- */
-- retval = PAM_ACCT_EXPIRED;
-- else if ((curdays > spwdent->sp_expire) && (spwdent->sp_expire != -1)
-- && (spwdent->sp_lstchg != 0))
-- /*
-- * OR their account has just plain expired
-- */
-- retval = PAM_ACCT_EXPIRED;
-- }
-- }
- return retval;
- }
-
-@@ -1020,8 +499,9 @@ 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;
-+ int rounds = -1;
-
- /* */
- const char *user;
-@@ -1030,7 +510,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand
-
- D(("called."));
-
-- ctrl = _set_ctrl(pamh, flags, &remember, argc, argv);
-+ ctrl = _set_ctrl(pamh, flags, &remember, &rounds, argc, argv);
-
- /*
- * First get the name of a user
-@@ -1239,40 +719,23 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand
- pass_new = pass_old = NULL; /* tidy up */
- 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) {
- 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();
--#endif
-+ unlock_pwdf();
- return retval;
- }
- }
-
- retval = _unix_verify_shadow(pamh, user, ctrl);
- if (retval != PAM_SUCCESS) {
-- pam_syslog(pamh, LOG_NOTICE, "user not authenticated 2");
--#ifdef USE_LCKPWDF
-- ulckpwdf();
--#endif
-+ pam_syslog(pamh, LOG_NOTICE, "user shadow entry expired");
-+ unlock_pwdf();
- return retval;
- }
-
-@@ -1281,9 +744,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand
- pam_syslog(pamh, LOG_NOTICE,
- "new password not acceptable 2");
- pass_new = pass_old = NULL; /* tidy up */
--#ifdef USE_LCKPWDF
-- ulckpwdf();
--#endif
-+ unlock_pwdf();
- return retval;
- }
-
-@@ -1296,51 +757,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_hand
- * First we encrypt the new password.
- */
-
-- if (on(UNIX_MD5_PASS, ctrl)) {
-- tpass = crypt_md5_wrapper(pass_new);
-- } else {
-- /*
-- * Salt manipulation is stolen from Rick Faith's passwd
-- * program. Sorry Rick :) -- alex
-- */
--
-- time_t tm;
-- char salt[3];
--
-- time(&tm);
-- salt[0] = bin_to_ascii(tm & 0x3f);
-- salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
-- salt[2] = '\0';
--
-- if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) {
-- /*
-- * to avoid using the _extensions_ of the bigcrypt()
-- * function we truncate the newly entered password
-- * [Problems that followed from this are fixed as per
-- * Bug 521314.]
-- */
-- char *temp = malloc(9);
--
-- if (temp == NULL) {
-- pam_syslog(pamh, LOG_CRIT,
-- "out of memory for password");
-- pass_new = pass_old = NULL; /* tidy up */
--#ifdef USE_LCKPWDF
-- ulckpwdf();
--#endif
-- return PAM_BUF_ERR;
-- }
-- /* copy first 8 bytes of password */
-- strncpy(temp, pass_new, 8);
-- temp[8] = '\0';
--
-- /* no longer need cleartext */
-- tpass = bigcrypt(temp, salt);
--
-- _pam_delete(temp); /* tidy up */
-- } else {
-- tpass = bigcrypt(pass_new, salt);
-- }
-+ tpass = create_password_hash(pass_new, ctrl, rounds);
-+ if (tpass == NULL) {
-+ pam_syslog(pamh, LOG_CRIT,
-+ "out of memory for password");
-+ pass_new = pass_old = NULL; /* tidy up */
-+ unlock_pwdf();
-+ return PAM_BUF_ERR;
- }
-
- D(("password processed"));
-@@ -1349,7 +772,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 2008-01-08 16:17:32.000000000 +0100
-@@ -13,7 +13,6 @@
-
- #include "config.h"
-
--#include
- #include
- #include
- #include
-@@ -25,401 +24,34 @@
- #include
- #include
- #include
--#ifdef WITH_SELINUX
--#include
--#define SELINUX_ENABLED (selinux_enabled!=-1 ? selinux_enabled : (selinux_enabled=is_selinux_enabled()>0))
--static security_context_t prev_context=NULL;
--static int selinux_enabled=-1;
--#else
--#define SELINUX_ENABLED 0
--#endif
--
--#define MAXPASS 200 /* the maximum length of a password */
-
- #include
- #include
-
--#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);
--}
-+#include "passverify.h"
-
--static int _verify_account(const char * const uname)
-+static int _check_expiry(const char *uname)
- {
- struct spwd *spent;
- struct passwd *pwent;
-+ int retval;
-+ int daysleft;
-
-- 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;
-- }
-+ retval = get_account_info(uname, &pwent, &spent);
-+ if (retval != PAM_SUCCESS) {
-+ helper_log_err(LOG_ALERT, "could not obtain user info (%s)", uname);
-+ printf("-1\n");
-+ return retval;
-+ }
-+
-+ if (spent == NULL) {
-+ printf("-1\n");
-+ return retval;
- }
-- 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) {
-+ retval = check_shadow_expiry(spent, &daysleft);
-+ printf("%d\n", daysleft);
- 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;
-- }
- }
-
- int main(int argc, char *argv[])
-@@ -427,9 +59,10 @@ int main(int argc, char *argv[])
- char pass[MAXPASS + 1];
- char *option;
- int npass, nullok;
-- int force_failure = 0;
-+ int blankpass = 0;
- int retval = PAM_AUTH_ERR;
- char *user;
-+ char *passwords[] = { pass };
-
- /*
- * Catch or ignore as many signal as possible.
-@@ -446,7 +79,7 @@ int main(int argc, char *argv[])
- */
-
- if (isatty(STDIN_FILENO) || argc != 3 ) {
-- _log_err(LOG_NOTICE
-+ helper_log_err(LOG_NOTICE
- ,"inappropriate use of Unix helper binary [UID=%d]"
- ,getuid());
- fprintf(stderr
-@@ -458,11 +91,9 @@ int main(int argc, char *argv[])
-
- /*
- * Determine what the current user's name is.
-- * On a SELinux enabled system with a strict policy leaving the
-- * existing check prevents shadow password authentication from working.
- * We must thus skip the check if the real uid is 0.
- */
-- if (SELINUX_ENABLED && getuid() == 0) {
-+ if (getuid() == 0) {
- user=argv[1];
- }
- else {
-@@ -476,63 +107,49 @@ 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]);
-- }
--
-+ if (strcmp(option, "chkexpiry") == 0)
-+ /* Check account information from the shadow file */
-+ return _check_expiry(argv[1]);
- /* read the nullok/nonull option */
-- if (strncmp(option, "nullok", 8) == 0)
-+ else if (strcmp(option, "nullok") == 0)
- nullok = 1;
-- else
-+ else if (strcmp(option, "nonull") == 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? */
-+ helper_log_err(LOG_DEBUG, "no password supplied");
-+ *pass = '\0';
-+ }
-
-- }
-+ if (*pass == '\0') {
-+ blankpass = 1;
- }
-
-+ retval = helper_verify_password(user, pass, nullok);
-+
- memset(pass, '\0', MAXPASS); /* clear memory of the password */
-
- /* return pass or fail */
-
-- if ((retval != PAM_SUCCESS) || force_failure) {
-- _log_err(LOG_NOTICE, "password check failed for user (%s)", user);
-- return PAM_AUTH_ERR;
-+ if (retval != PAM_SUCCESS) {
-+ if (!nullok || !blankpass)
-+ /* no need to log blank pass test */
-+ helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user);
-+ return PAM_AUTH_ERR;
- } else {
-- return PAM_SUCCESS;
-+ return PAM_SUCCESS;
- }
- }
-
- /*
- * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
-+ * Copyright (c) Red Hat, Inc., 2007,2008. All rights reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
-diff -up Linux-PAM-0.99.8.1/modules/pam_unix/support.h.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/support.h
---- Linux-PAM-0.99.8.1/modules/pam_unix/support.h.update-helper 2007-01-23 10:30:23.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/support.h 2008-01-08 16:17:32.000000000 +0100
-@@ -1,5 +1,5 @@
- /*
-- * $Id: pam-0.99.8.1-unix-update-helper.patch,v 1.3 2008/01/08 18:54:47 tmraz Exp $
-+ * $Id: pam-0.99.8.1-unix-update-helper.patch,v 1.3 2008/01/08 18:54:47 tmraz Exp $
- */
-
- #ifndef _PAM_UNIX_SUPPORT_H
-@@ -84,8 +84,12 @@ typedef struct {
- #define UNIX_NOREAP 21 /* don't reap child process */
- #define UNIX_BROKEN_SHADOW 22 /* ignore errors reading password aging
- * information during acct management */
-+#define UNIX_SHA256_PASS 23 /* new password hashes will use SHA256 */
-+#define UNIX_SHA512_PASS 24 /* new password hashes will use SHA512 */
-+#define UNIX_ALGO_ROUNDS 25 /* optional number of rounds for new
-+ password hash algorithms */
- /* -------------- */
--#define UNIX_CTRLS_ 23 /* number of ctrl arguments defined */
-+#define UNIX_CTRLS_ 26 /* number of ctrl arguments defined */
-
-
- static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
-@@ -116,6 +120,9 @@ static const UNIX_Ctrls unix_args[UNIX_C
- /* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000},
- /* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000},
- /* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000},
-+/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(040420000), 020000000},
-+/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(020420000), 040000000},
-+/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000},
- };
-
- #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
-@@ -131,8 +138,8 @@ static const UNIX_Ctrls unix_args[UNIX_C
-
- extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl
- ,int type, const char *text);
--extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int argc,
-- const char **argv);
-+extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int *rounds,
-+ int argc, const char **argv);
- extern int _unix_getpwnam (pam_handle_t *pamh,
- const char *name, int files, int nis,
- struct passwd **ret);
-@@ -149,7 +156,7 @@ extern int _unix_read_password(pam_handl
- ,const char *prompt2
- ,const char *data_name
- ,const void **pass);
--extern int _unix_shadowed(const struct passwd *pwd);
-
--extern struct spwd *_unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user);
-+extern int _unix_run_verify_binary(pam_handle_t *pamh,
-+ unsigned int ctrl, const char *user, int *daysleft);
- #endif /* _PAM_UNIX_SUPPORT_H */
-diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h
---- /dev/null 2008-01-05 20:21:31.621001512 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.h 2008-01-08 16:17:32.000000000 +0100
-@@ -0,0 +1,124 @@
-+/*
-+ * Copyright information at end of file.
-+ */
-+
-+#include
-+#include
-+#include
-+
-+#define PAM_UNIX_RUN_HELPER PAM_CRED_INSUFFICIENT
-+
-+#define MAXPASS 200 /* the maximum length of a password */
-+
-+#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
-+
-+int
-+verify_pwd_hash(const char *p, const char *hash, unsigned int nullok);
-+
-+int
-+is_pwd_shadowed(const struct passwd *pwd);
-+
-+char *
-+crypt_md5_wrapper(const char *pass_new);
-+
-+char *
-+create_password_hash(const char *password, unsigned int ctrl, int rounds);
-+
-+int
-+unix_selinux_confined(void);
-+
-+int
-+lock_pwdf(void);
-+
-+void
-+unlock_pwdf(void);
-+
-+int
-+save_old_password(const char *forwho, const char *oldpass,
-+ int howmany);
-+
-+#ifdef HELPER_COMPILE
-+void
-+helper_log_err(int err, const char *format,...);
-+
-+int
-+helper_verify_password(const char *name, const char *p, int nullok);
-+
-+void
-+setup_signals(void);
-+
-+char *
-+getuidname(uid_t uid);
-+
-+int
-+read_passwords(int fd, int npass, char **passwords);
-+
-+int
-+get_account_info(const char *name,
-+ struct passwd **pwd, struct spwd **spwdent);
-+
-+int
-+get_pwd_hash(const char *name,
-+ struct passwd **pwd, char **hash);
-+
-+int
-+check_shadow_expiry(struct spwd *spent, int *daysleft);
-+
-+int
-+unix_update_passwd(const char *forwho, const char *towhat);
-+
-+int
-+unix_update_shadow(const char *forwho, char *towhat);
-+#else
-+int
-+get_account_info(pam_handle_t *pamh, const char *name,
-+ struct passwd **pwd, struct spwd **spwdent);
-+
-+int
-+get_pwd_hash(pam_handle_t *pamh, const char *name,
-+ struct passwd **pwd, char **hash);
-+
-+int
-+check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft);
-+
-+int
-+unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat);
-+
-+int
-+unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat);
-+#endif
-+
-+/* ****************************************************************** *
-+ * 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
-+ * 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 2008-01-08 16:17:32.000000000 +0100
-@@ -47,10 +47,6 @@
- #include /* for time() */
- #include
- #include
--#ifdef WITH_SELINUX
--#include
--#define SELINUX_ENABLED is_selinux_enabled()>0
--#endif
-
- #include
-
-@@ -63,12 +59,10 @@
- #include
-
- #include "support.h"
-+#include "passverify.h"
-
--#ifdef WITH_SELINUX
--
--struct spwd spwd;
--
--struct spwd *_unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user)
-+int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
-+ const char *user, int *daysleft)
- {
- int retval=0, child, fds[2];
- void (*sighandler)(int) = NULL;
-@@ -78,7 +72,7 @@ struct spwd *_unix_run_verify_binary(pam
- if (pipe(fds) != 0) {
- D(("could not make pipe"));
- pam_syslog(pamh, LOG_ERR, "Could not make pipe: %m");
-- return NULL;
-+ return PAM_AUTH_ERR;
- }
- D(("called."));
-
-@@ -117,7 +111,7 @@ struct spwd *_unix_run_verify_binary(pam
- }
- }
-
-- if (SELINUX_ENABLED && geteuid() == 0) {
-+ if (geteuid() == 0) {
- /* must set the real uid to 0 so the helper will not error
- out if pam is called from setuid binary (su, sudo...) */
- setuid(0);
-@@ -126,7 +120,7 @@ struct spwd *_unix_run_verify_binary(pam
- /* exec binary helper */
- args[0] = x_strdup(CHKPWD_HELPER);
- args[1] = x_strdup(user);
-- args[2] = x_strdup("verify");
-+ args[2] = x_strdup("chkexpiry");
-
- execve(CHKPWD_HELPER, args, envp);
-
-@@ -134,11 +128,12 @@ struct spwd *_unix_run_verify_binary(pam
- /* should not get here: exit with error */
- close (fds[1]);
- D(("helper binary is not available"));
-+ printf("-1\n");
- exit(PAM_AUTHINFO_UNAVAIL);
- } else {
- close(fds[1]);
- if (child > 0) {
-- char buf[1024];
-+ char buf[32];
- int rc=0;
- rc=waitpid(child, &retval, 0); /* wait for helper to complete */
- if (rc<0) {
-@@ -146,22 +141,16 @@ struct spwd *_unix_run_verify_binary(pam
- retval = PAM_AUTH_ERR;
- } else {
- retval = WEXITSTATUS(retval);
-- if (retval != PAM_AUTHINFO_UNAVAIL) {
-- rc = pam_modutil_read(fds[0], buf, sizeof(buf) - 1);
-- if(rc > 0) {
-+ rc = pam_modutil_read(fds[0], buf, sizeof(buf) - 1);
-+ if(rc > 0) {
- buf[rc] = '\0';
-- if (sscanf(buf,"%ld:%ld:%ld:%ld:%ld:%ld",
-- &spwd.sp_lstchg, /* last password change */
-- &spwd.sp_min, /* days until change allowed. */
-- &spwd.sp_max, /* days before change required */
-- &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;
-+ if (sscanf(buf,"%d", daysleft) != 1 )
-+ 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 unix_chkpwd output error %d: %m", rc);
-+ retval = PAM_AUTH_ERR;
- }
-- }
- }
- } else {
- pam_syslog(pamh, LOG_ERR, "Fork failed: %m");
-@@ -174,15 +163,9 @@ struct spwd *_unix_run_verify_binary(pam
- (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
- }
- D(("Returning %d",retval));
-- if (retval != PAM_SUCCESS) {
-- return NULL;
-- }
-- return &spwd;
-+ return retval;
- }
-
--#endif
--
--
- /*
- * PAM framework looks for this entry-point to pass control to the
- * account management module.
-@@ -195,14 +178,13 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_hand
- const void *void_uname;
- const char *uname;
- int retval, daysleft;
-- time_t curdays;
- struct spwd *spent;
- struct passwd *pwent;
- char buf[256];
-
- D(("called."));
-
-- ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
-+ ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
-
- retval = pam_get_item(pamh, PAM_USER, &void_uname);
- uname = void_uname;
-@@ -214,134 +196,90 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_hand
- return PAM_USER_UNKNOWN;
- }
-
-- pwent = pam_modutil_getpwnam(pamh, uname);
-- if (!pwent) {
-+ retval = get_account_info(pamh, uname, &pwent, &spent);
-+ if (retval == PAM_USER_UNKNOWN) {
- pam_syslog(pamh, LOG_ALERT,
- "could not identify user (from getpwnam(%s))",
- uname);
-- return PAM_USER_UNKNOWN;
-+ return retval;
- }
-
-- if (!strcmp( pwent->pw_passwd, "*NP*" )) { /* NIS+ */
-- uid_t save_euid, save_uid;
--
-- save_euid = geteuid();
-- save_uid = getuid();
-- if (save_uid == pwent->pw_uid)
-- setreuid( save_euid, save_uid );
-- else {
-- setreuid( 0, -1 );
-- if (setreuid( -1, pwent->pw_uid ) == -1) {
-- setreuid( -1, 0 );
-- setreuid( 0, -1 );
-- if(setreuid( -1, pwent->pw_uid ) == -1)
-- return PAM_CRED_INSUFFICIENT;
-- }
-- }
-- spent = pam_modutil_getspnam (pamh, uname);
-- if (save_uid == pwent->pw_uid)
-- setreuid( save_uid, save_euid );
-- else {
-- if (setreuid( -1, 0 ) == -1)
-- setreuid( save_uid, -1 );
-- setreuid( -1, save_euid );
-- }
--
-- } else if (_unix_shadowed (pwent))
-- spent = pam_modutil_getspnam (pamh, uname);
-- else
-+ if (retval == PAM_SUCCESS && spent == NULL)
- return PAM_SUCCESS;
-
--#ifdef WITH_SELINUX
-- if (!spent && SELINUX_ENABLED )
-- spent = _unix_run_verify_binary(pamh, ctrl, uname);
--#endif
--
-- if (!spent)
-+ if (retval == PAM_UNIX_RUN_HELPER) {
-+ retval = _unix_run_verify_binary(pamh, ctrl, uname, &daysleft);
-+ if (retval == PAM_AUTHINFO_UNAVAIL &&
-+ on(UNIX_BROKEN_SHADOW, ctrl))
-+ return PAM_SUCCESS;
-+ } else if (retval != PAM_SUCCESS) {
- if (on(UNIX_BROKEN_SHADOW,ctrl))
- return PAM_SUCCESS;
-+ else
-+ return retval;
-+ } else
-+ retval = check_shadow_expiry(pamh, spent, &daysleft);
-
-- if (!spent)
-- return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */
--
-- curdays = time(NULL) / (60 * 60 * 24);
-- D(("today is %d, last change %d", curdays, spent->sp_lstchg));
-- if ((curdays > spent->sp_expire) && (spent->sp_expire != -1)) {
-+ switch (retval) {
-+ case PAM_ACCT_EXPIRED:
- pam_syslog(pamh, LOG_NOTICE,
-- "account %s has expired (account expired)",
-- uname);
-+ "account %s has expired (account expired)",
-+ uname);
- _make_remark(pamh, ctrl, PAM_ERROR_MSG,
-- _("Your account has expired; please contact your system administrator"));
-- D(("account expired"));
-- return PAM_ACCT_EXPIRED;
-- }
-- if (spent->sp_lstchg == 0) {
-- pam_syslog(pamh, LOG_NOTICE,
-- "expired password for user %s (root enforced)",
-- uname);
-- _make_remark(pamh, ctrl, PAM_ERROR_MSG,
-- _("You are required to change your password immediately (root enforced)"));
-- D(("need a new password"));
-- return PAM_NEW_AUTHTOK_REQD;
-- }
-- if (curdays < spent->sp_lstchg) {
-- pam_syslog(pamh, LOG_DEBUG,
-- "account %s has password changed in future",
-- uname);
-- return PAM_SUCCESS;
-- }
-- if ((curdays - spent->sp_lstchg > spent->sp_max)
-- && (curdays - spent->sp_lstchg > spent->sp_inact)
-- && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact)
-- && (spent->sp_max != -1) && (spent->sp_inact != -1)) {
-+ _("Your account has expired; please contact your system administrator"));
-+ break;
-+ case PAM_NEW_AUTHTOK_REQD:
-+ if (daysleft == 0) {
-+ pam_syslog(pamh, LOG_NOTICE,
-+ "expired password for user %s (root enforced)",
-+ uname);
-+ _make_remark(pamh, ctrl, PAM_ERROR_MSG,
-+ _("You are required to change your password immediately (root enforced)"));
-+ } else {
-+ pam_syslog(pamh, LOG_DEBUG,
-+ "expired password for user %s (password aged)",
-+ uname);
-+ _make_remark(pamh, ctrl, PAM_ERROR_MSG,
-+ _("You are required to change your password immediately (password aged)"));
-+ }
-+ break;
-+ case PAM_AUTHTOK_EXPIRED:
- pam_syslog(pamh, LOG_NOTICE,
-- "account %s has expired (failed to change password)",
-- uname);
-- _make_remark(pamh, ctrl, PAM_ERROR_MSG,
-- _("Your account has expired; please contact your system administrator"));
-- D(("account expired 2"));
-- return PAM_ACCT_EXPIRED;
-- }
-- if ((curdays - spent->sp_lstchg > spent->sp_max) && (spent->sp_max != -1)) {
-- pam_syslog(pamh, LOG_DEBUG,
-- "expired password for user %s (password aged)",
-- uname);
-+ "account %s has expired (failed to change password)",
-+ uname);
- _make_remark(pamh, ctrl, PAM_ERROR_MSG,
-- _("You are required to change your password immediately (password aged)"));
-- D(("need a new password 2"));
-- return PAM_NEW_AUTHTOK_REQD;
-- }
-- if ((curdays - spent->sp_lstchg > spent->sp_max - spent->sp_warn)
-- && (spent->sp_max != -1) && (spent->sp_warn != -1)) {
-- daysleft = (spent->sp_lstchg + spent->sp_max) - curdays;
-- pam_syslog(pamh, LOG_DEBUG,
-- "password for user %s will expire in %d days",
-- uname, daysleft);
--#ifdef HAVE_DNGETTEXT
-- snprintf (buf, sizeof (buf),
-- dngettext(PACKAGE,
-- "Warning: your password will expire in %d day",
-- "Warning: your password will expire in %d days",
-- daysleft),
-- daysleft);
-+ _("Your account has expired; please contact your system administrator"));
-+ break;
-+ case PAM_SUCCESS:
-+ if (daysleft >= 0) {
-+ pam_syslog(pamh, LOG_DEBUG,
-+ "password for user %s will expire in %d days",
-+ uname, daysleft);
-+#if defined HAVE_DNGETTEXT && defined ENABLE_NLS
-+ snprintf (buf, sizeof (buf),
-+ dngettext(PACKAGE,
-+ "Warning: your password will expire in %d day",
-+ "Warning: your password will expire in %d days",
-+ daysleft),
-+ daysleft);
- #else
-- if (daysleft == 1)
-- snprintf(buf, sizeof (buf),
-- _("Warning: your password will expire in %d day"),
-- daysleft);
-- else
-- snprintf(buf, sizeof (buf),
-- /* TRANSLATORS: only used if dngettext is not support
--ed */
-- _("Warning: your password will expire in %d days"),
-- daysleft);
-+ if (daysleft == 1)
-+ snprintf(buf, sizeof (buf),
-+ _("Warning: your password will expire in %d day"),
-+ daysleft);
-+ else
-+ snprintf(buf, sizeof (buf),
-+ /* TRANSLATORS: only used if dngettext is not supported */
-+ _("Warning: your password will expire in %d days"),
-+ daysleft);
- #endif
-- _make_remark(pamh, ctrl, PAM_TEXT_INFO, buf);
-+ _make_remark(pamh, ctrl, PAM_TEXT_INFO, buf);
-+ }
- }
-
- D(("all done"));
-
-- return PAM_SUCCESS;
-+ return retval;
- }
-
-
-diff -up /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/unix_update.c
---- /dev/null 2008-01-05 20:21:31.621001512 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/unix_update.c 2008-01-08 16:17:32.000000000 +0100
-@@ -0,0 +1,194 @@
-+/*
-+ * 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.
-+ *
-+ */
-+
-+#include "config.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#ifdef WITH_SELINUX
-+#include
-+#define SELINUX_ENABLED (selinux_enabled!=-1 ? selinux_enabled : (selinux_enabled=is_selinux_enabled()>0))
-+static int selinux_enabled=-1;
-+#else
-+#define SELINUX_ENABLED 0
-+#endif
-+
-+#include
-+#include
-+
-+#include "passverify.h"
-+
-+static int
-+set_password(const char *forwho, const char *shadow, const char *remember)
-+{
-+ struct passwd *pwd = NULL;
-+ int retval;
-+ char pass[MAXPASS + 1];
-+ char towhat[MAXPASS + 1];
-+ int npass = 0;
-+ /* we don't care about number format errors because the helper
-+ should be called internally only */
-+ int doshadow = atoi(shadow);
-+ int nremember = atoi(remember);
-+ char *passwords[] = { pass, towhat };
-+
-+ /* read the password from stdin (a pipe from the pam_unix module) */
-+
-+ npass = read_passwords(STDIN_FILENO, 2, passwords);
-+
-+ if (npass != 2) { /* is it a valid password? */
-+ if (npass == 1) {
-+ helper_log_err(LOG_DEBUG, "no new password supplied");
-+ memset(pass, '\0', MAXPASS);
-+ } else {
-+ helper_log_err(LOG_DEBUG, "no valid passwords supplied");
-+ }
-+ return PAM_AUTHTOK_ERR;
-+ }
-+
-+ if (lock_pwdf() != PAM_SUCCESS)
-+ return PAM_AUTHTOK_LOCK_BUSY;
-+
-+ pwd = getpwnam(forwho);
-+
-+ if (pwd == NULL) {
-+ retval = PAM_USER_UNKNOWN;
-+ goto done;
-+ }
-+
-+ /* does pass agree with the official one?
-+ we always allow change from null pass */
-+ retval = helper_verify_password(forwho, pass, 1);
-+ if (retval != PAM_SUCCESS) {
-+ goto done;
-+ }
-+
-+ /* first, save old password */
-+ if (save_old_password(forwho, pass, nremember)) {
-+ retval = PAM_AUTHTOK_ERR;
-+ goto done;
-+ }
-+
-+ if (doshadow || is_pwd_shadowed(pwd)) {
-+ retval = unix_update_shadow(forwho, towhat);
-+ if (retval == PAM_SUCCESS)
-+ if (!is_pwd_shadowed(pwd))
-+ retval = unix_update_passwd(forwho, "x");
-+ } else {
-+ retval = unix_update_passwd(forwho, towhat);
-+ }
-+
-+done:
-+ memset(pass, '\0', MAXPASS);
-+ memset(towhat, '\0', MAXPASS);
-+
-+ unlock_pwdf();
-+
-+ if (retval == PAM_SUCCESS) {
-+ return PAM_SUCCESS;
-+ } else {
-+ return PAM_AUTHTOK_ERR;
-+ }
-+}
-+
-+int main(int argc, char *argv[])
-+{
-+ char *option;
-+
-+ /*
-+ * Catch or ignore as many signal as possible.
-+ */
-+ setup_signals();
-+
-+ /*
-+ * we establish that this program is running with non-tty stdin.
-+ * this is to discourage casual use. It does *NOT* prevent an
-+ * intruder from repeatadly running this program to determine the
-+ * password of the current user (brute force attack, but one for
-+ * which the attacker must already have gained access to the user's
-+ * account).
-+ */
-+
-+ if (isatty(STDIN_FILENO) || argc != 5 ) {
-+ helper_log_err(LOG_NOTICE
-+ ,"inappropriate use of Unix helper binary [UID=%d]"
-+ ,getuid());
-+ fprintf(stderr
-+ ,"This binary is not designed for running in this way\n"
-+ "-- the system administrator has been informed\n");
-+ sleep(10); /* this should discourage/annoy the user */
-+ return PAM_SYSTEM_ERR;
-+ }
-+
-+ /* We must be root to read/update shadow.
-+ */
-+ if (geteuid() != 0) {
-+ return PAM_CRED_INSUFFICIENT;
-+ }
-+
-+ option = argv[2];
-+
-+ if (strcmp(option, "update") == 0) {
-+ /* Attempting to change the password */
-+ return set_password(argv[1], argv[3], argv[4]);
-+ }
-+
-+ return PAM_SYSTEM_ERR;
-+}
-+
-+/*
-+ * Copyright (c) Andrew G. Morgan, 1996. All rights reserved
-+ * Copyright (c) Red Hat, Inc., 2007, 2008. 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 /dev/null Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c
---- /dev/null 2008-01-05 20:21:31.621001512 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/passverify.c 2008-01-08 16:17:32.000000000 +0100
-@@ -0,0 +1,1083 @@
-+/*
-+ * Copyright information at end of file.
-+ */
-+#include "config.h"
-+#include
-+#include
-+#include "support.h"
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "md5.h"
-+#include "bigcrypt.h"
-+#include "passverify.h"
-+
-+#ifdef WITH_SELINUX
-+#include
-+#define SELINUX_ENABLED is_selinux_enabled()>0
-+#else
-+#define SELINUX_ENABLED 0
-+#endif
-+
-+#ifdef HELPER_COMPILE
-+#define pam_modutil_getpwnam(h,n) getpwnam(n)
-+#define pam_modutil_getspnam(h,n) getspnam(n)
-+#define pam_syslog(h,a,b,c) helper_log_err(a,b,c)
-+#else
-+#include
-+#include
-+#endif
-+
-+#if defined(USE_LCKPWDF) && !defined(HAVE_LCKPWDF)
-+# include "./lckpwdf.-c"
-+#endif
-+
-+int
-+verify_pwd_hash(const char *p, const char *hash, unsigned int nullok)
-+{
-+ size_t hash_len = strlen(hash);
-+ char *pp = NULL;
-+ int retval;
-+ D(("called"));
-+
-+ if (!hash_len) {
-+ /* the stored password is NULL */
-+ if (nullok) { /* this means we've succeeded */
-+ D(("user has empty password - access granted"));
-+ retval = PAM_SUCCESS;
-+ } else {
-+ D(("user has empty password - access denied"));
-+ retval = PAM_AUTH_ERR;
-+ }
-+ } else if (!p || *hash == '*' || *hash == '!') {
-+ retval = PAM_AUTH_ERR;
-+ } else {
-+ if (!strncmp(hash, "$1$", 3)) {
-+ pp = Goodcrypt_md5(p, hash);
-+ if (pp && strcmp(pp, hash) != 0) {
-+ _pam_delete(pp);
-+ pp = Brokencrypt_md5(p, hash);
-+ }
-+ } else if (*hash != '$' && hash_len >= 13) {
-+ pp = bigcrypt(p, hash);
-+ if (pp && hash_len == 13 && strlen(pp) > hash_len) {
-+ _pam_overwrite(pp + hash_len);
-+ }
-+ } else {
-+ /*
-+ * Ok, we don't know the crypt algorithm, but maybe
-+ * libcrypt nows about it? We should try it.
-+ */
-+ pp = x_strdup(crypt(p, hash));
-+ }
-+ p = NULL; /* no longer needed here */
-+
-+ /* the moment of truth -- do we agree with the password? */
-+ D(("comparing state of pp[%s] and salt[%s]", pp, salt));
-+
-+ if (pp && strcmp(pp, hash) == 0) {
-+ retval = PAM_SUCCESS;
-+ } else {
-+ retval = PAM_AUTH_ERR;
-+ }
-+ }
-+
-+ if (pp)
-+ _pam_delete(pp);
-+ D(("done [%d].", retval));
-+
-+ return retval;
-+}
-+
-+int
-+is_pwd_shadowed(const struct passwd *pwd)
-+{
-+ if (pwd != NULL) {
-+ if (strcmp(pwd->pw_passwd, "x") == 0) {
-+ return 1;
-+ }
-+ if ((pwd->pw_passwd[0] == '#') &&
-+ (pwd->pw_passwd[1] == '#') &&
-+ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) {
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+#ifdef HELPER_COMPILE
-+int
-+get_account_info(const char *name,
-+ struct passwd **pwd, struct spwd **spwdent)
-+#else
-+int
-+get_account_info(pam_handle_t *pamh, const char *name,
-+ struct passwd **pwd, struct spwd **spwdent)
-+#endif
-+{
-+ /* 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;
-+}
-+
-+#ifdef HELPER_COMPILE
-+int
-+get_pwd_hash(const char *name,
-+ struct passwd **pwd, char **hash)
-+#else
-+int
-+get_pwd_hash(pam_handle_t *pamh, const char *name,
-+ struct passwd **pwd, char **hash)
-+#endif
-+{
-+ int retval;
-+ struct spwd *spwdent = NULL;
-+
-+#ifdef HELPER_COMPILE
-+ retval = get_account_info(name, pwd, &spwdent);
-+#else
-+ retval = get_account_info(pamh, name, pwd, &spwdent);
-+#endif
-+ if (retval != PAM_SUCCESS) {
-+ return retval;
-+ }
-+
-+ if (spwdent)
-+ *hash = x_strdup(spwdent->sp_pwdp);
-+ else
-+ *hash = x_strdup((*pwd)->pw_passwd);
-+ if (*hash == NULL)
-+ return PAM_BUF_ERR;
-+
-+ return PAM_SUCCESS;
-+}
-+
-+#ifdef HELPER_COMPILE
-+int
-+check_shadow_expiry(struct spwd *spent, int *daysleft)
-+#else
-+int
-+check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft)
-+#endif
-+{
-+ long int curdays;
-+ *daysleft = -1;
-+ curdays = (long int)(time(NULL) / (60 * 60 * 24));
-+ D(("today is %d, last change %d", curdays, spent->sp_lstchg));
-+ if ((curdays > spent->sp_expire) && (spent->sp_expire != -1)) {
-+ D(("account expired"));
-+ return PAM_ACCT_EXPIRED;
-+ }
-+ if (spent->sp_lstchg == 0) {
-+ D(("need a new password"));
-+ *daysleft = 0;
-+ return PAM_NEW_AUTHTOK_REQD;
-+ }
-+ if (curdays < spent->sp_lstchg) {
-+ pam_syslog(pamh, LOG_DEBUG,
-+ "account %s has password changed in future",
-+ spent->sp_namp);
-+ return PAM_SUCCESS;
-+ }
-+ if ((curdays - spent->sp_lstchg > spent->sp_max)
-+ && (curdays - spent->sp_lstchg > spent->sp_inact)
-+ && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact)
-+ && (spent->sp_max != -1) && (spent->sp_inact != -1)) {
-+ *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays);
-+ D(("authtok expired"));
-+ return PAM_AUTHTOK_EXPIRED;
-+ }
-+ if ((curdays - spent->sp_lstchg > spent->sp_max) && (spent->sp_max != -1)) {
-+ D(("need a new password 2"));
-+ return PAM_NEW_AUTHTOK_REQD;
-+ }
-+ if ((curdays - spent->sp_lstchg > spent->sp_max - spent->sp_warn)
-+ && (spent->sp_max != -1) && (spent->sp_warn != -1)) {
-+ *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays);
-+ D(("warn before expiry"));
-+ }
-+ return PAM_SUCCESS;
-+
-+}
-+
-+/* passwd/salt conversion macros */
-+
-+#define PW_TMPFILE "/etc/npasswd"
-+#define SH_TMPFILE "/etc/nshadow"
-+#define OPW_TMPFILE "/etc/security/nopasswd"
-+
-+/*
-+ * 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 void
-+crypt_make_salt(char *where, int length)
-+{
-+ struct timeval tv;
-+ MD5_CTX ctx;
-+ unsigned char tmp[16];
-+ unsigned char *src = (unsigned char *)where;
-+ int i;
-+#ifdef PATH_RANDOMDEV
-+ int fd;
-+ int rv;
-+
-+ if ((rv = fd = open (PATH_RANDOMDEV, O_RDONLY)) != -1) {
-+ while ((rv = read(fd, where, length)) != length && errno == EINTR);
-+ close (fd);
-+ }
-+ if (rv != length) {
-+#endif
-+ /*
-+ * Code lifted from Marek Michalkiewicz's shadow suite. (CG)
-+ * removed use of static variables (AGM)
-+ *
-+ * will work correctly only for length <= 16 */
-+ src = tmp;
-+ 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, src, length);
-+ GoodMD5Final(tmp, &ctx);
-+#ifdef PATH_RANDOMDEV
-+ }
-+#endif
-+ for (i = 0; i < length; i++)
-+ *where++ = i64c(src[i] & 077);
-+ *where = '\0';
-+}
-+
-+char *
-+crypt_md5_wrapper(const char *pass_new)
-+{
-+ unsigned char result[16];
-+ char *cp = (char *) result;
-+
-+ cp = stpcpy(cp, "$1$"); /* magic for the MD5 */
-+ crypt_make_salt(cp, 9);
-+
-+ /* no longer need cleartext */
-+ cp = Goodcrypt_md5(pass_new, (const char *) result);
-+ pass_new = NULL;
-+
-+ return cp;
-+}
-+
-+char *
-+create_password_hash(const char *password, unsigned int ctrl, int rounds)
-+{
-+ const char *algoid;
-+ char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
-+ char *sp;
-+
-+ if (on(UNIX_MD5_PASS, ctrl)) {
-+ return crypt_md5_wrapper(password);
-+ }
-+ if (on(UNIX_SHA256_PASS, ctrl)) {
-+ algoid = "$5$";
-+ } else if (on(UNIX_SHA512_PASS, ctrl)) {
-+ algoid = "$6$";
-+ } else { /* must be crypt/bigcrypt */
-+ char tmppass[9];
-+ char *crypted;
-+
-+ crypt_make_salt(salt, 2);
-+ if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) {
-+ strncpy(tmppass, password, sizeof(tmppass)-1);
-+ tmppass[sizeof(tmppass)-1] = '\0';
-+ password = tmppass;
-+ }
-+ crypted = bigcrypt(password, salt);
-+ memset(tmppass, '\0', sizeof(tmppass));
-+ password = NULL;
-+ return crypted;
-+ }
-+
-+ sp = stpcpy(salt, algoid);
-+ if (on(UNIX_ALGO_ROUNDS, ctrl)) {
-+ sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds);
-+ }
-+ crypt_make_salt(sp, 8);
-+ /* For now be conservative so the resulting hashes
-+ * are not too long. 8 bytes of salt prevents dictionary
-+ * attacks well enough. */
-+ return x_strdup(crypt(password, salt));
-+}
-+
-+#ifdef WITH_SELINUX
-+int
-+unix_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
-+int
-+unix_selinux_confined(void)
-+{
-+ return 0;
-+}
-+#endif
-+
-+#ifdef USE_LCKPWDF
-+int
-+lock_pwdf(void)
-+{
-+ int i;
-+ int retval;
-+
-+#ifndef HELPER_COMPILE
-+ if (unix_selinux_confined()) {
-+ return PAM_SUCCESS;
-+ }
-+#endif
-+ /* 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) {
-+ return PAM_AUTHTOK_LOCK_BUSY;
-+ }
-+ return PAM_SUCCESS;
-+}
-+
-+void
-+unlock_pwdf(void)
-+{
-+#ifndef HELPER_COMPILE
-+ if (unix_selinux_confined()) {
-+ return;
-+ }
-+#endif
-+ ulckpwdf();
-+}
-+#else
-+int
-+lock_pwdf(void)
-+{
-+ return PAM_SUCCESS;
-+}
-+
-+void
-+unlock_pwdf(void)
-+{
-+ return;
-+}
-+#endif
-+
-+int
-+save_old_password(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;
-+ security_context_t prev_context=NULL;
-+
-+ 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 = NULL;
-+ found = 1;
-+ if (howmany == 0)
-+ continue;
-+ 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;
-+ }
-+ } else if (fputs(buf, pwfile) < 0) {
-+ err = 1;
-+ break;
-+ }
-+ }
-+ fclose(opwfile);
-+
-+ if (!found) {
-+ pwd = getpwnam(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;
-+ }
-+}
-+
-+#ifdef HELPER_COMPILE
-+int
-+unix_update_passwd(const char *forwho, const char *towhat)
-+#else
-+int
-+unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat)
-+#endif
-+{
-+ struct passwd *tmpent = NULL;
-+ struct stat st;
-+ FILE *pwfile, *opwfile;
-+ int err = 1;
-+ int oldmask;
-+ security_context_t prev_context=NULL;
-+
-+ 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"))
-+#ifdef HELPER_COMPILE
-+ helper_log_err(
-+#else
-+ pam_syslog(pamh,
-+#endif
-+ 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;
-+ }
-+}
-+
-+#ifdef HELPER_COMPILE
-+int
-+unix_update_shadow(const char *forwho, char *towhat)
-+#else
-+int
-+unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat)
-+#endif
-+{
-+ struct spwd *spwdent = NULL, *stmpent = NULL;
-+ struct stat st;
-+ FILE *pwfile, *opwfile;
-+ int err = 1;
-+ int oldmask;
-+ security_context_t prev_context=NULL;
-+
-+ 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"))
-+#ifdef HELPER_COMPILE
-+ helper_log_err(
-+#else
-+ pam_syslog(pamh,
-+#endif
-+ 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;
-+ }
-+}
-+
-+#ifdef HELPER_COMPILE
-+
-+int
-+helper_verify_password(const char *name, const char *p, int nullok)
-+{
-+ struct passwd *pwd = NULL;
-+ char *salt = NULL;
-+ int retval;
-+
-+ retval = get_pwd_hash(name, &pwd, &salt);
-+
-+ if (pwd == NULL || salt == NULL) {
-+ helper_log_err(LOG_WARNING, "check pass; user unknown");
-+ retval = PAM_USER_UNKNOWN;
-+ } else {
-+ retval = verify_pwd_hash(p, salt, nullok);
-+ }
-+
-+ if (salt) {
-+ _pam_overwrite(salt);
-+ _pam_drop(salt);
-+ }
-+
-+ p = NULL; /* no longer needed here */
-+
-+ return retval;
-+}
-+
-+void
-+helper_log_err(int err, const char *format, ...)
-+{
-+ va_list args;
-+
-+ va_start(args, format);
-+ openlog(HELPER_COMPILE, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
-+ vsyslog(err, format, args);
-+ va_end(args);
-+ closelog();
-+}
-+
-+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) {
-+ _exit(sig);
-+ }
-+}
-+
-+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);
-+}
-+
-+char *
-+getuidname(uid_t uid)
-+{
-+ struct passwd *pw;
-+ static char username[256];
-+
-+ pw = getpwuid(uid);
-+ if (pw == NULL)
-+ return NULL;
-+
-+ strncpy(username, pw->pw_name, sizeof(username));
-+ username[sizeof(username) - 1] = '\0';
-+
-+ return username;
-+}
-+
-+int
-+read_passwords(int fd, int npass, char **passwords)
-+{
-+ int rbytes = 0;
-+ int offset = 0;
-+ int i = 0;
-+ char *pptr;
-+ while (npass > 0) {
-+ rbytes = read(fd, passwords[i]+offset, MAXPASS-offset);
-+
-+ if (rbytes < 0) {
-+ if (errno == EINTR) continue;
-+ break;
-+ }
-+ if (rbytes == 0)
-+ break;
-+
-+ while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes))
-+ != NULL) {
-+ rbytes -= pptr - (passwords[i]+offset) + 1;
-+ i++;
-+ offset = 0;
-+ npass--;
-+ if (rbytes > 0) {
-+ if (npass > 0)
-+ memcpy(passwords[i], pptr+1, rbytes);
-+ memset(pptr+1, '\0', rbytes);
-+ }
-+ }
-+ offset += rbytes;
-+ }
-+
-+ /* clear up */
-+ if (offset > 0 && npass > 0) {
-+ memset(passwords[i], '\0', offset);
-+ }
-+
-+ return i;
-+}
-+
-+#endif
-+/* ****************************************************************** *
-+ * Copyright (c) Jan Rêkorajski 1999.
-+ * Copyright (c) Andrew G. Morgan 1996-8.
-+ * Copyright (c) Alex O. Yuriev, 1996.
-+ * Copyright (c) Cristian Gafton 1996.
-+ * Copyright (c) Red Hat, Inc. 1996, 2007, 2008.
-+ *
-+ * 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/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 2008-01-08 16:17:32.000000000 +0100
-@@ -26,9 +26,8 @@
- #include
- #include
-
--#include "md5.h"
- #include "support.h"
--#include "bigcrypt.h"
-+#include "passverify.h"
- #ifdef WITH_SELINUX
- #include
- #define SELINUX_ENABLED is_selinux_enabled()>0
-@@ -53,8 +52,8 @@ int _make_remark(pam_handle_t * pamh, un
- * set the control flags for the UNIX module.
- */
-
--int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc,
-- const char **argv)
-+int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
-+ int argc, const char **argv)
- {
- unsigned int ctrl;
-
-@@ -110,6 +109,16 @@ int _set_ctrl(pam_handle_t *pamh, int fl
- *remember = 400;
- }
- }
-+ if (rounds != NULL) {
-+ if (j == UNIX_ALGO_ROUNDS) {
-+ *rounds = strtol(*argv + 7, NULL, 10);
-+ if ((*rounds < 1000) || (*rounds == INT_MAX))
-+ /* don't care about bogus values */
-+ unset(UNIX_ALGO_ROUNDS, ctrl);
-+ if (*rounds >= 10000000)
-+ *rounds = 9999999;
-+ }
-+ }
- }
-
- ++argv; /* step to next argument */
-@@ -377,95 +386,6 @@ int _unix_comesfromsource(pam_handle_t *
- }
-
- /*
-- * _unix_blankpasswd() is a quick check for a blank password
-- *
-- * returns TRUE if user does not have a password
-- * - to avoid prompting for one in such cases (CG)
-- */
--
--int
--_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
--{
-- struct passwd *pwd = NULL;
-- struct spwd *spwdent = NULL;
-- char *salt = NULL;
-- int retval;
--
-- D(("called"));
--
-- /*
-- * This function does not have to be too smart if something goes
-- * wrong, return FALSE and let this case to be treated somewhere
-- * else (CG)
-- */
--
-- if (on(UNIX__NONULL, ctrl))
-- return 0; /* will fail but don't let on yet */
--
-- /* UNIX passwords area */
--
-- /* Get password file entry... */
-- pwd = pam_modutil_getpwnam (pamh, name);
--
-- if (pwd != NULL) {
-- if (strcmp( pwd->pw_passwd, "*NP*" ) == 0)
-- { /* NIS+ */
-- 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)
-- /* Will fail elsewhere. */
-- return 0;
-- }
-- }
--
-- spwdent = pam_modutil_getspnam (pamh, name);
-- if (save_uid == pwd->pw_uid)
-- setreuid( save_uid, save_euid );
-- else {
-- if (setreuid( -1, 0 ) == -1)
-- setreuid( save_uid, -1 );
-- setreuid( -1, save_euid );
-- }
-- } else if (_unix_shadowed(pwd)) {
-- /*
-- * ...and shadow password file entry for this user,
-- * if shadowing is enabled
-- */
-- spwdent = pam_modutil_getspnam(pamh, name);
-- }
-- if (spwdent)
-- salt = x_strdup(spwdent->sp_pwdp);
-- else
-- salt = x_strdup(pwd->pw_passwd);
-- }
-- /* Does this user have a password? */
-- if (salt == NULL) {
-- retval = 0;
-- } else {
-- if (strlen(salt) == 0)
-- retval = 1;
-- else
-- retval = 0;
-- }
--
-- /* tidy up */
--
-- if (salt)
-- _pam_delete(salt);
--
-- return retval;
--}
--
--/*
- * verify the password of a user
- */
-
-@@ -519,7 +439,7 @@ static int _unix_run_helper_binary(pam_h
- }
- }
-
-- if (SELINUX_ENABLED && geteuid() == 0) {
-+ if (geteuid() == 0) {
- /* must set the real uid to 0 so the helper will not error
- out if pam is called from setuid binary (su, sudo...) */
- setuid(0);
-@@ -573,13 +493,66 @@ static int _unix_run_helper_binary(pam_h
- return retval;
- }
-
-+/*
-+ * _unix_blankpasswd() is a quick check for a blank password
-+ *
-+ * returns TRUE if user does not have a password
-+ * - to avoid prompting for one in such cases (CG)
-+ */
-+
-+int
-+_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
-+{
-+ struct passwd *pwd = NULL;
-+ char *salt = NULL;
-+ int retval;
-+
-+ D(("called"));
-+
-+ /*
-+ * This function does not have to be too smart if something goes
-+ * wrong, return FALSE and let this case to be treated somewhere
-+ * else (CG)
-+ */
-+
-+ if (on(UNIX__NONULL, ctrl))
-+ return 0; /* will fail but don't let on yet */
-+
-+ /* UNIX passwords area */
-+
-+ retval = get_pwd_hash(pamh, name, &pwd, &salt);
-+
-+ if (retval == PAM_UNIX_RUN_HELPER) {
-+ /* salt will not be set here so we can return immediately */
-+ if (_unix_run_helper_binary(pamh, NULL, ctrl, name) == PAM_SUCCESS)
-+ return 1;
-+ else
-+ return 0;
-+ }
-+
-+ /* Does this user have a password? */
-+ if (salt == NULL) {
-+ retval = 0;
-+ } else {
-+ if (strlen(salt) == 0)
-+ retval = 1;
-+ else
-+ retval = 0;
-+ }
-+
-+ /* tidy up */
-+
-+ if (salt)
-+ _pam_delete(salt);
-+
-+ return retval;
-+}
-+
- int _unix_verify_password(pam_handle_t * pamh, const char *name
- ,const char *p, unsigned int ctrl)
- {
- struct passwd *pwd = NULL;
-- struct spwd *spwdent = NULL;
- char *salt = NULL;
-- char *pp = NULL;
- char *data_name;
- int retval;
-
-@@ -597,48 +570,7 @@ int _unix_verify_password(pam_handle_t *
-
- D(("locating user's record"));
-
-- /* UNIX passwords area */
-- pwd = pam_modutil_getpwnam (pamh, name); /* Get password file entry... */
--
-- if (pwd != NULL) {
-- if (strcmp( pwd->pw_passwd, "*NP*" ) == 0)
-- { /* NIS+ */
-- 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 {
-- if (setreuid( -1, 0 ) == -1)
-- setreuid( save_uid, -1 );
-- setreuid( -1, save_euid );
-- }
-- } else if (_unix_shadowed(pwd)) {
-- /*
-- * ...and shadow password file entry for this user,
-- * if shadowing is enabled
-- */
-- spwdent = pam_modutil_getspnam (pamh, name);
-- }
-- if (spwdent)
-- salt = x_strdup(spwdent->sp_pwdp);
-- else
-- salt = x_strdup(pwd->pw_passwd);
-- }
-+ retval = get_pwd_hash(pamh, name, &pwd, &salt);
-
- data_name = (char *) malloc(sizeof(FAIL_PREFIX) + strlen(name));
- if (data_name == NULL) {
-@@ -648,29 +580,22 @@ int _unix_verify_password(pam_handle_t *
- strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name);
- }
-
-- retval = PAM_SUCCESS;
-- if (pwd == NULL || salt == NULL || !strcmp(salt, "x") || ((salt[0] == '#') && (salt[1] == '#') && !strcmp(salt + 2, name))) {
--
-- if (pwd != NULL && (geteuid() || SELINUX_ENABLED)) {
-- /* we are not root perhaps this is the reason? Run helper */
-+ if (retval != PAM_SUCCESS) {
-+ if (retval == PAM_UNIX_RUN_HELPER) {
- D(("running helper binary"));
- retval = _unix_run_helper_binary(pamh, p, ctrl, name);
- } else {
- D(("user's record unavailable"));
- p = NULL;
-- if (pwd == NULL)
-- retval = PAM_USER_UNKNOWN;
-- else
-- retval = PAM_AUTHINFO_UNAVAIL;
- if (on(UNIX_AUDIT, ctrl)) {
- /* this might be a typo and the user has given a password
- instead of a username. Careful with this. */
-- pam_syslog(pamh, LOG_ALERT,
-+ pam_syslog(pamh, LOG_WARNING,
- "check pass; user (%s) unknown", name);
- } else {
- name = NULL;
- if (on(UNIX_DEBUG, ctrl) || pwd == NULL) {
-- pam_syslog(pamh, LOG_ALERT,
-+ pam_syslog(pamh, LOG_WARNING,
- "check pass; user unknown");
- } else {
- /* don't log failure as another pam module can succeed */
-@@ -679,48 +604,7 @@ int _unix_verify_password(pam_handle_t *
- }
- }
- } else {
-- size_t salt_len = strlen(salt);
-- if (!salt_len) {
-- /* the stored password is NULL */
-- if (off(UNIX__NONULL, ctrl)) {/* this means we've succeeded */
-- D(("user has empty password - access granted"));
-- retval = PAM_SUCCESS;
-- } else {
-- D(("user has empty password - access denied"));
-- retval = PAM_AUTH_ERR;
-- }
-- } else if (!p || *salt == '*' || *salt == '!') {
-- retval = PAM_AUTH_ERR;
-- } else {
-- if (!strncmp(salt, "$1$", 3)) {
-- pp = Goodcrypt_md5(p, salt);
-- if (pp && strcmp(pp, salt) != 0) {
-- _pam_delete(pp);
-- pp = Brokencrypt_md5(p, salt);
-- }
-- } else if (*salt != '$' && salt_len >= 13) {
-- pp = bigcrypt(p, salt);
-- if (pp && salt_len == 13 && strlen(pp) > salt_len) {
-- _pam_overwrite(pp + salt_len);
-- }
-- } else {
-- /*
-- * Ok, we don't know the crypt algorithm, but maybe
-- * libcrypt nows about it? We should try it.
-- */
-- pp = x_strdup (crypt(p, salt));
-- }
-- p = NULL; /* no longer needed here */
--
-- /* the moment of truth -- do we agree with the password? */
-- D(("comparing state of pp[%s] and salt[%s]", pp, salt));
--
-- if (pp && strcmp(pp, salt) == 0) {
-- retval = PAM_SUCCESS;
-- } else {
-- retval = PAM_AUTH_ERR;
-- }
-- }
-+ retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
- }
-
- if (retval == PAM_SUCCESS) {
-@@ -809,8 +693,6 @@ cleanup:
- _pam_delete(data_name);
- if (salt)
- _pam_delete(salt);
-- if (pp)
-- _pam_delete(pp);
-
- D(("done [%d].", retval));
-
-@@ -971,26 +853,12 @@ int _unix_read_password(pam_handle_t * p
- return PAM_SUCCESS;
- }
-
--int _unix_shadowed(const struct passwd *pwd)
--{
-- if (pwd != NULL) {
-- if (strcmp(pwd->pw_passwd, "x") == 0) {
-- return 1;
-- }
-- if ((pwd->pw_passwd[0] == '#') &&
-- (pwd->pw_passwd[1] == '#') &&
-- (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) {
-- return 1;
-- }
-- }
-- return 0;
--}
--
- /* ****************************************************************** *
- * Copyright (c) Jan Rkorajski 1999.
- * Copyright (c) Andrew G. Morgan 1996-8.
- * Copyright (c) Alex O. Yuriev, 1996.
- * Copyright (c) Cristian Gafton 1996.
-+ * 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
-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 2008-01-08 16:17:32.000000000 +0100
-@@ -16,7 +16,9 @@ securelibdir = $(SECUREDIR)
- secureconfdir = $(SCONFIGDIR)
-
- AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-- -DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\"
-+ -DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
-+ -DUPDATE_HELPER=\"$(sbindir)/unix_update\" \
-+ -DPATH_RANDOMDEV=\"/dev/urandom\"
-
- if HAVE_LIBSELINUX
- AM_CFLAGS += -D"WITH_SELINUX"
-@@ -25,33 +27,40 @@ if HAVE_LIBCRACK
- AM_CFLAGS += -D"USE_CRACKLIB"
- endif
-
--pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module \
-- @LIBCRACK@ @LIBNSL@ -L$(top_builddir)/libpam -lpam \
-- @LIBCRYPT@ @LIBSELINUX@
-+pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module
- if HAVE_VERSIONING
- pam_unix_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
- endif
-+pam_unix_la_LIBADD = @LIBCRACK@ @LIBNSL@ -L$(top_builddir)/libpam -lpam \
-+ @LIBCRYPT@ @LIBSELINUX@
-
- securelib_LTLIBRARIES = pam_unix.la
-
--noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h
-+noinst_HEADERS = md5.h support.h yppasswd.h bigcrypt.h passverify.h
-
--sbin_PROGRAMS = unix_chkpwd
-+sbin_PROGRAMS = unix_chkpwd unix_update
-
- noinst_PROGRAMS = bigcrypt
-
- pam_unix_la_SOURCES = bigcrypt.c pam_unix_acct.c \
- pam_unix_auth.c pam_unix_passwd.c pam_unix_sess.c support.c \
-- yppasswd_xdr.c md5_good.c md5_broken.c
-+ passverify.c yppasswd_xdr.c md5_good.c md5_broken.c
-
- bigcrypt_SOURCES = bigcrypt.c bigcrypt_main.c
- bigcrypt_CFLAGS = $(AM_CFLAGS)
--bigcrypt_LDFLAGS = @LIBCRYPT@
-+bigcrypt_LDADD = @LIBCRYPT@
-
--unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c
--unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
--unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ -L$(top_builddir)/libpam -lpam \
-- @LIBCRYPT@ @LIBSELINUX@
-+unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \
-+ passverify.c
-+unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\"
-+unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@
-+unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@
-+
-+unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \
-+ passverify.c
-+unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\"
-+unix_update_LDFLAGS = @PIE_LDFLAGS@
-+unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
-
- if ENABLE_REGENERATE_MAN
- noinst_DATA = README
-diff -up Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c.update-helper Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c
---- Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c.update-helper 2006-12-20 15:52:55.000000000 +0100
-+++ Linux-PAM-0.99.8.1/modules/pam_unix/pam_unix_auth.c 2008-01-07 16:38:50.000000000 +0100
-@@ -111,7 +111,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_h
-
- D(("called."));
-
-- ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
-+ ctrl = _set_ctrl(pamh, flags, NULL, NULL, argc, argv);
-
- /* Get a few bytes so we can pass our return value to
- pam_sm_setcred(). */
diff --git a/pam-0.99.8.1-xauth-no-free.patch b/pam-0.99.8.1-xauth-no-free.patch
deleted file mode 100644
index fcd9eff..0000000
--- a/pam-0.99.8.1-xauth-no-free.patch
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -up Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c.no-free Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c
---- Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c.no-free 2007-09-21 16:02:06.000000000 +0200
-+++ Linux-PAM-0.99.8.1/modules/pam_xauth/pam_xauth.c 2007-09-21 16:02:47.000000000 +0200
-@@ -573,6 +573,7 @@ pam_sm_open_session (pam_handle_t *pamh,
- "can't set environment variable '%s'",
- xauthority);
- putenv (xauthority); /* The environment owns this string now. */
-+ xauthority = NULL;
-
- /* set $DISPLAY in pam handle to make su - work */
- {
diff --git a/pam.spec b/pam.spec
index 98dd4c1..7504709 100644
--- a/pam.spec
+++ b/pam.spec
@@ -4,8 +4,8 @@
Summary: A security tool which provides authentication for applications
Name: pam
-Version: 0.99.8.1
-Release: 18%{?dist}
+Version: 0.99.10.0
+Release: 1%{?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
@@ -21,28 +21,15 @@ Source7: config-util.pamd
Source8: dlopen.sh
Source9: system-auth.5
Source10: config-util.5
+Source11: 90-nproc.conf
Patch1: pam-0.99.7.0-redhat-modules.patch
Patch2: db-4.6.18-glibc.patch
Patch4: pam-0.99.8.1-dbpam.patch
Patch5: pam-0.99.8.1-audit-no-log.patch
-Patch24: pam-0.99.8.1-unix-update-helper.patch
-Patch25: pam-0.99.8.1-unix-hpux-aging.patch
Patch31: pam-0.99.3.0-cracklib-try-first-pass.patch
Patch32: pam-0.99.3.0-tally-fail-close.patch
-Patch40: pam-0.99.7.1-namespace-temp-logon.patch
-Patch41: pam-0.99.8.1-namespace-init.patch
Patch42: pam-0.99.8.1-console-hal-handled.patch
Patch43: pam-0.99.8.1-console-mfd-scanners.patch
-Patch44: pam-0.99.7.1-namespace-homedir.patch
-Patch45: pam-0.99.8.1-selinux-permit.patch
-Patch46: pam-0.99.8.1-succif-in-operator.patch
-Patch47: pam-0.99.8.1-xauth-no-free.patch
-Patch48: pam-0.99.8.1-substack.patch
-Patch49: pam-0.99.8.1-tty-audit.patch
-Patch50: pam-0.99.8.1-tty-audit2.patch
-Patch51: pam-0.99.8.1-audit-failed.patch
-Patch52: pam-0.99.8.1-setkeycreatecon.patch
-Patch53: pam-0.99.8.1-sepermit-kill-user.patch
%define _sbindir /sbin
%define _moduledir /%{_lib}/security
@@ -113,24 +100,10 @@ pushd db-%{db_version}
popd
%patch4 -p1 -b .dbpam
%patch5 -p1 -b .no-log
-%patch24 -p1 -b .update-helper
-%patch25 -p1 -b .unix-hpux-aging
%patch31 -p1 -b .try-first-pass
%patch32 -p1 -b .fail-close
-%patch40 -p1 -b .temp-logon
-%patch41 -p1 -b .ns-init
%patch42 -p1 -b .hal-handled
%patch43 -p1 -b .mfd-scanners
-%patch44 -p1 -b .homedir
-%patch45 -p1 -b .permit
-%patch46 -p1 -b .in-operator
-%patch47 -p1 -b .no-free
-%patch48 -p0 -b .substack
-%patch49 -p1 -b .tty-audit
-%patch50 -p1 -b .tty-audit2
-%patch51 -p1 -b .audit-failed
-%patch52 -p1 -b .setkeycreatecon
-%patch53 -p1 -b .kill-user
autoreconf
@@ -191,6 +164,11 @@ done
# Install the binaries, libraries, and modules.
make install DESTDIR=$RPM_BUILD_ROOT LDCONFIG=:
+%if %{WITH_SELINUX}
+# Temporary compat link
+ln -sf pam_sepermit.so $RPM_BUILD_ROOT%{_moduledir}/pam_selinux_permit.so
+%endif
+
# RPM uses docs from source tree
rm -rf $RPM_BUILD_ROOT%{_datadir}/doc/Linux-PAM
# Included in setup package
@@ -201,6 +179,7 @@ install -d -m 755 $RPM_BUILD_ROOT%{_pamconfdir}
install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_pamconfdir}/other
install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_pamconfdir}/system-auth
install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pamconfdir}/config-util
+install -m 644 %{SOURCE11} $RPM_BUILD_ROOT%{_secconfdir}/limits.d/90-nproc.conf
install -m 600 /dev/null $RPM_BUILD_ROOT%{_secconfdir}/opasswd
install -d -m 755 $RPM_BUILD_ROOT/var/log
install -m 600 /dev/null $RPM_BUILD_ROOT/var/log/faillog
@@ -331,12 +310,12 @@ fi
%{_moduledir}/pam_permit.so
%{_moduledir}/pam_postgresok.so
%{_moduledir}/pam_rhosts.so
-%{_moduledir}/pam_rhosts_auth.so
%{_moduledir}/pam_rootok.so
%{_moduledir}/pam_rps.so
%if %{WITH_SELINUX}
%{_moduledir}/pam_selinux.so
%{_moduledir}/pam_selinux_permit.so
+%{_moduledir}/pam_sepermit.so
%endif
%{_moduledir}/pam_securetty.so
%{_moduledir}/pam_shells.so
@@ -365,7 +344,10 @@ fi
%config(noreplace) %{_secconfdir}/console.handlers
%config(noreplace) %{_secconfdir}/group.conf
%config(noreplace) %{_secconfdir}/limits.conf
+%dir %{_secconfdir}/limits.d
+%config(noreplace) %{_secconfdir}/limits.d/90-nproc.conf
%config(noreplace) %{_secconfdir}/namespace.conf
+%dir %{_secconfdir}/namespace.d
%attr(755,root,root) %config(noreplace) %{_secconfdir}/namespace.init
%config(noreplace) %{_secconfdir}/pam_env.conf
%config(noreplace) %{_secconfdir}/sepermit.conf
@@ -392,6 +374,11 @@ fi
%doc doc/adg/*.txt doc/adg/html
%changelog
+* Fri Feb 15 2008 Tomas Mraz 0.99.10.0-1
+- new upstream release
+- add default soft limit for nproc of 1024 to prevent
+ accidental fork bombs (#432903)
+
* Mon Feb 4 2008 Tomas Mraz 0.99.8.1-18
- allow the package to build without SELinux and audit support (#431415)
- macro usage cleanup
diff --git a/sources b/sources
index 62da324..60af30e 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
2a23dc703b550223206021ff03b1e434 pam-redhat-0.99.8-1.tar.bz2
-a6472db4afe13850cb401922211bba4e Linux-PAM-0.99.8.1.tar.bz2
89c7390ff120d5ebf3eccc5f97249e79 db-4.6.19.tar.gz
+be4dd1d34ac5933408e13e48f3eb710a Linux-PAM-0.99.10.0.tar.bz2