diff --git a/SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch b/SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch
new file mode 100644
index 0000000..52f7292
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch
@@ -0,0 +1,283 @@
+From d57ab22133654033ee1da89f128a81572d320985 Mon Sep 17 00:00:00 2001
+From: Tomas Mraz <tmraz@fedoraproject.org>
+Date: Thu, 20 Dec 2018 13:59:25 +0100
+Subject: [PATCH] pam_motd: Cleanup the code and avoid unnecessary logging
+
+The pam_motd module will not log if the default motd.d directories
+are missing.
+
+Also cleanup some code cleanliness issues and fix compilation
+warnings.
+
+* modules/pam_motd/pam_motd.c: Constification of constant strings.
+  (try_to_display_directory): Removed unused function.
+  (pam_split_string): Replace uint with unsigned int. Fix warnings.
+  (compare_strings): Fix warnings by proper constification.
+  (try_to_display_directories_with_overrides): Cleanups. Switch
+  off the logging if the motd.d directories are missing and they
+  are default ones.
+  (pam_sm_open_session): Cleanup warnings. Pass the information
+  to try_to_display_directories_with_overrides() that non-default
+  motd options are used.
+---
+ modules/pam_motd/pam_motd.c | 88 ++++++++++++++++---------------------
+ 1 file changed, 37 insertions(+), 51 deletions(-)
+
+diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
+index ec3ebd58..dbd718b6 100644
+--- a/modules/pam_motd/pam_motd.c
++++ b/modules/pam_motd/pam_motd.c
+@@ -22,6 +22,7 @@
+ #include <sys/stat.h>
+ #include <pwd.h>
+ #include <syslog.h>
++#include <errno.h>
+ 
+ #include <security/_pam_macros.h>
+ #include <security/pam_ext.h>
+@@ -48,8 +49,8 @@ pam_sm_close_session (pam_handle_t *pamh UNUSED, int flags UNUSED,
+      return PAM_IGNORE;
+ }
+ 
+-static char default_motd[] = DEFAULT_MOTD;
+-static char default_motd_dir[] = DEFAULT_MOTD_D;
++static const char default_motd[] = DEFAULT_MOTD;
++static const char default_motd_dir[] = DEFAULT_MOTD_D;
+ 
+ static void try_to_display_fd(pam_handle_t *pamh, int fd)
+ {
+@@ -75,28 +76,6 @@ static void try_to_display_fd(pam_handle_t *pamh, int fd)
+     _pam_drop(mtmp);
+ }
+ 
+-static void try_to_display_directory(pam_handle_t *pamh, const char *dirname)
+-{
+-    DIR *dirp;
+-
+-    dirp = opendir(dirname);
+-
+-    if (dirp != NULL) {
+-	struct dirent *entry;
+-
+-	while ((entry = readdir(dirp))) {
+-	    int fd = openat(dirfd(dirp), entry->d_name, O_RDONLY);
+-
+-	    if (fd >= 0) {
+-		try_to_display_fd(pamh, fd);
+-		close(fd);
+-	    }
+-	}
+-
+-	closedir(dirp);
+-    }
+-}
+-
+ /*
+  * Split a DELIM-separated string ARG into an array.
+  * Outputs a newly allocated array of strings OUT_ARG_SPLIT
+@@ -104,14 +83,14 @@ static void try_to_display_directory(pam_handle_t *pamh, const char *dirname)
+  * 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 ***out_arg_split, unsigned int *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;
++    unsigned int i = 0;
++    unsigned int num_strs = 0;
+     int retval = 0;
+ 
+     delim_str[0] = delim;
+@@ -126,7 +105,7 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
+ 	arg_ptr = strchr(arg_ptr + sizeof(const char), delim);
+     }
+ 
+-    arg_split = (char **)calloc(num_strs, sizeof(char *));
++    arg_split = calloc(num_strs, sizeof(char *));
+     if (arg_split == NULL) {
+ 	pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate string array");
+ 	goto out;
+@@ -180,10 +159,10 @@ static int join_dir_strings(char **strp_out, const char *a_str, const char *b_st
+     return retval;
+ }
+ 
+-static int compare_strings(const void * a, const void * b)
++static int compare_strings(const void *a, const void *b)
+ {
+-    const char *a_str = *(char **)a;
+-    const char *b_str = *(char **)b;
++    const char *a_str = *(const char * const *)a;
++    const char *b_str = *(const char * const *)b;
+ 
+     if (a_str == NULL && b_str == NULL) {
+         return 0;
+@@ -205,13 +184,13 @@ static int filter_dirents(const struct dirent *d)
+ }
+ 
+ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+-	char **motd_dir_path_split, int num_motd_dirs)
++	char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing)
+ {
+     struct dirent ***dirscans = NULL;
+-    int *dirscans_sizes = NULL;
+-    int dirscans_size_total = 0;
++    unsigned int *dirscans_sizes = NULL;
++    unsigned int dirscans_size_total = 0;
+     char **dirnames_all = NULL;
+-    int i;
++    unsigned int i;
+     int i_dirnames = 0;
+ 
+     if (pamh == NULL || motd_dir_path_split == NULL) {
+@@ -221,29 +200,31 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+ 	goto out;
+     }
+ 
+-    if ((dirscans = (struct dirent ***)calloc(num_motd_dirs,
+-	    sizeof(struct dirent **))) == NULL) {
++    if ((dirscans = 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) {
++    if ((dirscans_sizes = 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]),
++	int rv;
++	rv = 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;
++	if (rv < 0) {
++	    if (errno != ENOENT || report_missing) {
++		pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s: %m",
++		    motd_dir_path_split[i]);
++	    }
++	    dirscans_sizes[i] = rv;
+ 	}
+ 	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) {
++    if ((dirnames_all = calloc(dirscans_size_total, sizeof(char *))) == NULL) {
+ 	pam_syslog(pamh, LOG_CRIT, "pam_motd: failed to allocate dirname array");
+ 	goto out;
+     }
+@@ -253,7 +234,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+     }
+ 
+     for (i = 0; i < num_motd_dirs; i++) {
+-	int j;
++	unsigned int j;
+ 
+ 	for (j = 0; j < dirscans_sizes[i]; j++) {
+ 	    dirnames_all[i_dirnames] = dirscans[i][j]->d_name;
+@@ -265,7 +246,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+ 	    sizeof(const char *), compare_strings);
+ 
+     for (i = 0; i < dirscans_size_total; i++) {
+-	int j;
++	unsigned int j;
+ 
+ 	if (dirnames_all[i] == NULL) {
+ 	    continue;
+@@ -301,7 +282,8 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+   out:
+     _pam_drop(dirnames_all);
+     for (i = 0; i < num_motd_dirs; i++) {
+-	int j;
++	unsigned int j;
++
+ 	for (j = 0; j < dirscans_sizes[i]; j++) {
+ 	    _pam_drop(dirscans[i][j]);
+ 	}
+@@ -319,12 +301,13 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+     int retval = PAM_IGNORE;
+     const char *motd_path = NULL;
+     char *motd_path_copy = NULL;
+-    int num_motd_paths = 0;
++    unsigned 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;
++    unsigned int num_motd_dir_paths = 0;
+     char **motd_dir_path_split = NULL;
++    int report_missing;
+ 
+     if (flags & PAM_SILENT) {
+ 	return retval;
+@@ -360,6 +343,9 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+     if (motd_path == NULL && motd_dir_path == NULL) {
+ 	motd_path = default_motd;
+ 	motd_dir_path = default_motd_dir;
++	report_missing = 0;
++    } else {
++	report_missing = 1;
+     }
+ 
+     if (motd_path != NULL) {
+@@ -385,7 +371,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+     }
+ 
+     if (motd_path_split != NULL) {
+-	int i;
++	unsigned int i;
+ 
+ 	for (i = 0; i < num_motd_paths; i++) {
+ 	    int fd = open(motd_path_split[i], O_RDONLY, 0);
+@@ -402,7 +388,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
+ 
+     if (motd_dir_path_split != NULL)
+ 	try_to_display_directories_with_overrides(pamh, motd_dir_path_split,
+-		num_motd_dir_paths);
++		num_motd_dir_paths, report_missing);
+ 
+   out:
+     _pam_drop(motd_path_copy);
+-- 
+2.37.3
+
+From c2c0434bd634a817f2b16ce7f58fc96c04e88b03 Mon Sep 17 00:00:00 2001
+From: "Dmitry V. Levin" <ldv@altlinux.org>
+Date: Sun, 26 Apr 2020 11:12:59 +0000
+Subject: [PATCH] pam_motd: fix NULL dereference when at least one of motd
+ directories is not available
+
+* modules/pam_motd/pam_motd.c
+(try_to_display_directories_with_overrides): Do not assign -1U to
+dirscans_sizes[i] when scandir(motd_dir_path_split[i]) returns an error.
+
+Resolves: https://bugzilla.altlinux.org/38389
+Fixes: d57ab221 ("pam_motd: Cleanup the code and avoid unnecessary logging")
+---
+ modules/pam_motd/pam_motd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
+index df09b7d0..8147c6fd 100644
+--- a/modules/pam_motd/pam_motd.c
++++ b/modules/pam_motd/pam_motd.c
+@@ -219,6 +219,7 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
+ 		pam_syslog(pamh, LOG_ERR, "pam_motd: error scanning directory %s: %m",
+ 		    motd_dir_path_split[i]);
+ 	    }
++	} else {
+ 	    dirscans_sizes[i] = rv;
+ 	}
+ 	dirscans_size_total += dirscans_sizes[i];
+-- 
+2.37.3
+
diff --git a/SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch b/SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch
new file mode 100644
index 0000000..35e3d94
--- /dev/null
+++ b/SOURCES/pam-1.3.1-pam-pwhistory-load-conf-from-file.patch
@@ -0,0 +1,573 @@
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file	2022-09-29 10:13:35.709355179 +0200
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/Makefile.am	2022-09-29 10:13:35.780355766 +0200
+@@ -10,9 +10,10 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst-
+ 
+ TESTS = tst-pam_pwhistory
+ 
+-man_MANS = pam_pwhistory.8 pwhistory_helper.8
++man_MANS = pam_pwhistory.8 pwhistory_helper.8 pwhistory.conf.5
+ 
+-XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
++XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml \
++  pwhistory.conf.5.xml
+ 
+ securelibdir = $(SECUREDIR)
+ secureconfdir = $(SCONFIGDIR)
+@@ -25,12 +26,14 @@ if HAVE_VERSIONING
+   pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+ endif
+ 
+-noinst_HEADERS = opasswd.h
++noinst_HEADERS = opasswd.h pwhistory_config.h
++
++dist_secureconf_DATA = pwhistory.conf
+ 
+ securelib_LTLIBRARIES = pam_pwhistory.la
+ 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
++pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c pwhistory_config.c
+ 
+ sbin_PROGRAMS = pwhistory_helper
+ pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file	2017-02-10 11:10:15.000000000 +0100
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.8.xml	2022-09-29 10:13:35.780355766 +0200
+@@ -36,6 +36,9 @@
+       <arg choice="opt">
+         authtok_type=<replaceable>STRING</replaceable>
+       </arg>
++      <arg choice="opt">
++	      conf=<replaceable>/path/to/config-file</replaceable>
++      </arg>
+ 
+     </cmdsynopsis>
+   </refsynopsisdiv>
+@@ -104,7 +107,7 @@
+         <listitem>
+           <para>
+             The last <replaceable>N</replaceable> passwords for each
+-            user are saved in <filename>/etc/security/opasswd</filename>.
++            user are saved.
+             The default is <emphasis>10</emphasis>. Value of
+             <emphasis>0</emphasis> makes the module to keep the existing
+             contents of the <filename>opasswd</filename> file unchanged.
+@@ -137,7 +140,26 @@
+           </listitem>
+         </varlistentry>
+ 
++        <varlistentry>
++          <term>
++            <option>conf=<replaceable>/path/to/config-file</replaceable></option>
++          </term>
++          <listitem>
++            <para>
++              Use another configuration file instead of the default
++              <filename>/etc/security/pwhistory.conf</filename>.
++            </para>
++          </listitem>
++        </varlistentry>
++
+     </variablelist>
++    <para>
++      The options for configuring the module behavior are described in the
++      <citerefentry><refentrytitle>pwhistory.conf</refentrytitle>
++      <manvolnum>5</manvolnum></citerefentry> manual page. The options
++      specified on the module command line override the values from the
++      configuration file.
++    </para>
+   </refsect1>
+ 
+   <refsect1 id="pam_pwhistory-types">
+@@ -223,6 +245,9 @@ password     required       pam_unix.so
+     <title>SEE ALSO</title>
+     <para>
+       <citerefentry>
++	<refentrytitle>pwhistory.conf</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
++      <citerefentry>
+ 	<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
+       </citerefentry>,
+       <citerefentry>
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file	2022-09-29 10:13:35.711355195 +0200
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pam_pwhistory.c	2022-09-29 10:13:35.780355766 +0200
+@@ -62,18 +62,11 @@
+ #include <security/_pam_macros.h>
+ 
+ #include "opasswd.h"
++#include "pwhistory_config.h"
+ 
+ #define DEFAULT_BUFLEN 2048
+ #define MAX_FD_NO 20000
+ 
+-struct options_t {
+-  int debug;
+-  int enforce_for_root;
+-  int remember;
+-  int tries;
+-};
+-typedef struct options_t options_t;
+-
+ 
+ static void
+ parse_option (pam_handle_t *pamh, const char *argv, options_t *options)
+@@ -304,6 +297,8 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
+   options.remember = 10;
+   options.tries = 1;
+ 
++  parse_config_file(pamh, argc, argv, &options);
++
+   /* Parse parameters for module */
+   for ( ; argc-- > 0; argv++)
+     parse_option (pamh, *argv, &options);
+@@ -311,7 +306,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
+   if (options.debug)
+     pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok entered");
+ 
+-
+   if (options.remember == 0)
+     return PAM_IGNORE;
+ 
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file	2022-09-29 10:13:35.780355766 +0200
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.5.xml	2022-09-29 10:13:35.780355766 +0200
+@@ -0,0 +1,155 @@
++<?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.conf">
++
++  <refmeta>
++    <refentrytitle>pwhistory.conf</refentrytitle>
++    <manvolnum>5</manvolnum>
++    <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
++  </refmeta>
++
++  <refnamediv id="pwhistory.conf-name">
++    <refname>pwhistory.conf</refname>
++    <refpurpose>pam_pwhistory configuration file</refpurpose>
++  </refnamediv>
++
++  <refsect1 id="pwhistory.conf-description">
++
++    <title>DESCRIPTION</title>
++    <para>
++       <emphasis remap='B'>pwhistory.conf</emphasis> provides a way to configure the
++       default settings for saving the last passwords for each user.
++       This file is read by the <emphasis>pam_pwhistory</emphasis> module and is the
++       preferred method over configuring <emphasis>pam_pwhistory</emphasis> directly.
++    </para>
++    <para>
++       The file has a very simple <emphasis>name = value</emphasis> format with possible comments
++       starting with <emphasis>#</emphasis> character. The whitespace at the beginning of line, end
++       of line, and around the <emphasis>=</emphasis> sign is ignored.
++    </para>
++  </refsect1>
++
++  <refsect1 id="pwhistory.conf-options">
++
++    <title>OPTIONS</title>
++         <variablelist>
++            <varlistentry>
++              <term>
++                <option>debug</option>
++              </term>
++              <listitem>
++                <para>
++                  Turns on debugging via
++                  <citerefentry>
++                    <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
++                  </citerefentry>.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>enforce_for_root</option>
++              </term>
++              <listitem>
++                <para>
++                  If this option is set, the check is enforced for root, too.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>remember=<replaceable>N</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  The last <replaceable>N</replaceable> passwords for each
++                  user are saved.
++                  The default is <emphasis>10</emphasis>. Value of
++                  <emphasis>0</emphasis> makes the module to keep the existing
++                  contents of the <filename>opasswd</filename> file unchanged.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>retry=<replaceable>N</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  Prompt user at most <replaceable>N</replaceable> times
++                  before returning with error. The default is 1.
++                </para>
++              </listitem>
++            </varlistentry>
++            <varlistentry>
++              <term>
++                <option>file=<replaceable>/path/filename</replaceable></option>
++              </term>
++              <listitem>
++                <para>
++                  Store password history in file
++                  <replaceable>/path/filename</replaceable> rather than the default
++                  location. The default location is
++	                <filename>/etc/security/opasswd</filename>.
++                </para>
++              </listitem>
++            </varlistentry>
++        </variablelist>
++  </refsect1>
++
++  <refsect1 id='pwhistory.conf-examples'>
++    <title>EXAMPLES</title>
++    <para>
++      /etc/security/pwhistory.conf file example:
++    </para>
++    <programlisting>
++debug
++remember=5
++file=/tmp/opasswd
++    </programlisting>
++  </refsect1>
++
++  <refsect1 id="pwhistory.conf-files">
++    <title>FILES</title>
++    <variablelist>
++      <varlistentry>
++        <term><filename>/etc/security/pwhistory.conf</filename></term>
++        <listitem>
++          <para>the config file for custom options</para>
++        </listitem>
++      </varlistentry>
++    </variablelist>
++  </refsect1>
++
++  <refsect1 id='pwhistory.conf-see_also'>
++    <title>SEE ALSO</title>
++    <para>
++      <citerefentry>
++        <refentrytitle>pwhistory</refentrytitle><manvolnum>8</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
++      </citerefentry>,
++      <citerefentry>
++        <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
++      </citerefentry>
++    </para>
++  </refsect1>
++
++  <refsect1 id='pwhistory.conf-author'>
++    <title>AUTHOR</title>
++      <para>
++        pam_pwhistory was written by Thorsten Kukuk. The support for
++        pwhistory.conf was written by Iker Pedrosa.
++      </para>
++  </refsect1>
++
++</refentry>
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file	2022-09-29 10:13:35.781355775 +0200
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.c	2022-09-29 10:14:33.377832622 +0200
+@@ -0,0 +1,195 @@
++/*
++ * Copyright (c) 2022 Iker Pedrosa <ipedrosa@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 <ctype.h>
++
++#include <security/pam_modutil.h>
++
++#include "pam_inline.h"
++#include "pwhistory_config.h"
++
++#define PWHISTORY_DEFAULT_CONF "/etc/security/pwhistory.conf"
++
++/* lookup a value for key in login.defs file or similar key value format */
++static char *
++pwhistory_search_key(pam_handle_t *pamh UNUSED,
++		       const char *file_name,
++		       const char *key)
++{
++	FILE *fp;
++	char *buf = NULL;
++	size_t buflen = 0;
++	char *retval = NULL;
++
++#ifdef USE_ECONF
++	if (strcmp (file_name, LOGIN_DEFS) == 0)
++		return econf_search_key ("login", ".defs", key);
++#endif
++
++	fp = fopen(file_name, "r");
++	if (NULL == fp)
++		return NULL;
++
++	while (!feof(fp)) {
++		char *tmp, *cp;
++#if defined(HAVE_GETLINE)
++		ssize_t n = getline(&buf, &buflen, fp);
++#elif defined (HAVE_GETDELIM)
++		ssize_t n = getdelim(&buf, &buflen, '\n', fp);
++#else
++		ssize_t n;
++
++		if (buf == NULL) {
++			buflen = BUF_SIZE;
++			buf = malloc(buflen);
++			if (buf == NULL) {
++				fclose(fp);
++				return NULL;
++			}
++		}
++		buf[0] = '\0';
++		if (fgets(buf, buflen - 1, fp) == NULL)
++			break;
++		else if (buf != NULL)
++			n = strlen(buf);
++		else
++			n = 0;
++#endif /* HAVE_GETLINE / HAVE_GETDELIM */
++		cp = buf;
++
++		if (n < 1)
++			break;
++		if (cp[n - 1] == '\n')
++			cp[n - 1] = '\0';
++
++		tmp = strchr(cp, '#');  /* remove comments */
++		if (tmp)
++			*tmp = '\0';
++		while (isspace((int)*cp))    /* remove spaces and tabs */
++			++cp;
++		if (*cp == '\0')        /* ignore empty lines */
++			continue;
++
++		tmp = strsep (&cp, " \t=");
++		if (cp != NULL)
++			while (isspace((int)*cp) || *cp == '=')
++				++cp;
++		else
++			cp = buf + n;   /* empty string */
++
++		if (strcasecmp(tmp, key) == 0) {
++			retval = strdup(cp);
++			break;
++		}
++	}
++	fclose(fp);
++
++	free(buf);
++
++	return retval;
++}
++
++void
++parse_config_file(pam_handle_t *pamh, int argc, const char **argv,
++                  struct options_t *options)
++{
++    const char *fname = NULL;
++    int i;
++    char *val;
++
++    for (i = 0; i < argc; ++i) {
++        const char *str = pam_str_skip_prefix(argv[i], "conf=");
++
++        if (str != NULL) {
++            fname = str;
++        }
++    }
++
++    if (fname == NULL) {
++        fname = PWHISTORY_DEFAULT_CONF;
++    }
++
++    val = pwhistory_search_key (pamh, fname, "debug");
++    if (val != NULL) {
++        options->debug = 1;
++        free(val);
++    }
++
++    val = pwhistory_search_key (pamh, fname, "enforce_for_root");
++    if (val != NULL) {
++        options->enforce_for_root = 1;
++        free(val);
++    }
++
++    val = pwhistory_search_key (pamh, fname, "remember");
++    if (val != NULL) {
++        unsigned int temp;
++        if (sscanf(val, "%u", &temp) != 1) {
++            pam_syslog(pamh, LOG_ERR,
++                "Bad number supplied for remember argument");
++        } else {
++            options->remember = temp;
++        }
++        free(val);
++    }
++
++    val = pwhistory_search_key (pamh, fname, "retry");
++    if (val != NULL) {
++        unsigned int temp;
++        if (sscanf(val, "%u", &temp) != 1) {
++            pam_syslog(pamh, LOG_ERR,
++                "Bad number supplied for retry argument");
++        } else {
++            options->tries = temp;
++        }
++        free(val);
++    }
++
++    val = pwhistory_search_key (pamh, fname, "file");
++    if (val != NULL) {
++        if (*val != '/') {
++            pam_syslog (pamh, LOG_ERR,
++                "File path should be absolute: %s", val);
++        } else {
++            options->filename = val;
++        }
++    }
++}
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file	2022-09-29 10:13:35.781355775 +0200
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory_config.h	2022-09-29 10:13:35.781355775 +0200
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2022 Iker Pedrosa <ipedrosa@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.
++ */
++
++#ifndef _PWHISTORY_CONFIG_H
++#define _PWHISTORY_CONFIG_H
++
++#include <security/pam_ext.h>
++
++struct options_t {
++    int debug;
++    int enforce_for_root;
++    int remember;
++    int tries;
++    const char *filename;
++};
++typedef struct options_t options_t;
++
++void
++parse_config_file(pam_handle_t *pamh, int argc, const char **argv,
++                  struct options_t *options);
++
++#endif /* _PWHISTORY_CONFIG_H */
+diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf
+--- Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file	2022-09-29 10:13:35.781355775 +0200
++++ Linux-PAM-1.3.1/modules/pam_pwhistory/pwhistory.conf	2022-09-29 10:13:35.781355775 +0200
+@@ -0,0 +1,21 @@
++# Configuration for remembering the last passwords used by a user.
++#
++# Enable the debugging logs.
++# Enabled if option is present.
++# debug
++#
++# root account's passwords are also remembered.
++# Enabled if option is present.
++# enforce_for_root
++#
++# Number of passwords to remember.
++# The default is 10.
++# remember = 10
++#
++# Number of times to prompt for the password.
++# The default is 1.
++# retry = 1
++#
++# The directory where the last passwords are kept.
++# The default is /etc/security/opasswd.
++# file = /etc/security/opasswd
diff --git a/SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch b/SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
new file mode 100644
index 0000000..016bb15
--- /dev/null
+++ b/SOURCES/pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
@@ -0,0 +1,37 @@
+From 10086bc69663fa819277af244eeb5b629a2403b8 Mon Sep 17 00:00:00 2001
+From: Deepak Das <ddas@redhat.com>
+Date: Mon, 10 Oct 2022 21:21:35 +0530
+Subject: [PATCH] pam_faillock: avoid logging an erroneous consecutive login
+ failure message
+
+* modules/pam_faillock/pam_faillock.c (write_tally): Avoid logging
+a consecutive login failure message for the root user in case when
+even_deny_root is not set.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2082442
+---
+ modules/pam_faillock/pam_faillock.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
+index ddbb90e7..ca1c7035 100644
+--- a/modules/pam_faillock/pam_faillock.c
++++ b/modules/pam_faillock/pam_faillock.c
+@@ -374,9 +374,11 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
+ 		}
+ 		close(audit_fd);
+ #endif
+-		if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO)) {
+-			pam_syslog(pamh, LOG_INFO, "Consecutive login failures for user %s account temporarily locked",
+-				opts->user);
++		if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO) &&
++		    ((opts->flags & FAILLOCK_FLAG_DENY_ROOT) || (opts->uid != 0))) {
++			pam_syslog(pamh, LOG_INFO,
++				   "Consecutive login failures for user %s account temporarily locked",
++				   opts->user);
+ 		}
+ 	}
+ 
+-- 
+2.38.1
+
diff --git a/SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch b/SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch
new file mode 100644
index 0000000..3f15eb8
--- /dev/null
+++ b/SOURCES/pam-1.5.1-pam-faillock-clarify-missing-user.patch
@@ -0,0 +1,53 @@
+From bcbf145ce925934214e48200c27c9ff736452549 Mon Sep 17 00:00:00 2001
+From: Deepak Das <ddas@redhat.com>
+Date: Mon, 10 Oct 2022 17:55:53 +0530
+Subject: [PATCH] pam_faillock: Clarify missing user faillock files after
+ reboot
+
+* modules/pam_faillock/faillock.conf.5.xml: Adding note related to missing
+user specific faillock files after reboot.
+
+* modules/pam_faillock/pam_faillock.8.xml: Adding note related to missing
+user specific faillock files after reboot.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2062512
+---
+ modules/pam_faillock/faillock.conf.5.xml | 4 ++++
+ modules/pam_faillock/pam_faillock.8.xml  | 6 ++++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/modules/pam_faillock/faillock.conf.5.xml b/modules/pam_faillock/faillock.conf.5.xml
+index 04a84107..8faa5915 100644
+--- a/modules/pam_faillock/faillock.conf.5.xml
++++ b/modules/pam_faillock/faillock.conf.5.xml
+@@ -44,6 +44,10 @@
+                   The directory where the user files with the failure records are kept. The
+                   default is <filename>/var/run/faillock</filename>.
+                 </para>
++                <para>
++                  Note: These files will disappear after reboot on systems configured with
++                  directory <filename>/var/run/faillock</filename> mounted on virtual memory.
++                </para>
+               </listitem>
+             </varlistentry>
+             <varlistentry>
+diff --git a/modules/pam_faillock/pam_faillock.8.xml b/modules/pam_faillock/pam_faillock.8.xml
+index 79bcbbd0..b7b7b0db 100644
+--- a/modules/pam_faillock/pam_faillock.8.xml
++++ b/modules/pam_faillock/pam_faillock.8.xml
+@@ -327,6 +327,12 @@ session  required       pam_selinux.so open
+         <term><filename>/var/run/faillock/*</filename></term>
+         <listitem>
+           <para>the files logging the authentication failures for users</para>
++          <para>
++            Note: These files will disappear after reboot on systems configured with
++            directory <filename>/var/run/faillock</filename> mounted on virtual memory.
++            For persistent storage use the option <emphasis>dir=</emphasis> in
++            file <filename>/etc/security/faillock.conf</filename>.
++          </para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+-- 
+2.38.1
+
diff --git a/SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch b/SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch
new file mode 100644
index 0000000..80ad508
--- /dev/null
+++ b/SOURCES/pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch
@@ -0,0 +1,41 @@
+From 40c271164dbcebfc5304d0537a42fb42e6b6803c Mon Sep 17 00:00:00 2001
+From: Iker Pedrosa <ipedrosa@redhat.com>
+Date: Mon, 26 Sep 2022 12:16:53 +0200
+Subject: [PATCH] pam_lastlog: check localtime_r() return value
+
+Check the return value of localtime_r() before calling strftime(). This
+function crashes if the argument is NULL.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012871
+
+Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
+---
+ modules/pam_lastlog/pam_lastlog.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
+index abd048df..121e7560 100644
+--- a/modules/pam_lastlog/pam_lastlog.c
++++ b/modules/pam_lastlog/pam_lastlog.c
+@@ -573,12 +573,12 @@ last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t llt
+ 	    time_t lf_time;
+ 
+ 	    lf_time = utuser.ut_tv.tv_sec;
+-	    tm = localtime_r (&lf_time, &tm_buf);
+-	    strftime (the_time, sizeof (the_time),
+-	        /* TRANSLATORS: "strftime options for date of last login" */
+-		_(" %a %b %e %H:%M:%S %Z %Y"), tm);
+-
+-	    date = the_time;
++	    if ((tm = localtime_r (&lf_time, &tm_buf)) != NULL) {
++	        strftime (the_time, sizeof (the_time),
++	            /* TRANSLATORS: "strftime options for date of last login" */
++	                  _(" %a %b %e %H:%M:%S %Z %Y"), tm);
++	        date = the_time;
++	    }
+ 	}
+ 
+ 	/* we want & have the host? */
+-- 
+2.38.1
+
diff --git a/SPECS/pam.spec b/SPECS/pam.spec
index 8b0ed82..25deb7d 100644
--- a/SPECS/pam.spec
+++ b/SPECS/pam.spec
@@ -3,7 +3,7 @@
 Summary: An extensible library which provides authentication for applications
 Name: pam
 Version: 1.3.1
-Release: 22%{?dist}
+Release: 25%{?dist}
 # The library is BSD licensed with option to relicense as GPLv2+
 # - this option is redundant as the BSD license allows that anyway.
 # pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+.
@@ -85,6 +85,18 @@ Patch57: pam-1.3.1-inline.patch
 Patch58: pam-1.3.1-faillock-load-conf-from-file.patch
 # https://github.com/linux-pam/linux-pam/commit/370064ef6f99581b08d473a42bb3417d5dda3e4e
 Patch59: pam-1.3.1-pam-usertype-SYS_UID_MAX.patch
+# https://github.com/linux-pam/linux-pam/commit/ba2f6dd8b81ea2a58262c1709bec906b6852591d
+# https://github.com/linux-pam/linux-pam/commit/1180bde923a22605fe8075cd1fe7992ed7513411
+Patch60: pam-1.3.1-pam-pwhistory-load-conf-from-file.patch
+# https://github.com/linux-pam/linux-pam/commit/d57ab22133654033ee1da89f128a81572d320985
+# https://github.com/linux-pam/linux-pam/commit/c2c0434bd634a817f2b16ce7f58fc96c04e88b03
+Patch61: pam-1.3.1-pam-motd-avoid-unnecessary-logging.patch
+# https://github.com/linux-pam/linux-pam/commit/40c271164dbcebfc5304d0537a42fb42e6b6803c
+Patch62: pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch
+# https://github.com/linux-pam/linux-pam/commit/bcbf145ce925934214e48200c27c9ff736452549
+Patch63: pam-1.5.1-pam-faillock-clarify-missing-user.patch
+# https://github.com/linux-pam/linux-pam/commit/10086bc69663fa819277af244eeb5b629a2403b8
+Patch64: pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
 
 %define _pamlibdir %{_libdir}
 %define _moduledir %{_libdir}/security
@@ -192,6 +204,11 @@ cp %{SOURCE18} .
 %patch57 -p1 -b .inline
 %patch58 -p1 -b .faillock-load-conf-from-file
 %patch59 -p1 -b .pam-usertype-SYS_UID_MAX
+%patch60 -p1 -b .pam-pwhistory-load-conf-from-file
+%patch61 -p1 -b .pam-motd-avoid-unnecessary-logging
+%patch62 -p1 -b .pam-lastlog-check-localtime_r-return-value
+%patch63 -p1 -b .pam-faillock-clarify-missing-user
+%patch64 -p1 -b .pam-faillock-avoid-logging-erroneous
 
 autoreconf -i
 
@@ -416,6 +433,7 @@ done
 %dir %{_secconfdir}/namespace.d
 %attr(755,root,root) %config(noreplace) %{_secconfdir}/namespace.init
 %config(noreplace) %{_secconfdir}/pam_env.conf
+%config(noreplace) %{_secconfdir}/pwhistory.conf
 %config(noreplace) %{_secconfdir}/time.conf
 %config(noreplace) %{_secconfdir}/opasswd
 %dir %{_secconfdir}/console.apps
@@ -444,6 +462,15 @@ done
 %doc doc/specs/rfc86.0.txt
 
 %changelog
+* Tue Nov 29 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-25
+- pam_motd: avoid unnecessary logging. Resolves: #2091062
+- pam_lastlog: check localtime_r() return value. Resolves: #2012871
+- pam_faillock: clarify missing user faillock files after reboot. Resolves: #2062512
+- pam_faillock: avoid logging an erroneous consecutive login failure message. Resolves: #2082442
+
+* Thu Sep 29 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-24
+- pam_pwhistory: load configuration from file. Resolves: #2068461
+
 * Wed Jul 13 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-22
 - Regenerate the /run/motd.d at each boot. Resolves: #2104878