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; idebug = 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 @@ -+ -+ -+ -+
-+ -+ -+ -+ -+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" -+ href="pam_tty_audit.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_tty_audit-name"]/*)'/> -+ -+ -+ -+ -+
-+ -+
-+ -+
-+ -+
-+ -+
-+ -+
-+ -+
-+ -+
-+ -+
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