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 @@
+
+ authtok_type=STRING
+
++
++ conf=/path/to/config-file
++
+
+
+
+@@ -104,7 +107,7 @@
+
+
+ The last N passwords for each
+- user are saved in /etc/security/opasswd.
++ user are saved.
+ The default is 10. Value of
+ 0 makes the module to keep the existing
+ contents of the opasswd file unchanged.
+@@ -137,7 +140,26 @@
+
+
+
++
++
++
++
++
++
++ Use another configuration file instead of the default
++ /etc/security/pwhistory.conf.
++
++
++
++
+
++
++ The options for configuring the module behavior are described in the
++ pwhistory.conf
++ 5 manual page. The options
++ specified on the module command line override the values from the
++ configuration file.
++
+
+
+
+@@ -223,6 +245,9 @@ password required pam_unix.so
+ SEE ALSO
+
+
++ pwhistory.conf5
++ ,
++
+ pam.conf5
+ ,
+
+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
+
+ #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 @@
++
++
++
++
++
++
++ pwhistory.conf
++ 5
++ Linux-PAM Manual
++
++
++
++ pwhistory.conf
++ pam_pwhistory configuration file
++
++
++
++
++ DESCRIPTION
++
++ pwhistory.conf provides a way to configure the
++ default settings for saving the last passwords for each user.
++ This file is read by the pam_pwhistory module and is the
++ preferred method over configuring pam_pwhistory directly.
++
++
++ The file has a very simple name = value format with possible comments
++ starting with # character. The whitespace at the beginning of line, end
++ of line, and around the = sign is ignored.
++
++
++
++
++
++ OPTIONS
++
++
++
++
++
++
++
++ Turns on debugging via
++
++ syslog3
++ .
++
++
++
++
++
++
++
++
++
++ If this option is set, the check is enforced for root, too.
++
++
++
++
++
++
++
++
++
++ The last N passwords for each
++ user are saved.
++ The default is 10. Value of
++ 0 makes the module to keep the existing
++ contents of the opasswd file unchanged.
++
++
++
++
++
++
++
++
++
++ Prompt user at most N times
++ before returning with error. The default is 1.
++
++
++
++
++
++
++
++
++
++ Store password history in file
++ /path/filename rather than the default
++ location. The default location is
++ /etc/security/opasswd.
++
++
++
++
++
++
++
++ EXAMPLES
++
++ /etc/security/pwhistory.conf file example:
++
++
++debug
++remember=5
++file=/tmp/opasswd
++
++
++
++
++ FILES
++
++
++ /etc/security/pwhistory.conf
++
++ the config file for custom options
++
++
++
++
++
++
++ SEE ALSO
++
++
++ pwhistory8
++ ,
++
++ pam_pwhistory8
++ ,
++
++ pam.conf5
++ ,
++
++ pam.d5
++ ,
++
++ pam8
++
++
++
++
++
++ AUTHOR
++
++ pam_pwhistory was written by Thorsten Kukuk. The support for
++ pwhistory.conf was written by Iker Pedrosa.
++
++
++
++
+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
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, and the entire permission notice in its entirety,
++ * including the disclaimer of warranties.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * ALTERNATIVELY, this product may be distributed under the terms of
++ * the GNU Public License, in which case the provisions of the GPL are
++ * required INSTEAD OF the above restrictions. (This clause is
++ * necessary due to a potential bad interaction between the GPL and
++ * the restrictions contained in a BSD-style copyright.)
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "config.h"
++
++#include
++#include
++#include
++#include
++#include
++
++#include
++
++#include "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
++ *
++ * 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
++
++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/SPECS/pam.spec b/SPECS/pam.spec
index 8b0ed82..77e71c1 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: 24%{?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,9 @@ 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
%define _pamlibdir %{_libdir}
%define _moduledir %{_libdir}/security
@@ -192,6 +195,7 @@ 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
autoreconf -i
@@ -416,6 +420,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 +449,9 @@ done
%doc doc/specs/rfc86.0.txt
%changelog
+* Thu Sep 29 2022 Iker Pedrosa - 1.3.1-24
+- pam_pwhistory: load configuration from file. Resolves: #2068461
+
* Wed Jul 13 2022 Iker Pedrosa - 1.3.1-22
- Regenerate the /run/motd.d at each boot. Resolves: #2104878