summaryrefslogtreecommitdiffstats
path: root/source/a/pam
diff options
context:
space:
mode:
author Patrick J Volkerding <volkerdi@slackware.com>2020-05-18 19:17:21 +0000
committer Eric Hameleers <alien@slackware.com>2020-05-18 23:25:14 +0200
commitffef56590d68c334819ecf26118a257bdafccf6b (patch)
tree6681fac1801c4a0569147ba9a731f323b38dff15 /source/a/pam
parenteba2e5b781702a60ac9f9613c9b8456c1594215c (diff)
downloadcurrent-ffef56590d68c334819ecf26118a257bdafccf6b.tar.gz
current-ffef56590d68c334819ecf26118a257bdafccf6b.tar.xz
Mon May 18 19:17:21 UTC 202020200518191721
Greetings! After three months in /testing, the PAM merge into the main tree is now complete. When updating, be sure to install the new pam, cracklib, and libpwquality packages or you may find yourself locked out of your machine. Otherwise, these changes should be completely transparent and you shouldn't notice any obvious operational differences. Be careful if you make any changes in /etc/pam.d/ - leaving an extra console logged in while testing PAM config changes is a recommended standard procedure. Thanks again to Robby Workman, Vincent Batts, Phantom X, and ivandi for help implementing this. It's not done yet and there will be more fine-tuning of the config files, but now we can move on to build some other updates. Enjoy! a/cracklib-2.9.7-x86_64-1.txz: Added. a/kernel-firmware-20200517_f8d32e4-noarch-1.txz: Upgraded. a/libcgroup-0.41-x86_64-7.txz: Rebuilt. Rebuilt to add PAM support. a/libpwquality-1.4.2-x86_64-1.txz: Added. a/lilo-24.2-x86_64-9.txz: Rebuilt. Enable the "compact" option by default. liloconfig: correctly set the root partition. a/pam-1.3.1-x86_64-1.txz: Added. a/shadow-4.8.1-x86_64-7.txz: Rebuilt. Rebuilt to add PAM support. a/utempter-1.2.0-x86_64-1.txz: Upgraded. a/util-linux-2.35.1-x86_64-6.txz: Rebuilt. Rebuilt to add PAM support. a/xfsprogs-5.6.0-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. ap/at-3.2.1-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. ap/cups-2.3.3-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. ap/hplip-3.20.5-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. ap/mariadb-10.4.13-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. ap/screen-4.8.0-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. ap/soma-3.3.0-noarch-1.txz: Upgraded. Thanks to David Woodfall. ap/sqlite-3.31.1-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. ap/sudo-1.9.0-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. ap/vim-8.2.0788-x86_64-1.txz: Upgraded. d/bison-3.6.2-x86_64-1.txz: Upgraded. d/meson-0.54.2-x86_64-1.txz: Upgraded. d/python-setuptools-46.4.0-x86_64-1.txz: Upgraded. d/vala-0.48.6-x86_64-1.txz: Upgraded. kde/calligra-2.9.11-x86_64-36.txz: Rebuilt. Recompiled against icu4c-67.1. kde/kde-workspace-4.11.22-x86_64-7.txz: Rebuilt. Rebuilt to add PAM support. l/ConsoleKit2-1.2.1-x86_64-4.txz: Rebuilt. Rebuilt to add PAM support. l/boost-1.73.0-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. l/gnome-keyring-3.36.0-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. l/harfbuzz-2.6.6-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. l/icu4c-67.1-x86_64-1.txz: Upgraded. Shared library .so-version bump. l/imagemagick-7.0.10_13-x86_64-1.txz: Upgraded. l/libcap-2.34-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. l/libical-3.0.8-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. l/libuv-1.38.0-x86_64-1.txz: Upgraded. l/libvisio-0.1.7-x86_64-3.txz: Rebuilt. Recompiled against icu4c-67.1. l/polkit-0.116-x86_64-3.txz: Rebuilt. Rebuilt to add PAM support. l/qt-4.8.7-x86_64-16.txz: Rebuilt. Recompiled against icu4c-67.1. l/qt5-5.13.2-x86_64-4.txz: Rebuilt. Recompiled against icu4c-67.1. l/qt5-webkit-5.212.0_alpha4-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. l/raptor2-2.0.15-x86_64-9.txz: Rebuilt. Recompiled against icu4c-67.1. l/system-config-printer-1.5.12-x86_64-4.txz: Rebuilt. Rebuilt to add PAM support. l/vte-0.60.2-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. n/cifs-utils-6.10-x86_64-4.txz: Rebuilt. Rebuilt to add PAM support. n/cyrus-sasl-2.1.27-x86_64-4.txz: Rebuilt. Rebuilt to add PAM support. n/dovecot-2.3.10.1-x86_64-1.txz: Upgraded. Rebuilt to add PAM support. Compiled against icu4c-67.1. This update fixes several denial-of-service vulnerabilities. For more information, see: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10957 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10958 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10967 (* Security fix *) n/mutt-1.14.1-x86_64-1.txz: Upgraded. n/netatalk-3.1.12-x86_64-3.txz: Rebuilt. Rebuilt to add PAM support. n/netkit-rsh-0.17-x86_64-3.txz: Rebuilt. Rebuilt to add PAM support. n/nss-pam-ldapd-0.9.11-x86_64-1.txz: Added. n/openssh-8.2p1-x86_64-3.txz: Rebuilt. Rebuilt to add PAM support. n/openvpn-2.4.9-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. n/pam-krb5-4.9-x86_64-1.txz: Added. n/php-7.4.6-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. n/popa3d-1.0.3-x86_64-4.txz: Rebuilt. Rebuilt to add PAM support. n/postfix-3.5.2-x86_64-1.txz: Upgraded. Compiled against icu4c-67.1. n/ppp-2.4.8-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. n/proftpd-1.3.6c-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. n/samba-4.12.2-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. Recompiled against icu4c-67.1. n/tin-2.4.4-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. n/vsftpd-3.0.3-x86_64-6.txz: Rebuilt. Rebuilt to add PAM support. t/texlive-2019.190626-x86_64-4.txz: Rebuilt. Recompiled against icu4c-67.1. x/vulkan-sdk-1.2.135.0-x86_64-1.txz: Upgraded. x/xdm-1.1.11-x86_64-10.txz: Rebuilt. Rebuilt to add PAM support. x/xisxwayland-1-x86_64-1.txz: Added. xap/sane-1.0.30-x86_64-1.txz: Upgraded. This update fixes several security issues. For more information, see: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12867 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12862 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12863 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12865 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12866 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12861 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-12864 (* Security fix *) xap/vim-gvim-8.2.0788-x86_64-1.txz: Upgraded. xap/xlockmore-5.63-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. xap/xscreensaver-5.44-x86_64-2.txz: Rebuilt. Rebuilt to add PAM support. extra/brltty/brltty-6.1-x86_64-2.txz: Rebuilt. Recompiled against icu4c-67.1. extra/pure-alsa-system/qt5-5.13.2-x86_64-4_alsa.txz: Rebuilt. Recompiled against icu4c-67.1. isolinux/initrd.img: Rebuilt. Added PAM libraries, security modules, and config files. usb-and-pxe-installers/usbboot.img: Rebuilt. Added PAM libraries, security modules, and config files.
Diffstat (limited to 'source/a/pam')
-rw-r--r--source/a/pam/doinst.sh14
-rw-r--r--source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch27
-rw-r--r--source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch20
-rw-r--r--source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch31
-rw-r--r--source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch67
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch806
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch16
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-coverity.patch185
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch755
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-noflex.patch24
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch78
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch34
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch73
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch40
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch104
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch95
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch105
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch34
-rw-r--r--source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch479
-rwxr-xr-xsource/a/pam/pam.SlackBuild230
-rw-r--r--source/a/pam/pam.url2
-rw-r--r--source/a/pam/patches/pam.etc.environment.better.comments.diff15
-rw-r--r--source/a/pam/patches/pam.pam_tally2.no.fsync.patch35
-rw-r--r--source/a/pam/patches/pam.pam_tally2.slackware.diff11
-rw-r--r--source/a/pam/slack-desc19
25 files changed, 3299 insertions, 0 deletions
diff --git a/source/a/pam/doinst.sh b/source/a/pam/doinst.sh
new file mode 100644
index 000000000..e96721a14
--- /dev/null
+++ b/source/a/pam/doinst.sh
@@ -0,0 +1,14 @@
+
+config() {
+ NEW="$1"
+ OLD="$(dirname $NEW)/$(basename $NEW .new)"
+ # If there's no config file by that name, mv it over:
+ if [ ! -r $OLD ]; then
+ mv $NEW $OLD
+ elif [ "$(cat $OLD | md5sum)" = "$(cat $NEW | md5sum)" ]; then
+ # toss the redundant copy
+ rm $NEW
+ fi
+ # Otherwise, we leave the .new copy for the admin to consider...
+}
+
diff --git a/source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch b/source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch
new file mode 100644
index 000000000..f3a742c8d
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.1.3-nouserenv.patch
@@ -0,0 +1,27 @@
+diff -up pam/modules/pam_env/pam_env.c.nouserenv pam/modules/pam_env/pam_env.c
+--- pam/modules/pam_env/pam_env.c.nouserenv 2010-10-20 09:59:30.000000000 +0200
++++ pam/modules/pam_env/pam_env.c 2010-11-01 14:42:01.000000000 +0100
+@@ -10,7 +10,7 @@
+ #define DEFAULT_READ_ENVFILE 1
+
+ #define DEFAULT_USER_ENVFILE ".pam_environment"
+-#define DEFAULT_USER_READ_ENVFILE 1
++#define DEFAULT_USER_READ_ENVFILE 0
+
+ #include "config.h"
+
+diff -up pam/modules/pam_env/pam_env.8.xml.nouserenv pam/modules/pam_env/pam_env.8.xml
+--- pam/modules/pam_env/pam_env.8.xml.nouserenv 2010-10-20 09:59:30.000000000 +0200
++++ pam/modules/pam_env/pam_env.8.xml 2010-11-01 14:42:01.000000000 +0100
+@@ -147,7 +147,10 @@
+ <listitem>
+ <para>
+ Turns on or off the reading of the user specific environment
+- file. 0 is off, 1 is on. By default this option is on.
++ file. 0 is off, 1 is on. By default this option is off as user
++ supplied environment variables in the PAM environment could affect
++ behavior of subsequent modules in the stack without the consent
++ of the system administrator.
+ </para>
+ </listitem>
+ </varlistentry>
diff --git a/source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch b/source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch
new file mode 100644
index 000000000..3c17b781a
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.1.6-limits-user.patch
@@ -0,0 +1,20 @@
+diff -up Linux-PAM-1.1.6/modules/pam_limits/limits.conf.limits Linux-PAM-1.1.6/modules/pam_limits/limits.conf
+--- Linux-PAM-1.1.6/modules/pam_limits/limits.conf.limits 2012-08-15 13:08:43.000000000 +0200
++++ Linux-PAM-1.1.6/modules/pam_limits/limits.conf 2013-03-14 16:43:37.615087671 +0100
+@@ -1,5 +1,16 @@
+ # /etc/security/limits.conf
+ #
++#This file sets the resource limits for the users logged in via PAM.
++#It does not affect resource limits of the system services.
++#
++#Also note that configuration files in /etc/security/limits.d directory,
++#which are read in alphabetical order, override the settings in this
++#file in case the domain is the same or more specific.
++#That means for example that setting a limit for wildcard domain here
++#can be overriden with a wildcard setting in a config file in the
++#subdirectory, but a user specific setting here can be overriden only
++#with a user specific setting in the subdirectory.
++#
+ #Each line describes a limit for a user in the form:
+ #
+ #<domain> <type> <item> <value>
diff --git a/source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch b/source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch
new file mode 100644
index 000000000..277a5699f
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.1.8-audit-user-mgmt.patch
@@ -0,0 +1,31 @@
+diff -up Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c.audit-user-mgmt Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c
+--- Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c.audit-user-mgmt 2013-06-18 16:11:21.000000000 +0200
++++ Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c 2014-10-17 12:09:12.965490940 +0200
+@@ -997,9 +997,9 @@ main( int argc UNUSED, char **argv )
+ #ifdef HAVE_LIBAUDIT
+ char buf[64];
+ int audit_fd = audit_open();
+- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u reset=%hu", uid, cline_reset);
+- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
+- buf, NULL, NULL, ttyname(STDIN_FILENO), 1);
++ snprintf(buf, sizeof(buf), "pam_tally2 reset=%hu", cline_reset);
++ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
++ buf, NULL, uid, NULL, NULL, ttyname(STDIN_FILENO), 1);
+ if (audit_fd >=0)
+ close(audit_fd);
+ #endif
+@@ -1040,11 +1040,10 @@ main( int argc UNUSED, char **argv )
+ }
+ else if ( !cline_reset ) {
+ #ifdef HAVE_LIBAUDIT
+- char buf[64];
+ int audit_fd = audit_open();
+- snprintf(buf, sizeof(buf), "pam_tally2 uid=all reset=0");
+- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
+- buf, NULL, NULL, ttyname(STDIN_FILENO), 1);
++ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
++ "pam_tally2-reset-all-accts reset=0", "*", -1,
++ NULL, NULL, ttyname(STDIN_FILENO), 1);
+ if (audit_fd >=0)
+ close(audit_fd);
+ #endif
diff --git a/source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch b/source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch
new file mode 100644
index 000000000..b2d8526f9
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.1.8-full-relro.patch
@@ -0,0 +1,67 @@
+diff -up Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am
+--- Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro 2014-09-10 17:17:20.273401344 +0200
++++ Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am 2014-09-10 17:17:07.857115369 +0200
+@@ -9,7 +9,7 @@ securelibfilterdir = $(SECUREDIR)/pam_fi
+
+ AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ -I$(srcdir)/.. @PIE_CFLAGS@
+-AM_LDFLAGS = @PIE_LDFLAGS@
++AM_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+ LDADD = $(top_builddir)/libpam/libpam.la
+
+ securelibfilter_PROGRAMS = upperLOWER
+diff -up Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am
+--- Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
++++ Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am 2014-09-10 17:18:42.922304935 +0200
+@@ -30,6 +30,8 @@ endif
+
+ sbin_PROGRAMS = mkhomedir_helper
+ mkhomedir_helper_SOURCES = mkhomedir_helper.c
++mkhomedir_helper_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
++mkhomedir_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+ mkhomedir_helper_LDADD = $(top_builddir)/libpam/libpam.la
+
+ if ENABLE_REGENERATE_MAN
+diff -up Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am
+--- Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
++++ Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am 2014-09-10 17:22:04.339944040 +0200
+@@ -26,6 +26,8 @@ if HAVE_VERSIONING
+ pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+ endif
+
++pam_tally2_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
++pam_tally2_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+ pam_tally2_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT)
+
+ securelib_LTLIBRARIES = pam_tally2.la
+diff -up Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am
+--- Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
++++ Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am 2014-08-13 16:02:49.906688139 +0200
+@@ -36,7 +36,7 @@ pam_timestamp_la_CFLAGS = $(AM_CFLAGS)
+ pam_timestamp_check_SOURCES = pam_timestamp_check.c
+ pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+ pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la
+-pam_timestamp_check_LDFLAGS = @PIE_LDFLAGS@
++pam_timestamp_check_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+
+ hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c
+ hmacfile_LDADD = $(top_builddir)/libpam/libpam.la
+diff -up Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_unix/Makefile.am
+--- Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
++++ Linux-PAM-1.1.8/modules/pam_unix/Makefile.am 2014-08-13 16:02:49.906688139 +0200
+@@ -55,13 +55,13 @@ bigcrypt_LDADD = @LIBCRYPT@
+ 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_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+ unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@
+
+ 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_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+ unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
+
+ if ENABLE_REGENERATE_MAN
diff --git a/source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch b/source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch
new file mode 100644
index 000000000..554e5c8f8
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.0-pwhistory-helper.patch
@@ -0,0 +1,806 @@
+diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am
+--- Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am.pwhhelper 2016-03-24 12:45:42.000000000 +0100
++++ Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am 2016-05-06 15:18:42.307637933 +0200
+@@ -1,5 +1,6 @@
+ #
+ # Copyright (c) 2008, 2009 Thorsten Kukuk <kukuk@suse.de>
++# Copyright (c) 2013 Red Hat, Inc.
+ #
+
+ CLEANFILES = *~
+@@ -9,25 +10,34 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst-
+
+ TESTS = tst-pam_pwhistory
+
+-man_MANS = pam_pwhistory.8
++man_MANS = pam_pwhistory.8 pwhistory_helper.8
+
+-XMLS = README.xml pam_pwhistory.8.xml
++XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
+
+ securelibdir = $(SECUREDIR)
+ secureconfdir = $(SCONFIGDIR)
+
+-AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
+-AM_LDFLAGS = -no-undefined -avoid-version -module
++AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
++ -DPWHISTORY_HELPER=\"$(sbindir)/pwhistory_helper\"
++
++pam_pwhistory_la_LDFLAGS = -no-undefined -avoid-version -module
+ if HAVE_VERSIONING
+- AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
++ pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+ endif
+
+ noinst_HEADERS = opasswd.h
+
+ securelib_LTLIBRARIES = pam_pwhistory.la
+-pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
++pam_pwhistory_la_CFLAGS = $(AM_CFLAGS)
++pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ @LIBSELINUX@
+ pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c
+
++sbin_PROGRAMS = pwhistory_helper
++pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@
++pwhistory_helper_SOURCES = pwhistory_helper.c opasswd.c
++pwhistory_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
++pwhistory_helper_LDADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
++
+ if ENABLE_REGENERATE_MAN
+ noinst_DATA = README
+ README: pam_pwhistory.8.xml
+diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c
+--- Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c.pwhhelper 2016-03-24 12:45:42.000000000 +0100
++++ Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c 2016-05-06 15:18:42.307637933 +0200
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
++ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+@@ -38,6 +39,7 @@
+ #endif
+
+ #include <pwd.h>
++#include <shadow.h>
+ #include <time.h>
+ #include <ctype.h>
+ #include <errno.h>
+@@ -47,6 +49,7 @@
+ #include <string.h>
+ #include <stdlib.h>
+ #include <syslog.h>
++#include <stdarg.h>
+ #include <sys/stat.h>
+
+ #if defined (HAVE_XCRYPT_H)
+@@ -55,7 +58,14 @@
+ #include <crypt.h>
+ #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,...) helper_log_err(a,__VA_ARGS__)
++#else
++#include <security/pam_modutil.h>
+ #include <security/pam_ext.h>
++#endif
+ #include <security/pam_modules.h>
+
+ #include "opasswd.h"
+@@ -76,6 +86,19 @@ typedef struct {
+ char *old_passwords;
+ } opwd;
+
++#ifdef HELPER_COMPILE
++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();
++}
++#endif
+
+ static int
+ parse_entry (char *line, opwd *data)
+@@ -117,8 +140,8 @@ compare_password(const char *newpass, co
+ }
+
+ /* Check, if the new password is already in the opasswd file. */
+-int
+-check_old_pass (pam_handle_t *pamh, const char *user,
++PAMH_ARG_DECL(int
++check_old_pass, const char *user,
+ const char *newpass, int debug)
+ {
+ int retval = PAM_SUCCESS;
+@@ -128,6 +151,11 @@ check_old_pass (pam_handle_t *pamh, cons
+ opwd entry;
+ int found = 0;
+
++#ifndef HELPER_COMPILE
++ if (SELINUX_ENABLED)
++ return PAM_PWHISTORY_RUN_HELPER;
++#endif
++
+ if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL)
+ {
+ if (errno != ENOENT)
+@@ -213,9 +241,9 @@ check_old_pass (pam_handle_t *pamh, cons
+ return retval;
+ }
+
+-int
+-save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
+- const char *oldpass, int howmany, int debug UNUSED)
++PAMH_ARG_DECL(int
++save_old_pass, const char *user,
++ int howmany, int debug UNUSED)
+ {
+ char opasswd_tmp[] = TMP_PASSWORDS_FILE;
+ struct stat opasswd_stat;
+@@ -226,10 +254,35 @@ save_old_pass (pam_handle_t *pamh, const
+ char *buf = NULL;
+ size_t buflen = 0;
+ int found = 0;
++ struct passwd *pwd;
++ const char *oldpass;
++
++ pwd = pam_modutil_getpwnam (pamh, user);
++ if (pwd == NULL)
++ return PAM_USER_UNKNOWN;
+
+ if (howmany <= 0)
+ return PAM_SUCCESS;
+
++#ifndef HELPER_COMPILE
++ if (SELINUX_ENABLED)
++ return PAM_PWHISTORY_RUN_HELPER;
++#endif
++
++ if ((strcmp(pwd->pw_passwd, "x") == 0) ||
++ ((pwd->pw_passwd[0] == '#') &&
++ (pwd->pw_passwd[1] == '#') &&
++ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
++ {
++ struct spwd *spw = pam_modutil_getspnam (pamh, user);
++
++ if (spw == NULL)
++ return PAM_USER_UNKNOWN;
++ oldpass = spw->sp_pwdp;
++ }
++ else
++ oldpass = pwd->pw_passwd;
++
+ if (oldpass == NULL || *oldpass == '\0')
+ return PAM_SUCCESS;
+
+@@ -452,7 +505,7 @@ save_old_pass (pam_handle_t *pamh, const
+ {
+ char *out;
+
+- if (asprintf (&out, "%s:%d:1:%s\n", user, uid, oldpass) < 0)
++ if (asprintf (&out, "%s:%d:1:%s\n", user, pwd->pw_uid, oldpass) < 0)
+ {
+ retval = PAM_AUTHTOK_ERR;
+ if (oldpf)
+diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h
+--- Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h.pwhhelper 2016-03-24 12:45:42.000000000 +0100
++++ Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h 2016-05-06 15:18:42.307637933 +0200
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
++ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+@@ -36,10 +37,32 @@
+ #ifndef __OPASSWD_H__
+ #define __OPASSWD_H__
+
+-extern int check_old_pass (pam_handle_t *pamh, const char *user,
+- const char *newpass, int debug);
+-extern int save_old_pass (pam_handle_t *pamh, const char *user,
+- uid_t uid, const char *oldpass,
+- int howmany, int debug);
++#define PAM_PWHISTORY_RUN_HELPER PAM_CRED_INSUFFICIENT
++
++#ifdef WITH_SELINUX
++#include <selinux/selinux.h>
++#define SELINUX_ENABLED is_selinux_enabled()>0
++#else
++#define SELINUX_ENABLED 0
++#endif
++
++#ifdef HELPER_COMPILE
++#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__)
++#define PAMH_ARG(...) __VA_ARGS__
++#else
++#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__)
++#define PAMH_ARG(...) pamh, __VA_ARGS__
++#endif
++
++#ifdef HELPER_COMPILE
++void
++helper_log_err(int err, const char *format, ...);
++#endif
++
++PAMH_ARG_DECL(int
++check_old_pass, const char *user, const char *newpass, int debug);
++
++PAMH_ARG_DECL(int
++save_old_pass, const char *user, int howmany, int debug);
+
+ #endif /* __OPASSWD_H__ */
+diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c
+--- Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c.pwhhelper 2016-04-04 11:22:28.000000000 +0200
++++ Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c 2016-05-06 15:19:31.610785512 +0200
+@@ -1,6 +1,7 @@
+ /*
+ * Copyright (c) 2008, 2012 Thorsten Kukuk
+ * Author: Thorsten Kukuk <kukuk@thkukuk.de>
++ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+@@ -46,10 +47,14 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+-#include <shadow.h>
+ #include <syslog.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <sys/time.h>
++#include <sys/resource.h>
++#include <sys/wait.h>
++#include <signal.h>
++#include <fcntl.h>
+
+ #include <security/pam_modules.h>
+ #include <security/pam_modutil.h>
+@@ -59,6 +64,7 @@
+ #include "opasswd.h"
+
+ #define DEFAULT_BUFLEN 2048
++#define MAX_FD_NO 20000
+
+ struct options_t {
+ int debug;
+@@ -102,6 +108,184 @@ parse_option (pam_handle_t *pamh, const
+ pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv);
+ }
+
++static int
++run_save_helper(pam_handle_t *pamh, const char *user,
++ int howmany, int debug)
++{
++ int retval, child;
++ struct sigaction newsa, oldsa;
++
++ memset(&newsa, '\0', sizeof(newsa));
++ newsa.sa_handler = SIG_DFL;
++ sigaction(SIGCHLD, &newsa, &oldsa);
++
++ child = fork();
++ if (child == 0)
++ {
++ int i = 0;
++ struct rlimit rlim;
++ int dummyfds[2];
++ static char *envp[] = { NULL };
++ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
++
++ /* replace std file descriptors with a dummy pipe */
++ if (pipe2(dummyfds, O_NONBLOCK) == 0)
++ {
++ dup2(dummyfds[0], STDIN_FILENO);
++ dup2(dummyfds[1], STDOUT_FILENO);
++ dup2(dummyfds[1], STDERR_FILENO);
++ }
++
++ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0)
++ {
++ if (rlim.rlim_max >= MAX_FD_NO)
++ rlim.rlim_max = MAX_FD_NO;
++ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++)
++ {
++ if (i != dummyfds[0])
++ close(i);
++ }
++ }
++
++ /* exec binary helper */
++ args[0] = strdup(PWHISTORY_HELPER);
++ args[1] = strdup("save");
++ args[2] = x_strdup(user);
++ asprintf(&args[3], "%d", howmany);
++ asprintf(&args[4], "%d", debug);
++
++ execve(args[0], args, envp);
++
++ _exit(PAM_SYSTEM_ERR);
++ }
++ else if (child > 0)
++ {
++ /* wait for child */
++ int rc = 0;
++ rc = waitpid(child, &retval, 0); /* wait for helper to complete */
++ if (rc < 0)
++ {
++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save waitpid returned %d: %m", rc);
++ retval = PAM_SYSTEM_ERR;
++ }
++ else if (!WIFEXITED(retval))
++ {
++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save abnormal exit: %d", retval);
++ retval = PAM_SYSTEM_ERR;
++ }
++ else
++ {
++ retval = WEXITSTATUS(retval);
++ }
++ }
++ else
++ {
++ retval = PAM_SYSTEM_ERR;
++ }
++
++ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
++
++ return retval;
++}
++
++static int
++run_check_helper(pam_handle_t *pamh, const char *user,
++ const char *newpass, int debug)
++{
++ int retval, child, fds[2];
++ struct sigaction newsa, oldsa;
++
++ /* create a pipe for the password */
++ if (pipe(fds) != 0)
++ return PAM_SYSTEM_ERR;
++
++ memset(&newsa, '\0', sizeof(newsa));
++ newsa.sa_handler = SIG_DFL;
++ sigaction(SIGCHLD, &newsa, &oldsa);
++
++ child = fork();
++ if (child == 0)
++ {
++ int i = 0;
++ struct rlimit rlim;
++ int dummyfds[2];
++ static char *envp[] = { NULL };
++ char *args[] = { NULL, NULL, NULL, NULL, NULL };
++
++ /* reopen stdin as pipe */
++ dup2(fds[0], STDIN_FILENO);
++
++ /* replace std file descriptors with a dummy pipe */
++ if (pipe2(dummyfds, O_NONBLOCK) == 0)
++ {
++ dup2(dummyfds[1], STDOUT_FILENO);
++ dup2(dummyfds[1], STDERR_FILENO);
++ }
++
++ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0)
++ {
++ if (rlim.rlim_max >= MAX_FD_NO)
++ rlim.rlim_max = MAX_FD_NO;
++ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++)
++ {
++ if (i != dummyfds[0])
++ close(i);
++ }
++ }
++
++ /* exec binary helper */
++ args[0] = strdup(PWHISTORY_HELPER);
++ args[1] = strdup("check");
++ args[2] = x_strdup(user);
++ asprintf(&args[3], "%d", debug);
++
++ execve(args[0], args, envp);
++
++ _exit(PAM_SYSTEM_ERR);
++ }
++ else if (child > 0)
++ {
++ /* wait for child */
++ int rc = 0;
++ if (newpass == NULL)
++ newpass = "";
++
++ /* send the password to the child */
++ if (write(fds[1], newpass, strlen(newpass)+1) == -1)
++ {
++ pam_syslog(pamh, LOG_ERR, "Cannot send password to helper: %m");
++ retval = PAM_SYSTEM_ERR;
++ }
++ newpass = NULL;
++ close(fds[0]); /* close here to avoid possible SIGPIPE above */
++ close(fds[1]);
++ rc = waitpid(child, &retval, 0); /* wait for helper to complete */
++ if (rc < 0)
++ {
++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check waitpid returned %d: %m", rc);
++ retval = PAM_SYSTEM_ERR;
++ }
++ else if (!WIFEXITED(retval))
++ {
++ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check abnormal exit: %d", retval);
++ retval = PAM_SYSTEM_ERR;
++ }
++ else
++ {
++ retval = WEXITSTATUS(retval);
++ }
++ }
++ else
++ {
++ close(fds[0]);
++ close(fds[1]);
++ retval = PAM_SYSTEM_ERR;
++ }
++
++ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
++
++ return retval;
++}
+
+ /* This module saves the current crypted password in /etc/security/opasswd
+ and then compares the new password with all entries in this file. */
+@@ -109,7 +293,6 @@ parse_option (pam_handle_t *pamh, const
+ int
+ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+- struct passwd *pwd;
+ const char *newpass;
+ const char *user;
+ int retval, tries;
+@@ -154,31 +337,13 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
+ return PAM_SUCCESS;
+ }
+
+- pwd = pam_modutil_getpwnam (pamh, user);
+- if (pwd == NULL)
+- return PAM_USER_UNKNOWN;
+-
+- if ((strcmp(pwd->pw_passwd, "x") == 0) ||
+- ((pwd->pw_passwd[0] == '#') &&
+- (pwd->pw_passwd[1] == '#') &&
+- (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
+- {
+- struct spwd *spw = pam_modutil_getspnam (pamh, user);
+- if (spw == NULL)
+- return PAM_USER_UNKNOWN;
++ retval = save_old_pass (pamh, user, options.remember, options.debug);
+
+- retval = save_old_pass (pamh, user, pwd->pw_uid, spw->sp_pwdp,
+- options.remember, options.debug);
+- if (retval != PAM_SUCCESS)
+- return retval;
+- }
+- else
+- {
+- retval = save_old_pass (pamh, user, pwd->pw_uid, pwd->pw_passwd,
+- options.remember, options.debug);
+- if (retval != PAM_SUCCESS)
+- return retval;
+- }
++ if (retval == PAM_PWHISTORY_RUN_HELPER)
++ retval = run_save_helper(pamh, user, options.remember, options.debug);
++
++ if (retval != PAM_SUCCESS)
++ return retval;
+
+ newpass = NULL;
+ tries = 0;
+@@ -207,8 +372,11 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
+ if (options.debug)
+ pam_syslog (pamh, LOG_DEBUG, "check against old password file");
+
+- if (check_old_pass (pamh, user, newpass,
+- options.debug) != PAM_SUCCESS)
++ retval = check_old_pass (pamh, user, newpass, options.debug);
++ if (retval == PAM_PWHISTORY_RUN_HELPER)
++ retval = run_check_helper(pamh, user, newpass, options.debug);
++
++ if (retval != PAM_SUCCESS)
+ {
+ if (getuid() || options.enforce_for_root ||
+ (flags & PAM_CHANGE_EXPIRED_AUTHTOK))
+diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c
+--- Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c.pwhhelper 2016-05-06 15:18:42.308637957 +0200
++++ Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c 2016-05-06 15:18:42.308637957 +0200
+@@ -0,0 +1,209 @@
++/*
++ * Copyright (c) 2013 Red Hat, Inc.
++ * Author: Tomas Mraz <tmraz@redhat.com>
++ *
++ * 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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <syslog.h>
++#include <errno.h>
++#include <unistd.h>
++#include <signal.h>
++#include <security/_pam_types.h>
++#include <security/_pam_macros.h>
++#include "opasswd.h"
++
++#define MAXPASS 200
++
++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 ) {
++ struct sigaction sa;
++ memset(&sa, '\0', sizeof(sa));
++ sa.sa_handler = SIG_DFL;
++ sigaction(sig, &sa, NULL);
++ }
++#endif
++ if (sig > 0) {
++ _exit(sig);
++ }
++}
++
++static void
++setup_signals(void)
++{
++ struct sigaction action; /* posix signal structure */
++
++ /*
++ * Setup signal handlers
++ */
++ (void) memset((void *) &action, 0, sizeof(action));
++ action.sa_handler = su_sighandler;
++#ifdef SA_RESETHAND
++ action.sa_flags = SA_RESETHAND;
++#endif
++ (void) sigaction(SIGILL, &action, NULL);
++ (void) sigaction(SIGTRAP, &action, NULL);
++ (void) sigaction(SIGBUS, &action, NULL);
++ (void) sigaction(SIGSEGV, &action, NULL);
++ action.sa_handler = SIG_IGN;
++ action.sa_flags = 0;
++ (void) sigaction(SIGTERM, &action, NULL);
++ (void) sigaction(SIGHUP, &action, NULL);
++ (void) sigaction(SIGINT, &action, NULL);
++ (void) sigaction(SIGQUIT, &action, NULL);
++}
++
++static int
++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;
++}
++
++
++static int
++check_history(const char *user, const char *debug)
++{
++ char pass[MAXPASS + 1];
++ char *passwords[] = { pass };
++ int npass;
++ int dbg = atoi(debug); /* no need to be too fancy here */
++ int retval;
++
++ /* read the password from stdin (a pipe from the pam_pwhistory module) */
++ npass = read_passwords(STDIN_FILENO, 1, passwords);
++
++ if (npass != 1)
++ { /* is it a valid password? */
++ helper_log_err(LOG_DEBUG, "no password supplied");
++ return PAM_AUTHTOK_ERR;
++ }
++
++ retval = check_old_pass(user, pass, dbg);
++
++ memset(pass, '\0', MAXPASS); /* clear memory of the password */
++
++ return retval;
++}
++
++static int
++save_history(const char *user, const char *howmany, const char *debug)
++{
++ int num = atoi(howmany);
++ int dbg = atoi(debug); /* no need to be too fancy here */
++ int retval;
++
++ retval = save_old_pass(user, num, dbg);
++
++ return retval;
++}
++
++int
++main(int argc, char *argv[])
++{
++ const char *option;
++ const char *user;
++
++ /*
++ * 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.
++ */
++
++ if (isatty(STDIN_FILENO) || argc < 4)
++ {
++ fprintf(stderr,
++ "This binary is not designed for running in this way.\n");
++ sleep(10); /* this should discourage/annoy the user */
++ return PAM_SYSTEM_ERR;
++ }
++
++ option = argv[1];
++ user = argv[2];
++
++ if (strcmp(option, "check") == 0 && argc == 4)
++ return check_history(user, argv[3]);
++ else if (strcmp(option, "save") == 0 && argc == 5)
++ return save_history(user, argv[3], argv[4]);
++
++ return PAM_SYSTEM_ERR;
++}
++
+diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml
+--- Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml.pwhhelper 2016-05-06 15:18:42.308637957 +0200
++++ Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml 2016-05-06 15:18:42.308637957 +0200
+@@ -0,0 +1,68 @@
++<?xml version="1.0" encoding='UTF-8'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
++ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
++
++<refentry id="pwhistory_helper">
++
++ <refmeta>
++ <refentrytitle>pwhistory_helper</refentrytitle>
++ <manvolnum>8</manvolnum>
++ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
++ </refmeta>
++
++ <refnamediv id="pwhistory_helper-name">
++ <refname>pwhistory_helper</refname>
++ <refpurpose>Helper binary that transfers password hashes from passwd or shadow to opasswd</refpurpose>
++ </refnamediv>
++
++ <refsynopsisdiv>
++ <cmdsynopsis id="pwhistory_helper-cmdsynopsis">
++ <command>pwhistory_helper</command>
++ <arg choice="opt">
++ ...
++ </arg>
++ </cmdsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1 id="pwhistory_helper-description">
++
++ <title>DESCRIPTION</title>
++
++ <para>
++ <emphasis>pwhistory_helper</emphasis> is a helper program for the
++ <emphasis>pam_pwhistory</emphasis> module that transfers password hashes
++ from passwd or shadow file to the opasswd file and checks a password
++ supplied by user against the existing hashes in the opasswd file.
++ </para>
++
++ <para>
++ The purpose of the helper is to enable tighter confinement of
++ login and password changing services. The helper is thus called only
++ when SELinux is enabled on the system.
++ </para>
++
++ <para>
++ The interface of the helper - command line options, and input/output
++ data format are internal to the <emphasis>pam_pwhistory</emphasis>
++ module and it should not be called directly from applications.
++ </para>
++ </refsect1>
++
++ <refsect1 id='pwhistory_helper-see_also'>
++ <title>SEE ALSO</title>
++ <para>
++ <citerefentry>
++ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum>
++ </citerefentry>
++ </para>
++ </refsect1>
++
++ <refsect1 id='pwhistory_helper-author'>
++ <title>AUTHOR</title>
++ <para>
++ Written by Tomas Mraz based on the code originally in
++ <emphasis>pam_pwhistory and pam_unix</emphasis> modules.
++ </para>
++ </refsect1>
++
++</refentry>
diff --git a/source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch b/source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch
new file mode 100644
index 000000000..33c226773
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.0-unix-nomsg.patch
@@ -0,0 +1,16 @@
+diff -up Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c.nomsg Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c
+--- Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c.nomsg 2016-04-11 13:08:47.000000000 +0200
++++ Linux-PAM-1.3.0/modules/pam_unix/pam_unix_passwd.c 2017-04-20 16:51:24.853106709 +0200
+@@ -687,12 +687,6 @@ pam_sm_chauthtok(pam_handle_t *pamh, int
+ return PAM_SUCCESS;
+ } else if (off(UNIX__IAMROOT, ctrl) ||
+ (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, user, 0, 1))) {
+- /* instruct user what is happening */
+- if (off(UNIX__QUIET, ctrl)) {
+- retval = pam_info(pamh, _("Changing password for %s."), user);
+- if (retval != PAM_SUCCESS)
+- return retval;
+- }
+ retval = pam_get_authtok(pamh, PAM_OLDAUTHTOK, &pass_old, NULL);
+
+ if (retval != PAM_SUCCESS) {
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-coverity.patch b/source/a/pam/fedora-patches/pam-1.3.1-coverity.patch
new file mode 100644
index 000000000..cecf768f6
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-coverity.patch
@@ -0,0 +1,185 @@
+diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
+index 106ef7c..b2e94c7 100644
+--- a/libpam/pam_handlers.c
++++ b/libpam/pam_handlers.c
+@@ -282,7 +282,6 @@ _pam_open_config_file(pam_handle_t *pamh
+ {
+ char *p;
+ FILE *f;
+- int err = 0;
+
+ /* Absolute path */
+ if (service[0] == '/') {
+diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c
+index be53f34..07dce36 100644
+--- a/libpam_misc/misc_conv.c
++++ b/libpam_misc/misc_conv.c
+@@ -211,7 +211,7 @@ static int read_string(int echo, const char *prompt, char **retstr)
+ line[nc] = '\0';
+ }
+ *retstr = strdup(line);
+- _pam_overwrite(line);
++ _pam_overwrite_n(line, sizeof(line));
+ if (!*retstr) {
+ D(("no memory for response string"));
+ nc = -1;
+@@ -244,7 +244,7 @@ static int read_string(int echo, const char *prompt, char **retstr)
+ D(("the timer appears to have expired"));
+
+ *retstr = NULL;
+- _pam_overwrite(line);
++ _pam_overwrite_n(line, sizeof(line));
+
+ cleanexit:
+
+diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
+index 80d885d..3801862 100644
+--- a/modules/pam_access/pam_access.c
++++ b/modules/pam_access/pam_access.c
+@@ -806,7 +806,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
+ const char *user=NULL;
+ const void *void_from=NULL;
+ const char *from;
+- const char const *default_config = PAM_ACCESS_CONFIG;
++ const char * const default_config = PAM_ACCESS_CONFIG;
+ struct passwd *user_pw;
+ char hostname[MAXHOSTNAMELEN + 1];
+ int rv;
+diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
+index 4bc4ae7..f8476b4 100644
+--- a/modules/pam_limits/pam_limits.c
++++ b/modules/pam_limits/pam_limits.c
+@@ -342,7 +342,7 @@ static const char *lnames[RLIM_NLIMITS] = {
+ #endif
+ };
+
+-static int str2rlimit(char *name) {
++static int str2rlimit(const char *name) {
+ int i;
+ if (!name || *name == '\0')
+ return -1;
+@@ -352,7 +352,7 @@ static int str2rlimit(char *name) {
+ return -1;
+ }
+
+-static rlim_t str2rlim_t(char *value) {
++static rlim_t str2rlim_t(const char *value) {
+ unsigned long long rlimit = 0;
+
+ if (!value) return (rlim_t)rlimit;
+@@ -384,7 +384,7 @@ static void parse_kernel_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int
+ FILE *limitsfile;
+ const char *proclimits = "/proc/1/limits";
+ char line[256];
+- char *units, *hard, *soft, *name;
++ const char *units, *hard, *soft, *name;
+
+ if (!(limitsfile = fopen(proclimits, "r"))) {
+ pam_syslog(pamh, LOG_WARNING, "Could not read %s (%s), using PAM defaults", proclimits, strerror(errno));
+diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
+index 96bfd98..66d202c 100644
+--- a/modules/pam_loginuid/pam_loginuid.c
++++ b/modules/pam_loginuid/pam_loginuid.c
+@@ -64,7 +64,7 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
+ fd = open("/proc/self/uid_map", O_RDONLY);
+ if (fd >= 0) {
+ count = pam_modutil_read(fd, uid_map, sizeof(uid_map));
+- if (strncmp(uid_map, host_uid_map, count) != 0)
++ if (count <= 0 || strncmp(uid_map, host_uid_map, count) != 0)
+ rc = PAM_IGNORE;
+ close(fd);
+ }
+diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c
+index 9e204c1..4b8d6b7 100644
+--- a/modules/pam_mkhomedir/mkhomedir_helper.c
++++ b/modules/pam_mkhomedir/mkhomedir_helper.c
+@@ -232,6 +232,8 @@ create_homedir(const struct passwd *pwd,
+ {
+ pam_syslog(NULL, LOG_DEBUG,
+ "unable to open or stat src file %s: %m", newsource);
++ if (srcfd >= 0)
++ close(srcfd);
+ closedir(d);
+
+ #ifndef PATH_MAX
+diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
+index f541f89..85f5efa 100644
+--- a/modules/pam_namespace/pam_namespace.c
++++ b/modules/pam_namespace/pam_namespace.c
+@@ -1418,6 +1418,7 @@ static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat *
+ if (fstat(fd, &newstatbuf) < 0) {
+ pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m",
+ ipath);
++ close(fd);
+ rmdir(ipath);
+ return PAM_SESSION_ERR;
+ }
+diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
+index e6cf346..813f579 100644
+--- a/modules/pam_pwhistory/opasswd.c
++++ b/modules/pam_pwhistory/opasswd.c
+@@ -326,6 +326,9 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
+ n = strlen (buf);
+ #endif /* HAVE_GETLINE / HAVE_GETDELIM */
+
++ if (n < 1)
++ break;
++
+ cp = buf;
+ save = strdup (buf); /* Copy to write the original data back. */
+ if (save == NULL)
+@@ -336,9 +339,6 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
+ goto error_opasswd;
+ }
+
+- if (n < 1)
+- break;
+-
+ tmp = strchr (cp, '#'); /* remove comments */
+ if (tmp)
+ *tmp = '\0';
+diff --git a/modules/pam_rootok/pam_rootok.c b/modules/pam_rootok/pam_rootok.c
+index 17baabe..a9d9140 100644
+--- a/modules/pam_rootok/pam_rootok.c
++++ b/modules/pam_rootok/pam_rootok.c
+@@ -66,14 +66,17 @@ log_callback (int type, const char *fmt, ...)
+ int audit_fd;
+ va_list ap;
+
+- va_start(ap, fmt);
+ #ifdef HAVE_LIBAUDIT
+ audit_fd = audit_open();
+
+ if (audit_fd >= 0) {
+ char *buf;
++ int ret;
+
+- if (vasprintf (&buf, fmt, ap) < 0)
++ va_start(ap, fmt);
++ ret = vasprintf (&buf, fmt, ap);
++ va_end(ap);
++ if (ret < 0)
+ return 0;
+ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
+ NULL, 0);
+@@ -83,6 +86,7 @@ log_callback (int type, const char *fmt, ...)
+ }
+
+ #endif
++ va_start(ap, fmt);
+ vsyslog (LOG_USER | LOG_INFO, fmt, ap);
+ va_end(ap);
+ return 0;
+diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c
+index c653290..f37af0f 100644
+--- a/modules/pam_sepermit/pam_sepermit.c
++++ b/modules/pam_sepermit/pam_sepermit.c
+@@ -353,7 +353,7 @@ sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
+ if (*sense == PAM_SUCCESS) {
+ if (ignore)
+ *sense = PAM_IGNORE;
+- if (geteuid() == 0 && exclusive && get_loginuid(pamh) == -1)
++ if (geteuid() == 0 && exclusive && get_loginuid(pamh) == (uid_t)-1)
+ if (sepermit_lock(pamh, user, debug) < 0)
+ *sense = PAM_AUTH_ERR;
+ }
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch b/source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch
new file mode 100644
index 000000000..a0b069815
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-motd-multiple-paths.patch
@@ -0,0 +1,755 @@
+diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml
+index 906c4ed..4e2110c 100644
+--- a/modules/pam_motd/pam_motd.8.xml
++++ b/modules/pam_motd/pam_motd.8.xml
+@@ -21,6 +21,9 @@
+ <arg choice="opt">
+ motd=<replaceable>/path/filename</replaceable>
+ </arg>
++ <arg choice="opt">
++ motd_dir=<replaceable>/path/dirname.d</replaceable>
++ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+@@ -31,10 +34,49 @@
+ <para>
+ pam_motd is a PAM module that can be used to display
+ arbitrary motd (message of the day) files after a successful
+- login. By default the <filename>/etc/motd</filename> file is
+- shown. The message size is limited to 64KB.
++ login. By default, pam_motd shows files in the
++ following locations:
++ </para>
++ <para>
++ <simplelist type='vert'>
++ <member><filename>/etc/motd</filename></member>
++ <member><filename>/run/motd</filename></member>
++ <member><filename>/usr/lib/motd</filename></member>
++ <member><filename>/etc/motd.d/</filename></member>
++ <member><filename>/run/motd.d/</filename></member>
++ <member><filename>/usr/lib/motd.d/</filename></member>
++ </simplelist>
++ </para>
++ <para>
++ Each message size is limited to 64KB.
++ </para>
++ <para>
++ If <filename>/etc/motd</filename> does not exist,
++ then <filename>/run/motd</filename> is shown. If
++ <filename>/run/motd</filename> does not exist, then
++ <filename>/usr/lib/motd</filename> is shown.
++ </para>
++ <para>
++ Similar overriding behavior applies to the directories.
++ Files in <filename>/etc/motd.d/</filename> override files
++ with the same name in <filename>/run/motd.d/</filename> and
++ <filename>/usr/lib/motd.d/</filename>. Files in <filename>/run/motd.d/</filename>
++ override files with the same name in <filename>/usr/lib/motd.d/</filename>.
++ </para>
++ <para>
++ Files the in the directories listed above are displayed in
++ lexicographic order by name.
++ </para>
++ <para>
++ To silence a message,
++ a symbolic link with target <filename>/dev/null</filename>
++ may be placed in <filename>/etc/motd.d</filename> with
++ the same filename as the message to be silenced. Example:
++ Creating a symbolic link as follows silences <filename>/usr/lib/motd.d/my_motd</filename>.
++ </para>
++ <para>
++ <command>ln -s /dev/null /etc/motd.d/my_motd</command>
+ </para>
+-
+ </refsect1>
+
+ <refsect1 id="pam_motd-options">
+@@ -47,8 +89,10 @@
+ </term>
+ <listitem>
+ <para>
+- The <filename>/path/filename</filename> file is displayed
+- as message of the day.
++ The <filename>/path/filename</filename> file is displayed
++ as message of the day. Multiple paths to try can be
++ specified as a colon-separated list. By default this option
++ is set to <filename>/etc/motd:/run/motd:/usr/lib/motd</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -59,16 +103,17 @@
+ <listitem>
+ <para>
+ The <filename>/path/dirname.d</filename> directory is scanned
+- and each file contained inside of it is displayed.
++ and each file contained inside of it is displayed. Multiple
++ directories to scan can be specified as a colon-separated list.
++ By default this option is set to <filename>/etc/motd.d:/run/motd.d:/usr/lib/motd.d</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+- When no options are given, the default is to display both
+- <filename>/etc/motd</filename> and the contents of
+- <filename>/etc/motd.d</filename>. Specifying either option (or both)
+- will disable this default behavior.
++ When no options are given, the default behavior applies for both
++ options. Specifying either option (or both) will disable the
++ default behavior for both options.
+ </para>
+ </refsect1>
+
+diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
+index cc828d7..ec3ebd5 100644
+--- a/modules/pam_motd/pam_motd.c
++++ b/modules/pam_motd/pam_motd.c
+@@ -33,8 +33,8 @@
+ */
+
+ #define PAM_SM_SESSION
+-#define DEFAULT_MOTD "/etc/motd"
+-#define DEFAULT_MOTD_D "/etc/motd.d"
++#define DEFAULT_MOTD "/etc/motd:/run/motd:/usr/lib/motd"
++#define DEFAULT_MOTD_D "/etc/motd.d:/run/motd.d:/usr/lib/motd.d"
+
+ #include <security/pam_modules.h>
+ #include <security/pam_modutil.h>
+@@ -97,12 +97,234 @@ static void try_to_display_directory(pam_handle_t *pamh, const char *dirname)
+ }
+ }
+
++/*
++ * Split a DELIM-separated string ARG into an array.
++ * Outputs a newly allocated array of strings OUT_ARG_SPLIT
++ * and the number of strings OUT_NUM_STRS.
++ * Returns 0 in case of error, 1 in case of success.
++ */
++static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
++ char ***out_arg_split, uint *out_num_strs)
++{
++ char *arg_extracted = NULL;
++ const char *arg_ptr = arg;
++ char **arg_split = NULL;
++ char delim_str[2];
++ int i = 0;
++ uint num_strs = 0;
++ int retval = 0;
++
++ delim_str[0] = delim;
++ delim_str[1] = '\0';
++
++ if (arg == NULL) {
++ goto out;
++ }
++
++ while (arg_ptr != NULL) {
++ num_strs++;
++ arg_ptr = strchr(arg_ptr + sizeof(const char), delim);
++ }
++
++ arg_split = (char **)calloc(num_strs, sizeof(char *));
++ if (arg_split == NULL) {
++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate string array");
++ goto out;
++ }
++
++ arg_extracted = strtok_r(arg, delim_str, &arg);
++ while (arg_extracted != NULL && i < num_strs) {
++ arg_split[i++] = arg_extracted;
++ arg_extracted = strtok_r(NULL, delim_str, &arg);
++ }
++
++ retval = 1;
++
++ out:
++ *out_num_strs = num_strs;
++ *out_arg_split = arg_split;
++
++ return retval;
++}
++
++/* Join A_STR and B_STR, inserting a "/" between them if one is not already trailing
++ * in A_STR or beginning B_STR. A pointer to a newly allocated string holding the
++ * joined string is returned in STRP_OUT.
++ * Returns -1 in case of error, or the number of bytes in the joined string in
++ * case of success. */
++static int join_dir_strings(char **strp_out, const char *a_str, const char *b_str)
++{
++ int has_sep = 0;
++ int retval = -1;
++ char *join_strp = NULL;
++
++ if (strp_out == NULL || a_str == NULL || b_str == NULL) {
++ goto out;
++ }
++ if (strlen(a_str) == 0) {
++ goto out;
++ }
++
++ has_sep = (a_str[strlen(a_str) - 1] == '/') || (b_str[0] == '/');
++
++ retval = asprintf(&join_strp, "%s%s%s", a_str,
++ (has_sep == 1) ? "" : "/", b_str);
++
++ if (retval < 0) {
++ goto out;
++ }
++
++ *strp_out = join_strp;
++
++ out:
++ return retval;
++}
++
++static int compare_strings(const void * a, const void * b)
++{
++ const char *a_str = *(char **)a;
++ const char *b_str = *(char **)b;
++
++ if (a_str == NULL && b_str == NULL) {
++ return 0;
++ }
++ else if (a_str == NULL) {
++ return -1;
++ }
++ else if (b_str == NULL) {
++ return 1;
++ }
++ else {
++ return strcmp(a_str, b_str);
++ }
++}
++
++static int filter_dirents(const struct dirent *d)
++{
++ return (d->d_type == DT_REG || d->d_type == DT_LNK);
++}
++
++static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
++ char **motd_dir_path_split, int num_motd_dirs)
++{
++ struct dirent ***dirscans = NULL;
++ int *dirscans_sizes = NULL;
++ int dirscans_size_total = 0;
++ char **dirnames_all = NULL;
++ int i;
++ int i_dirnames = 0;
++
++ if (pamh == NULL || motd_dir_path_split == NULL) {
++ goto out;
++ }
++ if (num_motd_dirs < 1) {
++ goto out;
++ }
++
++ if ((dirscans = (struct dirent ***)calloc(num_motd_dirs,
++ sizeof(struct dirent **))) == NULL) {
++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent arrays");
++ goto out;
++ }
++ if ((dirscans_sizes = (int *)calloc(num_motd_dirs, sizeof(int))) == NULL) {
++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirent array sizes");
++ goto out;
++ }
++
++ for (i = 0; i < num_motd_dirs; i++) {
++ dirscans_sizes[i] = scandir(motd_dir_path_split[i], &(dirscans[i]),
++ filter_dirents, alphasort);
++ if (dirscans_sizes[i] < 0) {
++ pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s", motd_dir_path_split[i]);
++ dirscans_sizes[i] = 0;
++ }
++ dirscans_size_total += dirscans_sizes[i];
++ }
++
++ /* Allocate space for all file names found in the directories, including duplicates. */
++ if ((dirnames_all = (char **)calloc(dirscans_size_total,
++ sizeof(char *))) == NULL) {
++ pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array");
++ goto out;
++ }
++
++ for (i = 0; i < dirscans_size_total; i++) {
++ dirnames_all[i] = NULL;
++ }
++
++ for (i = 0; i < num_motd_dirs; i++) {
++ int j;
++
++ for (j = 0; j < dirscans_sizes[i]; j++) {
++ dirnames_all[i_dirnames] = dirscans[i][j]->d_name;
++ i_dirnames++;
++ }
++ }
++
++ qsort(dirnames_all, dirscans_size_total,
++ sizeof(const char *), compare_strings);
++
++ for (i = 0; i < dirscans_size_total; i++) {
++ int j;
++
++ if (dirnames_all[i] == NULL) {
++ continue;
++ }
++
++ /* Skip duplicate file names. */
++ if (i > 0 && strcmp(dirnames_all[i], dirnames_all[i - 1]) == 0) {
++ continue;
++ }
++
++ for (j = 0; j < num_motd_dirs; j++) {
++ char *abs_path = NULL;
++
++ if (join_dir_strings(&abs_path, motd_dir_path_split[j],
++ dirnames_all[i]) < 0) {
++ continue;
++ }
++
++ if (abs_path != NULL) {
++ int fd = open(abs_path, O_RDONLY, 0);
++ if (fd >= 0) {
++ try_to_display_fd(pamh, fd);
++ close(fd);
++
++ /* We displayed a file, skip to the next file name. */
++ break;
++ }
++ }
++ _pam_drop(abs_path);
++ }
++ }
++
++ out:
++ _pam_drop(dirnames_all);
++ for (i = 0; i < num_motd_dirs; i++) {
++ int j;
++ for (j = 0; j < dirscans_sizes[i]; j++) {
++ _pam_drop(dirscans[i][j]);
++ }
++ _pam_drop(dirscans[i]);
++ }
++ _pam_drop(dirscans_sizes);
++ _pam_drop(dirscans);
++
++ return;
++}
++
+ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+ int argc, const char **argv)
+ {
+ int retval = PAM_IGNORE;
+ const char *motd_path = NULL;
++ char *motd_path_copy = NULL;
++ int num_motd_paths = 0;
++ char **motd_path_split = NULL;
+ const char *motd_dir_path = NULL;
++ char *motd_dir_path_copy = NULL;
++ int num_motd_dir_paths = 0;
++ char **motd_dir_path_split = NULL;
+
+ if (flags & PAM_SILENT) {
+ return retval;
+@@ -141,16 +363,52 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+ }
+
+ if (motd_path != NULL) {
+- int fd = open(motd_path, O_RDONLY, 0);
++ motd_path_copy = strdup(motd_path);
++ }
++
++ if (motd_path_copy != NULL) {
++ if (pam_split_string(pamh, motd_path_copy, ':',
++ &motd_path_split, &num_motd_paths) == 0) {
++ goto out;
++ }
++ }
++
++ if (motd_dir_path != NULL) {
++ motd_dir_path_copy = strdup(motd_dir_path);
++ }
+
+- if (fd >= 0) {
+- try_to_display_fd(pamh, fd);
+- close(fd);
++ if (motd_dir_path_copy != NULL) {
++ if (pam_split_string(pamh, motd_dir_path_copy, ':',
++ &motd_dir_path_split, &num_motd_dir_paths) == 0) {
++ goto out;
+ }
+ }
+
+- if (motd_dir_path != NULL)
+- try_to_display_directory(pamh, motd_dir_path);
++ if (motd_path_split != NULL) {
++ int i;
++
++ for (i = 0; i < num_motd_paths; i++) {
++ int fd = open(motd_path_split[i], O_RDONLY, 0);
++
++ if (fd >= 0) {
++ try_to_display_fd(pamh, fd);
++ close(fd);
++
++ /* We found and displayed a file, move onto next filename. */
++ break;
++ }
++ }
++ }
++
++ if (motd_dir_path_split != NULL)
++ try_to_display_directories_with_overrides(pamh, motd_dir_path_split,
++ num_motd_dir_paths);
++
++ out:
++ _pam_drop(motd_path_copy);
++ _pam_drop(motd_path_split);
++ _pam_drop(motd_dir_path_copy);
++ _pam_drop(motd_dir_path_split);
+
+ return retval;
+ }
+diff --git a/xtests/Makefile.am b/xtests/Makefile.am
+index a6d6f8d..4d5aba3 100644
+--- a/xtests/Makefile.am
++++ b/xtests/Makefile.am
+@@ -32,7 +32,10 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \
+ tst-pam_substack5.pamd tst-pam_substack5a.pamd tst-pam_substack5.sh \
+ tst-pam_assemble_line1.pamd tst-pam_assemble_line1.sh \
+ tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \
+- tst-pam_time1.pamd time.conf
++ tst-pam_time1.pamd time.conf \
++ tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \
++ tst-pam_motd3.sh tst-pam_motd4.sh tst-pam_motd1.pamd \
++ tst-pam_motd2.pamd tst-pam_motd3.pamd tst-pam_motd4.pamd
+
+ XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \
+ tst-pam_dispatch4 tst-pam_dispatch5 \
+@@ -41,7 +44,7 @@ XTESTS = tst-pam_dispatch1 tst-pam_dispatch2 tst-pam_dispatch3 \
+ tst-pam_access1 tst-pam_access2 tst-pam_access3 \
+ tst-pam_access4 tst-pam_limits1 tst-pam_succeed_if1 \
+ tst-pam_group1 tst-pam_authfail tst-pam_authsucceed \
+- tst-pam_pwhistory1 tst-pam_time1
++ tst-pam_pwhistory1 tst-pam_time1 tst-pam_motd
+
+ NOSRCTESTS = tst-pam_substack1 tst-pam_substack2 tst-pam_substack3 \
+ tst-pam_substack4 tst-pam_substack5 tst-pam_assemble_line1
+diff --git a/xtests/tst-pam_motd.c b/xtests/tst-pam_motd.c
+new file mode 100644
+index 0000000..bba2f9d
+--- /dev/null
++++ b/xtests/tst-pam_motd.c
+@@ -0,0 +1,69 @@
++/*
++ * 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.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <security/pam_appl.h>
++#include <security/pam_misc.h>
++
++static struct pam_conv conv = {
++ misc_conv,
++ NULL
++};
++
++int main(int argc, char *argv[])
++{
++ pam_handle_t *pamh=NULL;
++ char *tst_arg = NULL;
++ int retval;
++
++ if (argc > 1)
++ tst_arg = argv[1];
++
++ retval = pam_start(tst_arg, NULL, &conv, &pamh);
++
++ retval = pam_open_session(pamh, 0);
++
++ retval = pam_close_session(pamh, 0);
++
++ if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
++ pamh = NULL;
++ exit(1);
++ }
++
++ return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
++}
+diff --git a/xtests/tst-pam_motd.sh b/xtests/tst-pam_motd.sh
+new file mode 100755
+index 0000000..9080128
+--- /dev/null
++++ b/xtests/tst-pam_motd.sh
+@@ -0,0 +1,8 @@
++#!/bin/bash
++
++set -e
++
++./tst-pam_motd1.sh
++./tst-pam_motd2.sh
++./tst-pam_motd3.sh
++./tst-pam_motd4.sh
+diff --git a/xtests/tst-pam_motd1.pamd b/xtests/tst-pam_motd1.pamd
+new file mode 100644
+index 0000000..ddea82c
+--- /dev/null
++++ b/xtests/tst-pam_motd1.pamd
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session required pam_permit.so
++session optional pam_motd.so motd=tst-pam_motd1.d/etc/motd motd_dir=tst-pam_motd1.d/etc/motd.d
+diff --git a/xtests/tst-pam_motd1.sh b/xtests/tst-pam_motd1.sh
+new file mode 100755
+index 0000000..cc88854
+--- /dev/null
++++ b/xtests/tst-pam_motd1.sh
+@@ -0,0 +1,36 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd1.d"
++
++function tst_cleanup() {
++ rm -rf "${TST_DIR}"
++ rm -f tst-pam_motd1.out
++}
++
++mkdir -p ${TST_DIR}
++mkdir -p ${TST_DIR}/etc/motd.d
++
++# Verify the case of single motd and motd.d directory works
++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
++echo "motd: /etc/motd.d/test" > ${TST_DIR}/etc/motd.d/test
++
++./tst-pam_motd tst-pam_motd1 > tst-pam_motd1.out
++
++RET=$?
++
++motd_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd")
++if [ -z "${motd_to_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++motd_dir_to_show_output=$(cat tst-pam_motd1.out | grep "motd: /etc/motd.d/test")
++if [ -z "${motd_dir_to_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++tst_cleanup
++exit $RET
+diff --git a/xtests/tst-pam_motd2.pamd b/xtests/tst-pam_motd2.pamd
+new file mode 100644
+index 0000000..8200191
+--- /dev/null
++++ b/xtests/tst-pam_motd2.pamd
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session required pam_permit.so
++session optional pam_motd.so motd=tst-pam_motd2.d/etc/motd:tst-pam_motd2.d/run/motd:tst-pam_motd2.d/usr/lib/motd motd_dir=tst-pam_motd2.d/etc/motd.d:tst-pam_motd2.d/run/motd.d:tst-pam_motd2.d/usr/lib/motd.d
+diff --git a/xtests/tst-pam_motd2.sh b/xtests/tst-pam_motd2.sh
+new file mode 100755
+index 0000000..d26ea92
+--- /dev/null
++++ b/xtests/tst-pam_motd2.sh
+@@ -0,0 +1,53 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd2.d"
++
++function tst_cleanup() {
++ rm -rf "${TST_DIR}"
++ rm -f tst-pam_motd2.out
++}
++
++mkdir -p ${TST_DIR}
++mkdir -p ${TST_DIR}/etc/motd.d
++mkdir -p ${TST_DIR}/run/motd.d
++mkdir -p ${TST_DIR}/usr/lib/motd.d
++
++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
++echo "motd: /run/motd" > ${TST_DIR}/run/motd
++echo "motd: /usr/lib/motd" > ${TST_DIR}/usr/lib/motd
++
++# Drop a motd file in test directories such that every overriding
++# condition (for 3 directories in this case) will be seen.
++echo "motd: e0r0u1 in usr/lib - will show" > ${TST_DIR}/usr/lib/motd.d/e0r0u1.motd
++echo "motd: e0r1u0 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u0.motd
++echo "motd: e0r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e0r1u1.motd
++echo "motd: e0r1u1 in run - will show" > ${TST_DIR}/run/motd.d/e0r1u1.motd
++echo "motd: e1r0u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u0.motd
++echo "motd: e1r0u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r0u1.motd
++echo "motd: e1r0u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r0u1.motd
++echo "motd: e1r1u0 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u0.motd
++echo "motd: e1r1u0 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u0.motd
++echo "motd: e1r1u1 in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/e1r1u1.motd
++echo "motd: e1r1u1 in run - not show" > ${TST_DIR}/run/motd.d/e1r1u1.motd
++echo "motd: e1r1u1 in etc - will show" > ${TST_DIR}/etc/motd.d/e1r1u1.motd
++
++./tst-pam_motd tst-pam_motd2 > tst-pam_motd2.out
++
++RET=$?
++
++motd_to_show_output=$(cat tst-pam_motd2.out | grep "motd: /etc/motd")
++if [ -z "${motd_to_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++motd_dir_not_show_output=$(cat tst-pam_motd2.out | grep "not show")
++if [ -n "${motd_dir_not_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++tst_cleanup
++exit $RET
+diff --git a/xtests/tst-pam_motd3.pamd b/xtests/tst-pam_motd3.pamd
+new file mode 100644
+index 0000000..a8b8cbf
+--- /dev/null
++++ b/xtests/tst-pam_motd3.pamd
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session required pam_permit.so
++session optional pam_motd.so motd=tst-pam_motd3.d/etc/motd:tst-pam_motd3.d/run/motd:tst-pam_motd3.d/usr/lib/motd motd_dir=tst-pam_motd3.d/etc/motd.d:tst-pam_motd3.d/run/motd.d:tst-pam_motd3.d/usr/lib/motd.d
+diff --git a/xtests/tst-pam_motd3.sh b/xtests/tst-pam_motd3.sh
+new file mode 100755
+index 0000000..e18856b
+--- /dev/null
++++ b/xtests/tst-pam_motd3.sh
+@@ -0,0 +1,53 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd3.d"
++
++function tst_cleanup() {
++ rm -rf "${TST_DIR}"
++ rm -f tst-pam_motd3.out
++}
++
++mkdir -p ${TST_DIR}
++mkdir -p ${TST_DIR}/etc/motd.d
++mkdir -p ${TST_DIR}/run/motd.d
++mkdir -p ${TST_DIR}/usr/lib/motd.d
++
++# Verify motd is still displayed when not overridden
++echo "motd: test-show in run - show" > ${TST_DIR}/run/motd.d/test-show.motd
++
++# Test overridden by a symlink to a file that isn't /dev/null; symlink target should show
++echo "motd: hidden-by-symlink in usr/lib - not show" > ${TST_DIR}/usr/lib/motd.d/hidden-by-symlink.motd
++echo "motd: test-from-symlink - show" > ${TST_DIR}/test-from-symlink.motd
++ln -sr ${TST_DIR}/test-from-symlink.motd ${TST_DIR}/run/motd.d/hidden-by-symlink.motd
++
++# Test hidden by a null symlink
++echo "motd: hidden-by-null-symlink in run - not show" > ${TST_DIR}/run/motd.d/hidden-by-null-symlink.motd
++ln -s /dev/null ${TST_DIR}/etc/motd.d/hidden-by-null-symlink.motd
++
++./tst-pam_motd tst-pam_motd3 > tst-pam_motd3.out
++
++RET=$?
++
++motd_dir_not_show_output=$(cat tst-pam_motd3.out | grep "not show")
++if [ -n "${motd_dir_not_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++motd_test_show_output=$(cat tst-pam_motd3.out | grep "test-show.*- show")
++if [ -z "${motd_test_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++motd_general_symlink_show_output=$(cat tst-pam_motd3.out | grep "test-from-symlink.*- show")
++if [ -z "${motd_general_symlink_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++tst_cleanup
++exit $RET
+diff --git a/xtests/tst-pam_motd4.pamd b/xtests/tst-pam_motd4.pamd
+new file mode 100644
+index 0000000..9dc311a
+--- /dev/null
++++ b/xtests/tst-pam_motd4.pamd
+@@ -0,0 +1,3 @@
++#%PAM-1.0
++session required pam_permit.so
++session optional pam_motd.so motd=tst-pam_motd4.d/etc/motd
+diff --git a/xtests/tst-pam_motd4.sh b/xtests/tst-pam_motd4.sh
+new file mode 100755
+index 0000000..6022177
+--- /dev/null
++++ b/xtests/tst-pam_motd4.sh
+@@ -0,0 +1,27 @@
++#!/bin/bash
++
++TST_DIR="tst-pam_motd4.d"
++
++function tst_cleanup() {
++ rm -rf "${TST_DIR}"
++ rm -f tst-pam_motd4.out
++}
++
++mkdir -p ${TST_DIR}/etc
++
++# Verify the case of single motd with no motd_dir given in tst-pam_motd4.pamd
++echo "motd: /etc/motd" > ${TST_DIR}/etc/motd
++
++./tst-pam_motd tst-pam_motd4 > tst-pam_motd4.out
++
++RET=$?
++
++motd_to_show_output=$(cat tst-pam_motd4.out | grep "motd: /etc/motd")
++if [ -z "${motd_to_show_output}" ];
++then
++ tst_cleanup
++ exit 1
++fi
++
++tst_cleanup
++exit $RET
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-noflex.patch b/source/a/pam/fedora-patches/pam-1.3.1-noflex.patch
new file mode 100644
index 000000000..c65d22537
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-noflex.patch
@@ -0,0 +1,24 @@
+diff -up Linux-PAM-1.3.1/doc/Makefile.am.noflex Linux-PAM-1.3.1/doc/Makefile.am
+--- Linux-PAM-1.3.1/doc/Makefile.am.noflex 2017-02-10 11:10:15.000000000 +0100
++++ Linux-PAM-1.3.1/doc/Makefile.am 2018-05-18 14:53:50.300997606 +0200
+@@ -2,7 +2,7 @@
+ # Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
+ #
+
+-SUBDIRS = man specs sag adg mwg
++SUBDIRS = man sag adg mwg
+
+ CLEANFILES = *~
+
+diff -up Linux-PAM-1.3.1/Makefile.am.noflex Linux-PAM-1.3.1/Makefile.am
+--- Linux-PAM-1.3.1/Makefile.am.noflex 2018-05-18 14:53:50.301997629 +0200
++++ Linux-PAM-1.3.1/Makefile.am 2018-05-18 14:55:31.576353800 +0200
+@@ -4,7 +4,7 @@
+
+ AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 dist-xz check-news
+
+-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests
++SUBDIRS = libpam tests libpamc libpam_misc modules po doc examples xtests
+
+ CLEANFILES = *~
+
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch b/source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch
new file mode 100644
index 000000000..4d3f37414
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-redhat-modules.patch
@@ -0,0 +1,78 @@
+diff -up Linux-PAM-1.3.1/configure.ac.redhat-modules Linux-PAM-1.3.1/configure.ac
+--- Linux-PAM-1.3.1/configure.ac.redhat-modules 2018-05-18 12:57:57.000000000 +0200
++++ Linux-PAM-1.3.1/configure.ac 2018-11-26 12:58:14.623545121 +0100
+@@ -611,10 +611,12 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
+ libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
+ po/Makefile.in \
+ modules/Makefile \
++ modules/pam_chroot/Makefile modules/pam_console/Makefile \
++ modules/pam_postgresok/Makefile \
+ modules/pam_access/Makefile modules/pam_cracklib/Makefile \
+ modules/pam_debug/Makefile modules/pam_deny/Makefile \
+ modules/pam_echo/Makefile modules/pam_env/Makefile \
+- modules/pam_faildelay/Makefile \
++ modules/pam_faildelay/Makefile modules/pam_faillock/Makefile \
+ modules/pam_filter/Makefile modules/pam_filter/upperLOWER/Makefile \
+ modules/pam_ftp/Makefile modules/pam_group/Makefile \
+ modules/pam_issue/Makefile modules/pam_keyinit/Makefile \
+diff -up Linux-PAM-1.3.1/doc/sag/pam_faillock.xml.redhat-modules Linux-PAM-1.3.1/doc/sag/pam_faillock.xml
+--- Linux-PAM-1.3.1/doc/sag/pam_faillock.xml.redhat-modules 2018-11-26 12:58:14.623545121 +0100
++++ Linux-PAM-1.3.1/doc/sag/pam_faillock.xml 2018-11-26 12:58:14.623545121 +0100
+@@ -0,0 +1,38 @@
++<?xml version='1.0' encoding='UTF-8'?>
++<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
++ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
++<section id='sag-pam_faillock'>
++ <title>pam_faillock - temporarily locking access based on failed authentication attempts during an interval</title>
++ <cmdsynopsis>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//cmdsynopsis[@id = "pam_faillock-cmdsynopsisauth"]/*)'/>
++ </cmdsynopsis>
++ <cmdsynopsis>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//cmdsynopsis[@id = "pam_faillock-cmdsynopsisacct"]/*)'/>
++ </cmdsynopsis>
++ <section id='sag-pam_faillock-description'>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-description"]/*)'/>
++ </section>
++ <section id='sag-pam_faillock-options'>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-options"]/*)'/>
++ </section>
++ <section id='sag-pam_faillock-types'>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-types"]/*)'/>
++ </section>
++ <section id='sag-pam_faillock-return_values'>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-return_values"]/*)'/>
++ </section>
++ <section id='sag-pam_faillock-examples'>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-examples"]/*)'/>
++ </section>
++ <section id='sag-pam_faillock-author'>
++ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
++ href="../../modules/pam_faillock/pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-author"]/*)'/>
++ </section>
++</section>
+diff -up Linux-PAM-1.3.1/modules/Makefile.am.redhat-modules Linux-PAM-1.3.1/modules/Makefile.am
+--- Linux-PAM-1.3.1/modules/Makefile.am.redhat-modules 2017-02-10 11:10:15.000000000 +0100
++++ Linux-PAM-1.3.1/modules/Makefile.am 2018-11-26 12:58:14.623545121 +0100
+@@ -3,13 +3,14 @@
+ #
+
+ SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \
++ pam_chroot pam_console pam_postgresok pam_faillock \
+ pam_env pam_exec pam_faildelay pam_filter pam_ftp \
+ pam_group pam_issue pam_keyinit pam_lastlog pam_limits \
+ pam_listfile pam_localuser pam_loginuid pam_mail \
+ pam_mkhomedir pam_motd pam_namespace pam_nologin \
+ pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \
+ pam_selinux pam_sepermit pam_shells pam_stress \
+- pam_succeed_if pam_tally pam_tally2 pam_time pam_timestamp \
++ pam_succeed_if pam_time pam_timestamp \
+ pam_tty_audit pam_umask \
+ pam_unix pam_userdb pam_warn pam_wheel pam_xauth
+
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch
new file mode 100644
index 000000000..bff9d47ea
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch
@@ -0,0 +1,34 @@
+From f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
+Date: Thu, 15 Nov 2018 15:01:57 +0100
+Subject: [PATCH] pam_unix: Use bcrypt b-variant for computing new hashes.
+
+Bcrypt hashes used the "$2a$" prefix since 1997.
+However, in 2011 an implementation bug was discovered in bcrypt
+affecting the handling of characters in passphrases with the 8th
+bit set.
+
+Besides fixing the bug, OpenBSD 5.5 introduced the "$2b$" prefix
+for a behavior that exactly matches crypt_blowfish's "$2y$", and
+the crypt_blowfish implementation supports it as well since v1.1.
+
+That said new computed bcrypt hashes should use the "$2b$" prefix.
+
+* modules/pam_unix/passverify.c: Use bcrypt b-variant.
+---
+ modules/pam_unix/passverify.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
+index 9c1771e2..1f433b3a 100644
+--- a/modules/pam_unix/passverify.c
++++ b/modules/pam_unix/passverify.c
+@@ -385,7 +385,7 @@ PAMH_ARG_DECL(char * create_password_hash,
+ /* algoid = "$1" */
+ return crypt_md5_wrapper(password);
+ } else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+- algoid = "$2a$";
++ algoid = "$2b$";
+ } else if (on(UNIX_SHA256_PASS, ctrl)) {
+ algoid = "$5$";
+ } else if (on(UNIX_SHA512_PASS, ctrl)) {
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch
new file mode 100644
index 000000000..5cbc35b03
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch
@@ -0,0 +1,73 @@
+From 86eed7ca01864b9fd17099e57f10f2b9b6b568a1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
+Date: Mon, 26 Nov 2018 22:33:17 +0100
+Subject: [PATCH] pam_unix: Report unusable hashes found by checksalt to
+ syslog.
+
+libxcrypt can be build-time configured to support (or not support)
+various hashing methods. Future versions will also have support for
+runtime configuration by the system's vendor and/or administrator.
+
+For that reason adminstrator should be notified by pam if users cannot
+log into their account anymore because of such a change in the system's
+configuration of libxcrypt.
+
+Also check for malformed hashes, like descrypt hashes starting with
+"$2...", which might have been generated by unsafe base64 encoding
+functions as used in glibc <= 2.16.
+Such hashes are likely to be rejected by many recent implementations
+of libcrypt.
+
+* modules/pam_unix/passverify.c (verify_pwd_hash): Report unusable
+hashes found by checksalt to syslog.
+---
+ modules/pam_unix/passverify.c | 36 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
+index eb2444bb..2c808eb5 100644
+--- a/modules/pam_unix/passverify.c
++++ b/modules/pam_unix/passverify.c
+@@ -103,6 +103,42 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
+ * Ok, we don't know the crypt algorithm, but maybe
+ * libcrypt knows about it? We should try it.
+ */
++#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE
++ /* Get the status of the hash from checksalt */
++ int retval_checksalt = crypt_checksalt(hash);
++
++ /*
++ * Check for hashing methods that are disabled by
++ * libcrypt configuration and/or system preset.
++ */
++ if (retval_checksalt == CRYPT_SALT_METHOD_DISABLED) {
++ /*
++ * pam_syslog() needs a pam handle,
++ * but that's not available here.
++ */
++ helper_log_err(LOG_ERR,
++ "pam_unix(verify_pwd_hash): The method "
++ "for computing the hash \"%.6s\" has been "
++ "disabled in libcrypt by the preset from "
++ "the system's vendor and/or administrator.",
++ hash);
++ }
++ /*
++ * Check for malformed hashes, like descrypt hashes
++ * starting with "$2...", which might have been
++ * generated by unsafe base64 encoding functions
++ * as used in glibc <= 2.16.
++ * Such hashes are likely to be rejected by many
++ * recent implementations of libcrypt.
++ */
++ if (retval_checksalt == CRYPT_SALT_INVALID) {
++ helper_log_err(LOG_ERR,
++ "pam_unix(verify_pwd_hash): The hash \"%.6s\""
++ "does not use a method known by the version "
++ "of libcrypt this system is supplied with.",
++ hash);
++ }
++#endif
+ #ifdef HAVE_CRYPT_R
+ struct crypt_data *cdata;
+ cdata = malloc(sizeof(*cdata));
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch
new file mode 100644
index 000000000..0a74e940e
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch
@@ -0,0 +1,40 @@
+From 62425bf2a0c72d0e23139d0b285547a7add26251 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
+Date: Thu, 15 Nov 2018 19:49:44 +0100
+Subject: [PATCH] pam_unix: Add support for crypt_checksalt, if libcrypt
+ supports it.
+
+libxcrypt v4.3 has added the crypt_checksalt function to whether
+the prefix at the begining of a given hash string refers to a
+supported hashing method.
+
+Future revisions of this function will add support to check whether
+the hashing method, the prefix refers to, was disabled or considered
+deprecated by the system's factory presets or system administrator.
+Furthermore it will be able to detect whether the parameters, which
+are used by the corresponding hashing method, being encoded in the
+hash string are not considered to be strong enough anymore.
+
+*modules/pam_unix/passverify.c: Add support for crypt_checksalt.
+---
+ modules/pam_unix/passverify.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
+index 1f433b3a..6132130a 100644
+--- a/modules/pam_unix/passverify.c
++++ b/modules/pam_unix/passverify.c
+@@ -244,7 +244,13 @@ PAMH_ARG_DECL(int check_shadow_expiry,
+ D(("account expired"));
+ return PAM_ACCT_EXPIRED;
+ }
++#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE
++ if (spent->sp_lstchg == 0 ||
++ crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_LEGACY ||
++ crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_TOO_CHEAP) {
++#else
+ if (spent->sp_lstchg == 0) {
++#endif
+ D(("need a new password"));
+ *daysleft = 0;
+ return PAM_NEW_AUTHTOK_REQD;
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch
new file mode 100644
index 000000000..41733ae04
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch
@@ -0,0 +1,104 @@
+From d8d11db2cef65da5d2afa7acf21aa9c8cd88abed Mon Sep 17 00:00:00 2001
+From: Tomas Mraz <tmraz@fedoraproject.org>
+Date: Tue, 27 Nov 2018 16:11:03 +0100
+Subject: [PATCH] pam_unix: Use pam_syslog instead of helper_log_err.
+
+* modules/pam_unix/passverify.c (verify_pwd_hash): Add pamh argument via
+ PAMH_ARG_DECL. Call pam_syslog() instead of helper_log_err().
+* modules/pam_unix/passverify.h: Adjust the declaration of verify_pwd_hash().
+* modules/pam_unix/support.c (_unix_verify_password): Add the pamh argument
+ to verify_pwd_hash() call.
+---
+ modules/pam_unix/passverify.c | 24 +++++++++++++-----------
+ modules/pam_unix/passverify.h | 6 +++---
+ modules/pam_unix/support.c | 2 +-
+ 3 files changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
+index 2c808eb5..80e32767 100644
+--- a/modules/pam_unix/passverify.c
++++ b/modules/pam_unix/passverify.c
+@@ -65,8 +65,8 @@ strip_hpux_aging(char *hash)
+ }
+ }
+
+-int
+-verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
++PAMH_ARG_DECL(int verify_pwd_hash,
++ const char *p, char *hash, unsigned int nullok)
+ {
+ size_t hash_len;
+ char *pp = NULL;
+@@ -116,11 +116,10 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
+ * pam_syslog() needs a pam handle,
+ * but that's not available here.
+ */
+- helper_log_err(LOG_ERR,
+- "pam_unix(verify_pwd_hash): The method "
+- "for computing the hash \"%.6s\" has been "
+- "disabled in libcrypt by the preset from "
+- "the system's vendor and/or administrator.",
++ pam_syslog(pamh, LOG_ERR,
++ "The support for password hash \"%.6s\" "
++ "has been disabled in libcrypt "
++ "configuration.",
+ hash);
+ }
+ /*
+@@ -132,12 +131,15 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
+ * recent implementations of libcrypt.
+ */
+ if (retval_checksalt == CRYPT_SALT_INVALID) {
+- helper_log_err(LOG_ERR,
+- "pam_unix(verify_pwd_hash): The hash \"%.6s\""
+- "does not use a method known by the version "
+- "of libcrypt this system is supplied with.",
++ pam_syslog(pamh, LOG_ERR,
++ "The password hash \"%.6s\" is unknown to "
++ "libcrypt.",
+ hash);
+ }
++#else
++#ifndef HELPER_COMPILE
++ (void)pamh;
++#endif
+ #endif
+ #ifdef HAVE_CRYPT_R
+ struct crypt_data *cdata;
+diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
+index 086c28ac..e9a88fbf 100644
+--- a/modules/pam_unix/passverify.h
++++ b/modules/pam_unix/passverify.h
+@@ -12,9 +12,6 @@
+
+ #define OLD_PASSWORDS_FILE "/etc/security/opasswd"
+
+-int
+-verify_pwd_hash(const char *p, char *hash, unsigned int nullok);
+-
+ int
+ is_pwd_shadowed(const struct passwd *pwd);
+
+@@ -65,6 +62,9 @@ read_passwords(int fd, int npass, char **passwords);
+ #define PAMH_ARG(...) pamh, __VA_ARGS__
+ #endif
+
++PAMH_ARG_DECL(int verify_pwd_hash,
++ const char *p, char *hash, unsigned int nullok);
++
+ PAMH_ARG_DECL(char * create_password_hash,
+ const char *password, unsigned long long ctrl, int rounds);
+
+diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
+index 6894288d..ea5594d2 100644
+--- a/modules/pam_unix/support.c
++++ b/modules/pam_unix/support.c
+@@ -770,7 +770,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
+ }
+ }
+ } else {
+- retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
++ retval = verify_pwd_hash(pamh, p, salt, off(UNIX__NONULL, ctrl));
+ }
+
+ if (retval == PAM_SUCCESS) {
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch
new file mode 100644
index 000000000..8ae4abfd8
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch
@@ -0,0 +1,95 @@
+From 05aa693b7db6b818d31e41f0cab1d5fb4f49600e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
+Date: Thu, 15 Nov 2018 15:58:56 +0100
+Subject: [PATCH] pam_unix: Prefer a gensalt function, that supports auto
+ entropy.
+
+* modules/pam_unix/pam_unix_passwd.c: Initialize rounds parameter to 0.
+* modules/pam_unix/passverify.c: Prefer gensalt with auto entropy.
+* modules/pam_unix/support.c: Fix sanitizing of rounds parameter.
+---
+ modules/pam_unix/pam_unix_passwd.c | 2 +-
+ modules/pam_unix/passverify.c | 13 +++++++++++++
+ modules/pam_unix/support.c | 7 +++++--
+ 3 files changed, 19 insertions(+), 3 deletions(-)
+
+Index: Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c
+===================================================================
+--- Linux-PAM-1.3.1.orig/modules/pam_unix/pam_unix_passwd.c
++++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c
+@@ -607,7 +607,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int
+ unsigned int ctrl, lctrl;
+ int retval;
+ int remember = -1;
+- int rounds = -1;
++ int rounds = 0;
+ int pass_min_len = 0;
+
+ /* <DO NOT free() THESE> */
+Index: Linux-PAM-1.3.1/modules/pam_unix/passverify.c
+===================================================================
+--- Linux-PAM-1.3.1.orig/modules/pam_unix/passverify.c
++++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c
+@@ -375,7 +375,12 @@ PAMH_ARG_DECL(char * create_password_has
+ const char *password, unsigned int ctrl, int rounds)
+ {
+ const char *algoid;
++#if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64
++ /* Strings returned by crypt_gensalt_rn will be no longer than this. */
++ char salt[CRYPT_GENSALT_OUTPUT_SIZE];
++#else
+ char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
++#endif
+ char *sp;
+ #ifdef HAVE_CRYPT_R
+ struct crypt_data *cdata = NULL;
+@@ -406,6 +411,13 @@ PAMH_ARG_DECL(char * create_password_has
+ return crypted;
+ }
+
++#if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY
++ /*
++ * Any version of libcrypt supporting auto entropy is
++ * guaranteed to have crypt_gensalt_rn().
++ */
++ sp = crypt_gensalt_rn(algoid, rounds, NULL, 0, salt, sizeof(salt));
++#else
+ #ifdef HAVE_CRYPT_GENSALT_R
+ if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ char entropy[17];
+@@ -423,6 +435,7 @@ PAMH_ARG_DECL(char * create_password_has
+ #ifdef HAVE_CRYPT_GENSALT_R
+ }
+ #endif
++#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */
+ #ifdef HAVE_CRYPT_R
+ sp = NULL;
+ cdata = malloc(sizeof(*cdata));
+Index: Linux-PAM-1.3.1/modules/pam_unix/support.c
+===================================================================
+--- Linux-PAM-1.3.1.orig/modules/pam_unix/support.c
++++ Linux-PAM-1.3.1/modules/pam_unix/support.c
+@@ -175,6 +175,7 @@ int _set_ctrl(pam_handle_t *pamh, int fl
+
+ if (val) {
+ *rounds = strtol(val, NULL, 10);
++ set(UNIX_ALGO_ROUNDS, ctrl);
+ free (val);
+ }
+ }
+@@ -254,11 +255,13 @@ int _set_ctrl(pam_handle_t *pamh, int fl
+ if (*rounds < 4 || *rounds > 31)
+ *rounds = 5;
+ } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
+- if ((*rounds < 1000) || (*rounds == INT_MAX))
++ if ((*rounds < 1000) || (*rounds == INT_MAX)) {
+ /* don't care about bogus values */
++ *rounds = 0;
+ unset(UNIX_ALGO_ROUNDS, ctrl);
+- if (*rounds >= 10000000)
++ } else if (*rounds >= 10000000) {
+ *rounds = 9999999;
++ }
+ }
+ }
+
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch
new file mode 100644
index 000000000..8755cf602
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-no-fallback.patch
@@ -0,0 +1,105 @@
+Index: Linux-PAM-1.3.1/modules/pam_unix/pam_unix.8.xml
+===================================================================
+--- Linux-PAM-1.3.1.orig/modules/pam_unix/pam_unix.8.xml
++++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix.8.xml
+@@ -293,11 +293,10 @@
+ <listitem>
+ <para>
+ When a user changes their password next,
+- encrypt it with the SHA256 algorithm. If the
+- SHA256 algorithm is not known to the <citerefentry>
++ encrypt it with the SHA256 algorithm. The
++ SHA256 algorithm must be supported by the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+- </citerefentry> function,
+- fall back to MD5.
++ </citerefentry> function.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -308,11 +307,10 @@
+ <listitem>
+ <para>
+ When a user changes their password next,
+- encrypt it with the SHA512 algorithm. If the
+- SHA512 algorithm is not known to the <citerefentry>
++ encrypt it with the SHA512 algorithm. The
++ SHA512 algorithm must be supported by the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+- </citerefentry> function,
+- fall back to MD5.
++ </citerefentry> function.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -323,11 +321,10 @@
+ <listitem>
+ <para>
+ When a user changes their password next,
+- encrypt it with the blowfish algorithm. If the
+- blowfish algorithm is not known to the <citerefentry>
++ encrypt it with the blowfish algorithm. The
++ blowfish algorithm must be supported by the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+- </citerefentry> function,
+- fall back to MD5.
++ </citerefentry> function.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -338,11 +335,10 @@
+ <listitem>
+ <para>
+ When a user changes their password next,
+- encrypt it with the gost-yescrypt algorithm. If the
+- gost-yescrypt algorithm is not known to the <citerefentry>
++ encrypt it with the gost-yescrypt algorithm. The
++ gost-yescrypt algorithm must be supported by the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+- </citerefentry> function,
+- fall back to MD5.
++ </citerefentry> function.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -353,11 +349,10 @@
+ <listitem>
+ <para>
+ When a user changes their password next,
+- encrypt it with the yescrypt algorithm. If the
+- yescrypt algorithm is not known to the <citerefentry>
++ encrypt it with the yescrypt algorithm. The
++ yescrypt algorithm must be supported by the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+- </citerefentry> function,
+- fall back to MD5.
++ </citerefentry> function.
+ </para>
+ </listitem>
+ </varlistentry>
+Index: Linux-PAM-1.3.1/modules/pam_unix/passverify.c
+===================================================================
+--- Linux-PAM-1.3.1.orig/modules/pam_unix/passverify.c
++++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c
+@@ -466,10 +466,9 @@ PAMH_ARG_DECL(char * create_password_has
+ sp = crypt(password, salt);
+ #endif
+ if (!sp || strncmp(algoid, sp, strlen(algoid)) != 0) {
+- /* libxcrypt/libc doesn't know the algorithm, use MD5 */
++ /* libxcrypt/libc doesn't know the algorithm, error out */
+ pam_syslog(pamh, LOG_ERR,
+- "Algo %s not supported by the crypto backend, "
+- "falling back to MD5\n",
++ "Algo %s not supported by the crypto backend.\n",
+ on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" :
+ on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" :
+ on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
+@@ -481,7 +480,7 @@ PAMH_ARG_DECL(char * create_password_has
+ #ifdef HAVE_CRYPT_R
+ free(cdata);
+ #endif
+- return crypt_md5_wrapper(password);
++ return NULL;
+ }
+ sp = x_strdup(sp);
+ #ifdef HAVE_CRYPT_R
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch
new file mode 100644
index 000000000..14f285deb
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch
@@ -0,0 +1,34 @@
+From a2b72aeb86f297d349bc9e6a8f059fedf97a499a Mon Sep 17 00:00:00 2001
+From: "Dmitry V. Levin" <ldv@altlinux.org>
+Date: Thu, 31 May 2018 00:20:18 +0000
+Subject: [PATCH] pam_unix: remove obsolete _unix_read_password prototype
+
+The function was removed by commit Linux-PAM-1.3.0~5
+so the function prototype should go as well.
+
+* modules/pam_unix/support.h (_unix_read_password): Remove.
+
+Complements: 7e09188c5dc4 ("pam_unix: Use pam_get_authtok() instead of
+direct pam_prompt() calls.")
+---
+ modules/pam_unix/support.h | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
+index b4c279c3..543e9b9f 100644
+--- a/modules/pam_unix/support.h
++++ b/modules/pam_unix/support.h
+@@ -164,13 +164,6 @@ extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl,
+ const char *name);
+ extern int _unix_verify_password(pam_handle_t * pamh, const char *name
+ ,const char *p, unsigned int ctrl);
+-extern int _unix_read_password(pam_handle_t * pamh
+- ,unsigned int ctrl
+- ,const char *comment
+- ,const char *prompt1
+- ,const char *prompt2
+- ,const char *data_name
+- ,const void **pass);
+
+ extern int _unix_run_verify_binary(pam_handle_t *pamh,
+ unsigned int ctrl, const char *user, int *daysleft);
diff --git a/source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch b/source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch
new file mode 100644
index 000000000..f04a59ce7
--- /dev/null
+++ b/source/a/pam/fedora-patches/pam-1.3.1-unix-yescrypt.patch
@@ -0,0 +1,479 @@
+From 16bd523f85ede9fa9115f80e826f2d803d7e61d4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
+Date: Thu, 15 Nov 2018 16:38:05 +0100
+Subject: [PATCH] pam_unix: Add support for (gost-)yescrypt hashing methods.
+
+libxcrypt (v4.2 and later) has added support for the yescrypt
+hashing method; gost-yescrypt has been added in v4.3.
+
+* modules/pam_unix/pam_unix.8.xml: Documentation for (gost-)yescrypt.
+* modules/pam_unix/pam_unix_acct.c: Use 64 bit type for control flags.
+* modules/pam_unix/pam_unix_auth.c: Likewise.
+* modules/pam_unix/pam_unix_passwd.c: Likewise.
+* modules/pam_unix/pam_unix_sess.c: Likewise.
+* modules/pam_unix/passverify.c: Add support for (gost-)yescrypt.
+* modules/pam_unix/passverify.h: Use 64 bit type for control flags.
+* modules/pam_unix/support.c: Set sane rounds for (gost-)yescrypt.
+* modules/pam_unix/support.h: Add support for (gost-)yescrypt.
+---
+ modules/pam_unix/pam_unix.8.xml | 35 +++++++++-
+ modules/pam_unix/pam_unix_acct.c | 4 +-
+ modules/pam_unix/pam_unix_auth.c | 4 +-
+ modules/pam_unix/pam_unix_passwd.c | 12 ++--
+ modules/pam_unix/pam_unix_sess.c | 4 +-
+ modules/pam_unix/passverify.c | 8 ++-
+ modules/pam_unix/passverify.h | 2 +-
+ modules/pam_unix/support.c | 33 ++++++----
+ modules/pam_unix/support.h | 101 +++++++++++++++--------------
+ 9 files changed, 128 insertions(+), 75 deletions(-)
+
+diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
+index 1b318f11..cae2aeaa 100644
+--- a/modules/pam_unix/pam_unix.8.xml
++++ b/modules/pam_unix/pam_unix.8.xml
+@@ -331,14 +331,45 @@
+ </para>
+ </listitem>
+ </varlistentry>
++ <varlistentry>
++ <term>
++ <option>gost_yescrypt</option>
++ </term>
++ <listitem>
++ <para>
++ When a user changes their password next,
++ encrypt it with the gost-yescrypt algorithm. If the
++ gost-yescrypt algorithm is not known to the <citerefentry>
++ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
++ </citerefentry> function,
++ fall back to MD5.
++ </para>
++ </listitem>
++ </varlistentry>
++ <varlistentry>
++ <term>
++ <option>yescrypt</option>
++ </term>
++ <listitem>
++ <para>
++ When a user changes their password next,
++ encrypt it with the yescrypt algorithm. If the
++ yescrypt algorithm is not known to the <citerefentry>
++ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
++ </citerefentry> function,
++ fall back to MD5.
++ </para>
++ </listitem>
++ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>rounds=<replaceable>n</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+- Set the optional number of rounds of the SHA256, SHA512
+- and blowfish password hashing algorithms to
++ Set the optional number of rounds of the SHA256, SHA512,
++ blowfish, gost-yescrypt, and yescrypt password hashing
++ algorithms to
+ <replaceable>n</replaceable>.
+ </para>
+ </listitem>
+diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
+index fbc84e2f..d8d084ac 100644
+--- a/modules/pam_unix/pam_unix_acct.c
++++ b/modules/pam_unix/pam_unix_acct.c
+@@ -62,7 +62,7 @@
+ #include "support.h"
+ #include "passverify.h"
+
+-int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
++int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl,
+ const char *user, int *daysleft)
+ {
+ int retval=0, child, fds[2];
+@@ -185,7 +185,7 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
+ int
+ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+- unsigned int ctrl;
++ unsigned long long ctrl;
+ const void *void_uname;
+ const char *uname;
+ int retval, daysleft;
+diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c
+index 9d9f709d..905fc66c 100644
+--- a/modules/pam_unix/pam_unix_auth.c
++++ b/modules/pam_unix/pam_unix_auth.c
+@@ -96,7 +96,7 @@ setcred_free (pam_handle_t *pamh UNUSED, void *ptr, int err UNUSED)
+ int
+ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+- unsigned int ctrl;
++ unsigned long long ctrl;
+ int retval, *ret_data = NULL;
+ const char *name;
+ const char *p;
+@@ -194,7 +194,7 @@ pam_sm_setcred (pam_handle_t *pamh, int flags,
+ {
+ int retval;
+ const void *pretval = NULL;
+- unsigned int ctrl;
++ unsigned long long ctrl;
+
+ D(("called."));
+
+diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
+index f2c42513..df4c1233 100644
+--- a/modules/pam_unix/pam_unix_passwd.c
++++ b/modules/pam_unix/pam_unix_passwd.c
+@@ -138,7 +138,7 @@ __taddr2port (const struct netconfig *nconf, const struct netbuf *nbuf)
+ }
+ #endif
+
+-static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl)
++static char *getNISserver(pam_handle_t *pamh, unsigned long long ctrl)
+ {
+ char *master;
+ char *domainname;
+@@ -233,7 +233,7 @@ static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl)
+
+ #ifdef WITH_SELINUX
+
+-static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user,
++static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, const char *user,
+ const char *fromwhat, const char *towhat, int remember)
+ {
+ int retval, child, fds[2];
+@@ -388,7 +388,7 @@ static int check_old_password(const char *forwho, const char *newpass)
+
+ static int _do_setpass(pam_handle_t* pamh, const char *forwho,
+ const char *fromwhat,
+- char *towhat, unsigned int ctrl, int remember)
++ char *towhat, unsigned long long ctrl, int remember)
+ {
+ struct passwd *pwd = NULL;
+ int retval = 0;
+@@ -512,7 +512,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho,
+ return retval;
+ }
+
+-static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned int ctrl)
++static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned long long ctrl)
+ {
+ struct passwd *pwent = NULL; /* Password and shadow password */
+ struct spwd *spent = NULL; /* file entries for the user */
+@@ -542,7 +542,7 @@ static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned in
+ }
+
+ static int _pam_unix_approve_pass(pam_handle_t * pamh
+- ,unsigned int ctrl
++ ,unsigned long long ctrl
+ ,const char *pass_old
+ ,const char *pass_new,
+ int pass_min_len)
+@@ -600,7 +600,7 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
+ int
+ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+- unsigned int ctrl, lctrl;
++ unsigned long long ctrl, lctrl;
+ int retval;
+ int remember = -1;
+ int rounds = 0;
+diff --git a/modules/pam_unix/pam_unix_sess.c b/modules/pam_unix/pam_unix_sess.c
+index 03e7dcd9..4b8af530 100644
+--- a/modules/pam_unix/pam_unix_sess.c
++++ b/modules/pam_unix/pam_unix_sess.c
+@@ -67,7 +67,7 @@ int
+ pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+ char *user_name, *service;
+- unsigned int ctrl;
++ unsigned long long ctrl;
+ int retval;
+ const char *login_name;
+
+@@ -103,7 +103,7 @@ int
+ pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+ {
+ char *user_name, *service;
+- unsigned int ctrl;
++ unsigned long long ctrl;
+ int retval;
+
+ D(("called."));
+diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
+index 95dfe528..39e2bfac 100644
+--- a/modules/pam_unix/passverify.c
++++ b/modules/pam_unix/passverify.c
+@@ -387,7 +387,7 @@ crypt_md5_wrapper(const char *pass_new)
+ }
+
+ PAMH_ARG_DECL(char * create_password_hash,
+- const char *password, unsigned int ctrl, int rounds)
++ const char *password, unsigned long long ctrl, int rounds)
+ {
+ const char *algoid;
+ #if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64
+@@ -404,6 +404,10 @@ PAMH_ARG_DECL(char * create_password_hash,
+ if (on(UNIX_MD5_PASS, ctrl)) {
+ /* algoid = "$1" */
+ return crypt_md5_wrapper(password);
++ } else if (on(UNIX_YESCRYPT_PASS, ctrl)) {
++ algoid = "$y$";
++ } else if (on(UNIX_GOST_YESCRYPT_PASS, ctrl)) {
++ algoid = "$gy$";
+ } else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ algoid = "$2b$";
+ } else if (on(UNIX_SHA256_PASS, ctrl)) {
+@@ -466,6 +470,8 @@ PAMH_ARG_DECL(char * create_password_hash,
+ pam_syslog(pamh, LOG_ERR,
+ "Algo %s not supported by the crypto backend, "
+ "falling back to MD5\n",
++ on(UNIX_YESCRYPT_PASS, ctrl) ? "yescrypt" :
++ on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" :
+ on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
+ on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
+ on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
+diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
+index caf7ae8a..086c28ac 100644
+--- a/modules/pam_unix/passverify.h
++++ b/modules/pam_unix/passverify.h
+@@ -66,7 +66,7 @@ read_passwords(int fd, int npass, char **passwords);
+ #endif
+
+ PAMH_ARG_DECL(char * create_password_hash,
+- const char *password, unsigned int ctrl, int rounds);
++ const char *password, unsigned long long ctrl, int rounds);
+
+ PAMH_ARG_DECL(int get_account_info,
+ const char *name, struct passwd **pwd, struct spwd **spwdent);
+diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
+index 8cbc4217..6894288d 100644
+--- a/modules/pam_unix/support.c
++++ b/modules/pam_unix/support.c
+@@ -107,7 +107,7 @@ search_key (const char *key, const char *filename)
+
+ /* this is a front-end for module-application conversations */
+
+-int _make_remark(pam_handle_t * pamh, unsigned int ctrl,
++int _make_remark(pam_handle_t * pamh, unsigned long long ctrl,
+ int type, const char *text)
+ {
+ int retval = PAM_SUCCESS;
+@@ -122,10 +122,11 @@ int _make_remark(pam_handle_t * pamh, unsigned int ctrl,
+ * set the control flags for the UNIX module.
+ */
+
+-int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
+- int *pass_min_len, int argc, const char **argv)
++unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember,
++ int *rounds, int *pass_min_len, int argc,
++ const char **argv)
+ {
+- unsigned int ctrl;
++ unsigned long long ctrl;
+ char *val;
+ int j;
+
+@@ -243,15 +244,23 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
+ set(UNIX__NONULL, ctrl);
+ }
+
+- /* Set default rounds for blowfish */
+- if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) {
+- *rounds = 5;
+- set(UNIX_ALGO_ROUNDS, ctrl);
++ /* Set default rounds for blowfish, gost-yescrypt and yescrypt */
++ if (off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) {
++ if (on(UNIX_BLOWFISH_PASS, ctrl) ||
++ on(UNIX_GOST_YESCRYPT_PASS, ctrl) ||
++ on(UNIX_YESCRYPT_PASS, ctrl)) {
++ *rounds = 5;
++ set(UNIX_ALGO_ROUNDS, ctrl);
++ }
+ }
+
+ /* Enforce sane "rounds" values */
+ if (on(UNIX_ALGO_ROUNDS, ctrl)) {
+- if (on(UNIX_BLOWFISH_PASS, ctrl)) {
++ if (on(UNIX_GOST_YESCRYPT_PASS, ctrl) ||
++ on(UNIX_YESCRYPT_PASS, ctrl)) {
++ if (*rounds < 3 || *rounds > 11)
++ *rounds = 5;
++ } else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ if (*rounds < 4 || *rounds > 31)
+ *rounds = 5;
+ } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
+@@ -532,7 +541,7 @@ int _unix_comesfromsource(pam_handle_t *pamh,
+ #include <sys/wait.h>
+
+ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
+- unsigned int ctrl, const char *user)
++ unsigned long long ctrl, const char *user)
+ {
+ int retval, child, fds[2];
+ struct sigaction newsa, oldsa;
+@@ -658,7 +667,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
+ */
+
+ int
+-_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
++_unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name)
+ {
+ struct passwd *pwd = NULL;
+ char *salt = NULL;
+@@ -706,7 +715,7 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
+ }
+
+ int _unix_verify_password(pam_handle_t * pamh, const char *name
+- ,const char *p, unsigned int ctrl)
++ ,const char *p, unsigned long long ctrl)
+ {
+ struct passwd *pwd = NULL;
+ char *salt = NULL;
+diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
+index 543e9b9f..e02c05e0 100644
+--- a/modules/pam_unix/support.h
++++ b/modules/pam_unix/support.h
+@@ -22,8 +22,8 @@
+
+ typedef struct {
+ const char *token;
+- unsigned int mask; /* shall assume 32 bits of flags */
+- unsigned int flag;
++ unsigned long long mask; /* shall assume 64 bits of flags */
++ unsigned long long flag;
+ unsigned int is_hash_algo;
+ } UNIX_Ctrls;
+
+@@ -48,7 +48,7 @@ typedef struct {
+
+ /* the generic mask */
+
+-#define _ALL_ON_ (~0U)
++#define _ALL_ON_ (~0ULL)
+
+ /* end of macro definitions definitions for the control flags */
+
+@@ -98,47 +98,51 @@ typedef struct {
+ #define UNIX_QUIET 28 /* Don't print informational messages */
+ #define UNIX_NO_PASS_EXPIRY 29 /* Don't check for password expiration if not used for authentication */
+ #define UNIX_DES 30 /* DES, default */
++#define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */
++#define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */
+ /* -------------- */
+-#define UNIX_CTRLS_ 31 /* number of ctrl arguments defined */
++#define UNIX_CTRLS_ 33 /* number of ctrl arguments defined */
+
+-#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl))
++#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl))
+
+ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
+ {
+-/* symbol token name ctrl mask ctrl *
+- * ----------------------- ------------------- --------------------- -------- */
+-
+-/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0},
+-/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0},
+-/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0},
+-/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0},
+-/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020, 0},
+-/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040, 0},
+-/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0},
+-/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200, 0},
+-/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400, 0},
+-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
+-/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
+-/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
+-/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
+-/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000, 1},
+-/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0, 0},
+-/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0},
+-/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0},
+-/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0},
+-/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000, 1},
+-/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0},
+-/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0},
+-/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0},
+-/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0},
+-/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000, 1},
+-/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000, 1},
+-/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0},
+-/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000, 1},
+-/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0},
+-/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0},
+-/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0},
+-/* UNIX_DES */ {"des", _ALL_ON_^(0260420000), 0, 1},
++/* symbol token name ctrl mask ctrl *
++ * --------------------------- -------------------- ------------------------- ---------------- */
++
++/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0},
++/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0},
++/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0},
++/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0},
++/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060ULL), 020, 0},
++/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060ULL), 040, 0},
++/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0},
++/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600ULL), 0200, 0},
++/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600ULL), 0400, 0},
++/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
++/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
++/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
++/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
++/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1},
++/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0},
++/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0},
++/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0},
++/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0},
++/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1},
++/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0},
++/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0},
++/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0},
++/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0},
++/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1},
++/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1},
++/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0},
++/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1},
++/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0},
++/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0},
++/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0},
++/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1},
++/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1},
++/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1},
+ };
+
+ #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
+@@ -151,20 +155,23 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
+ _pam_drop(xx); \
+ }
+
+-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 *rounds,
+- int *pass_min_len, int argc, const char **argv);
++extern int _make_remark(pam_handle_t * pamh, unsigned long long ctrl,
++ int type, const char *text);
++extern unsigned long long _set_ctrl(pam_handle_t * pamh, int flags,
++ int *remember, int *rounds,
++ int *pass_min_len,
++ int argc, const char **argv);
+ extern int _unix_getpwnam (pam_handle_t *pamh,
+ const char *name, int files, int nis,
+ struct passwd **ret);
+ extern int _unix_comesfromsource (pam_handle_t *pamh,
+ const char *name, int files, int nis);
+-extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl,
++extern int _unix_blankpasswd(pam_handle_t *pamh, unsigned long long ctrl,
+ const char *name);
+-extern int _unix_verify_password(pam_handle_t * pamh, const char *name
+- ,const char *p, unsigned int ctrl);
++extern int _unix_verify_password(pam_handle_t * pamh, const char *name,
++ const char *p, unsigned long long ctrl);
+
+ extern int _unix_run_verify_binary(pam_handle_t *pamh,
+- unsigned int ctrl, const char *user, int *daysleft);
++ unsigned long long ctrl,
++ const char *user, int *daysleft);
+ #endif /* _PAM_UNIX_SUPPORT_H */
diff --git a/source/a/pam/pam.SlackBuild b/source/a/pam/pam.SlackBuild
new file mode 100755
index 000000000..23aad8bc5
--- /dev/null
+++ b/source/a/pam/pam.SlackBuild
@@ -0,0 +1,230 @@
+#!/bin/sh
+
+# Copyright 2010 Vincent Batts, vbatts@hashbangbash.com
+# Copyright 2010, 2011 Patrick J. Volkerding, Sebeka, Minnesota, USA
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
+
+cd $(dirname $0) ; CWD=$(pwd)
+
+SRCNAM=Linux-PAM
+PKGNAM=pam
+PAMRHVER=${PAMRHVER:-$(echo pam-redhat-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
+VERSION=${VERSION:-$(echo $SRCNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
+BUILD=${BUILD:-1}
+
+# Automatically determine the architecture we're building on:
+if [ -z "$ARCH" ]; then
+ case "$( uname -m )" in
+ i?86) export ARCH=i586 ;;
+ arm*) export ARCH=arm ;;
+ # Unless $ARCH is already set, use uname -m for all other archs:
+ *) export ARCH=$( uname -m ) ;;
+ esac
+fi
+
+# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
+# the name of the created package would be, and then exit. This information
+# could be useful to other scripts.
+if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
+ echo "$PKGNAM-$VERSION-$ARCH-$BUILD.txz"
+ exit 0
+fi
+
+NUMJOBS=${NUMJOBS:-" -j$(expr $(nproc) + 1) "}
+
+if [ "$ARCH" = "i586" ]; then
+ SLKCFLAGS="-O2 -march=i586 -mtune=i686"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "s390" ]; then
+ SLKCFLAGS="-O2"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "x86_64" ]; then
+ SLKCFLAGS="-O2 -fPIC"
+ LIBDIRSUFFIX="64"
+else
+ SLKCFLAGS="-O2"
+ LIBDIRSUFFIX=""
+fi
+
+TMP=${TMP:-/tmp}
+PKG=$TMP/package-$PKGNAM
+
+rm -rf $PKG
+mkdir -p $TMP $PKG
+
+cd $TMP
+rm -rf $SRCNAM-$VERSION
+tar xvf $CWD/$SRCNAM-$VERSION.tar.?z || exit 1
+cd $SRCNAM-$VERSION || exit 1
+
+chown -R root:root .
+find . \
+ \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
+ -exec chmod 755 {} \+ -o \
+ \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
+ -exec chmod 644 {} \+
+
+# Better take the Red Hat added modules and patches, because that's very
+# likely to be the most standard as far as PAM goes:
+tar xvf $CWD/pam-redhat-$PAMRHVER.tar.?z || exit 1
+for file in CHANGELOG COPYING README ; do
+ mv pam-redhat-$PAMRHVER/${file}* ./${file}.pam-redhat
+done
+mv pam-redhat-$PAMRHVER/* modules
+zcat $CWD/fedora-patches/pam-1.3.1-redhat-modules.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-noflex.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.1.3-nouserenv.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.1.6-limits-user.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.1.8-full-relro.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.0-pwhistory-helper.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.1.8-audit-user-mgmt.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.0-unix-nomsg.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-coverity.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-remove-obsolete-_unix_read_password-prototype.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-bcrypt_b.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-gensalt-autoentropy.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-crypt_checksalt.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-yescrypt.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-no-fallback.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-motd-multiple-paths.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-checksalt_syslog.patch.gz | patch -p1 --verbose || exit 1
+zcat $CWD/fedora-patches/pam-1.3.1-unix-fix_checksalt_syslog.patch.gz | patch -p1 --verbose || exit 1
+
+# pam_tally2 removed in recent redhat-modules.patch, but we'll keep it
+# for now since system-auth in the shadow package uses it. Perhaps see if
+# pam_faillock can replace the usage there?
+zcat $CWD/patches/pam.pam_tally2.slackware.diff.gz | patch -p1 --verbose || exit 1
+
+# Upstream git patch to prevent pam_tally2 from doing an fsync()
+# with every failed login. This can cause system slowdowns, especially
+# on Internet-connected machines that may endure endless dictionary
+# attacks.
+zcat $CWD/patches/pam.pam_tally2.no.fsync.patch.gz | patch -p1 --verbose || exit 1
+
+# Improve the comments in /etc/environment:
+zcat $CWD/patches/pam.etc.environment.better.comments.diff.gz | patch -p1 --verbose || exit 1
+
+autoreconf -ivf || exit 1
+
+CFLAGS="$SLKCFLAGS" \
+CXXFLAGS="$SLKCFLAGS" \
+./configure \
+ --prefix=/ \
+ --libdir=/lib${LIBDIRSUFFIX} \
+ --sysconfdir=/etc \
+ --includedir=/usr/include/security \
+ --enable-securedir=/lib${LIBDIRSUFFIX}/security \
+ --datarootdir=/usr/share \
+ --localstatedir=/var \
+ --mandir=/usr/man \
+ --docdir=/usr/doc/$PKGNAM-$VERSION \
+ --disable-regenerate-docu \
+ --disable-audit \
+ --disable-prelude \
+ --disable-rpath \
+ --disable-selinux \
+ --disable-static \
+ --build=$ARCH-slackware-linux || exit 1
+
+# Make these man pages or the build falls over later
+xmlto man modules/pam_faillock/faillock.8.xml -o modules/pam_faillock/
+xmlto man modules/pam_faillock/pam_faillock.8.xml -o modules/pam_faillock/
+xmlto man modules/pam_pwhistory/pwhistory_helper.8.xml -o modules/pam_pwhistory/
+
+make -C po update-gmo
+make $NUMJOBS || make || exit 1
+make install DESTDIR=$PKG || exit 1
+
+# Don't ship .la files:
+rm -f $PKG/{,usr/}lib${LIBDIRSUFFIX}/*.la
+
+# The ones in /lib${LIBDIRSUFFIX}/security can also go:
+rm -f $PKG/lib${LIBDIRSUFFIX}/security/*.la
+
+# Add extra symlinks added by pam.spec:
+( cd $PKG/lib${LIBDIRSUFFIX}/security
+ for type in acct auth passwd session ; do
+ ln -sf pam_unix.so pam_unix_${type}.so
+ done
+)
+
+# This is a pam helper that can only be called from pam
+chown root:root $PKG/sbin/unix_chkpwd
+chmod 6755 $PKG/sbin/unix_chkpwd
+
+# This package can own the /etc/pam.d/ directory
+mkdir -p $PKG/etc/pam.d
+
+# Strip binaries:
+( cd $PKG
+ find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+ find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+)
+
+# Don't clobber config files:
+find $PKG/etc -type f -exec mv {} {}.new \;
+
+# Compress and if needed symlink the man pages:
+if [ -d $PKG/usr/man ]; then
+ ( cd $PKG/usr/man
+ for manpagedir in $(find . -type d -name "man*") ; do
+ ( cd $manpagedir
+ for eachpage in $( find . -type l -maxdepth 1) ; do
+ ln -s $( readlink $eachpage ).gz $eachpage.gz
+ rm $eachpage
+ done
+ gzip -9 *.?
+ )
+ done
+ )
+fi
+
+mkdir -p $PKG/usr/doc/$PKGNAM-$VERSION
+cp -a \
+ AUTHORS COPYING* Copyright NEWS README* \
+ $PKG/usr/doc/$PKGNAM-$VERSION
+
+# If there's a ChangeLog, installing at least part of the recent history
+# is useful, but don't let it get totally out of control:
+if [ -r ChangeLog ]; then
+ DOCSDIR=$(echo $PKG/usr/doc/${PKGNAM}-$VERSION)
+ cat ChangeLog | head -n 1000 > $DOCSDIR/ChangeLog
+ touch -r ChangeLog $DOCSDIR/ChangeLog
+fi
+if [ -r CHANGELOG ]; then
+ DOCSDIR=$(echo $PKG/usr/doc/${PKGNAM}-$VERSION)
+ cat CHANGELOG | head -n 1000 > $DOCSDIR/CHANGELOG
+ touch -r CHANGELOG $DOCSDIR/CHANGELOG
+fi
+rm -f $PKG/usr/doc/$PKGNAM-$VERSION/index.html
+
+mkdir -p $PKG/install
+cat $CWD/slack-desc > $PKG/install/slack-desc
+zcat $CWD/doinst.sh.gz > $PKG/install/doinst.sh
+
+# Append config statements to the install/doinst.sh:
+( cd $PKG
+ for i in $(find etc -type f -name "*.new") ; do
+ echo "config $i" >> $PKG/install/doinst.sh ;
+ done
+)
+
+cd $PKG
+/sbin/makepkg -p -l y -c n $TMP/$PKGNAM-$VERSION-$ARCH-$BUILD.txz
diff --git a/source/a/pam/pam.url b/source/a/pam/pam.url
new file mode 100644
index 000000000..07dfcb99b
--- /dev/null
+++ b/source/a/pam/pam.url
@@ -0,0 +1,2 @@
+#http://www.linux-pam.org/library/Linux-PAM-1.3.1.tar.bz2
+https://github.com/linux-pam/linux-pam/releases
diff --git a/source/a/pam/patches/pam.etc.environment.better.comments.diff b/source/a/pam/patches/pam.etc.environment.better.comments.diff
new file mode 100644
index 000000000..6899e4c14
--- /dev/null
+++ b/source/a/pam/patches/pam.etc.environment.better.comments.diff
@@ -0,0 +1,15 @@
+--- ./modules/pam_env/environment.orig 2017-02-10 04:10:15.000000000 -0600
++++ ./modules/pam_env/environment 2020-01-02 14:40:48.793005303 -0600
+@@ -1,5 +1,10 @@
+-#
+-# This file is parsed by pam_env module
++# /etc/environment
++# This file is parsed by pam_env module.
++# This file may contain environment variable settings that should be used
++# system-wide. Please note that it is not a script file and should only
++# contain assignment expressions, one per line.
++# The environment variables in this file will be loaded before those in other
++# files such as: /etc/profile, /etc/profile.d/*, ~/.profile, etc.
+ #
+ # Syntax: simple "KEY=VAL" pairs on separate lines
+ #
diff --git a/source/a/pam/patches/pam.pam_tally2.no.fsync.patch b/source/a/pam/patches/pam.pam_tally2.no.fsync.patch
new file mode 100644
index 000000000..15b40115d
--- /dev/null
+++ b/source/a/pam/patches/pam.pam_tally2.no.fsync.patch
@@ -0,0 +1,35 @@
+From b136bff25e93be6f11de74aca03569022364b973 Mon Sep 17 00:00:00 2001
+From: "Maciej S. Szmigiero" <mail@maciej.szmigiero.name>
+Date: Mon, 25 Feb 2019 20:50:48 +0100
+Subject: [PATCH] pam_tally2: Remove unnecessary fsync()
+
+pam_tally2 does fsync() after writing to a tally file.
+This causes hard drive cache flushes on every failed SSH login on many
+(if not most) filesystems.
+And an internet-exposed machine can have a lot of these failed logins.
+
+This operation however doesn't seem to be necessary - the pam_tally2
+module does not do any operation which would need explicit post-crash
+ordering, it just does simple file reads and writes.
+And doing a fsync() after them doesn't close any race if the system happens
+to crash between a write being posted and its fsync() completion.
+
+Let's remove this operation to get rid of all these extra cache flushes.
+---
+ modules/pam_tally2/pam_tally2.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c
+index 984edf6a..ce7f5aee 100644
+--- a/modules/pam_tally2/pam_tally2.c
++++ b/modules/pam_tally2/pam_tally2.c
+@@ -484,10 +484,6 @@ set_tally(pam_handle_t *pamh, uid_t uid,
+ }
+ }
+
+- if (fsync(*tfile)) {
+- pam_syslog(pamh, LOG_ALERT, "update (fsync) failed for %s: %m", filename);
+- return PAM_AUTH_ERR;
+- }
+ return PAM_SUCCESS;
+ }
diff --git a/source/a/pam/patches/pam.pam_tally2.slackware.diff b/source/a/pam/patches/pam.pam_tally2.slackware.diff
new file mode 100644
index 000000000..8ab853210
--- /dev/null
+++ b/source/a/pam/patches/pam.pam_tally2.slackware.diff
@@ -0,0 +1,11 @@
+--- ./modules/Makefile.am.orig 2019-07-16 13:18:28.619322386 -0500
++++ ./modules/Makefile.am 2019-07-16 13:45:49.260371056 -0500
+@@ -10,7 +10,7 @@
+ pam_mkhomedir pam_motd pam_namespace pam_nologin \
+ pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \
+ pam_selinux pam_sepermit pam_shells pam_stress \
+- pam_succeed_if pam_time pam_timestamp \
++ pam_succeed_if pam_tally2 pam_time pam_timestamp \
+ pam_tty_audit pam_umask \
+ pam_unix pam_userdb pam_warn pam_wheel pam_xauth
+
diff --git a/source/a/pam/slack-desc b/source/a/pam/slack-desc
new file mode 100644
index 000000000..7c0bcbbd9
--- /dev/null
+++ b/source/a/pam/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|'
+# on the right side marks the last column you can put a character in. You must
+# make exactly 11 lines for the formatting to be correct. It's also
+# customary to leave one space after the ':'.
+
+ |-----handy-ruler------------------------------------------------------|
+pam: pam (Pluggable Authentication Modules)
+pam:
+pam: PAM = Pluggable Authentication Modules. Basically, it is a flexible
+pam: mechanism for authenticating users. PAM provides a way to develop
+pam: programs that are independent of authentication scheme. However,
+pam: these programs will need "authentication modules" (and libpam) at
+pam: run-time in order to work.
+pam:
+pam: Homepage: http://www.linux-pam.org/
+pam:
+pam: