Compare commits

...

3 Commits

Author SHA1 Message Date
eabdullin 314d1b0950 import UBI pam-1.3.1-27.el8 2023-11-14 19:52:36 +00:00
CentOS Sources 910e053cd6 import pam-1.3.1-25.el8 2023-05-17 02:28:14 +00:00
CentOS Sources af54e60230 import pam-1.3.1-22.el8 2022-11-08 14:07:23 +00:00
14 changed files with 2183 additions and 25 deletions

View File

@ -0,0 +1,125 @@
diff -up Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c
--- Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe 2017-02-10 11:10:15.000000000 +0100
+++ Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c 2022-04-25 12:10:28.071240439 +0200
@@ -20,6 +20,7 @@
#include <security/pam_modutil.h>
#include <security/pam_ext.h>
#include <sys/syscall.h>
+#include <stdatomic.h>
#define KEY_SPEC_SESSION_KEYRING -3 /* ID for session keyring */
#define KEY_SPEC_USER_KEYRING -4 /* ID for UID-specific keyring */
@@ -30,12 +31,12 @@
#define KEYCTL_REVOKE 3 /* revoke a key */
#define KEYCTL_LINK 8 /* link a key into a keyring */
-static int my_session_keyring;
-static int session_counter;
-static int do_revoke;
-static int revoke_as_uid;
-static int revoke_as_gid;
-static int xdebug = 0;
+static _Thread_local int my_session_keyring = 0;
+static _Atomic int session_counter = 0;
+static _Thread_local int do_revoke = 0;
+static _Thread_local uid_t revoke_as_uid;
+static _Thread_local gid_t revoke_as_gid;
+static _Thread_local int xdebug = 0;
static void debug(pam_handle_t *pamh, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
@@ -65,6 +66,33 @@ static int error(pam_handle_t *pamh, con
return PAM_SESSION_ERR;
}
+static int pam_setreuid(uid_t ruid, uid_t euid)
+{
+#if defined(SYS_setreuid32)
+ return syscall(SYS_setreuid32, ruid, euid);
+#else
+ return syscall(SYS_setreuid, ruid, euid);
+#endif
+}
+
+static int pam_setregid(gid_t rgid, gid_t egid)
+{
+#if defined(SYS_setregid32)
+ return syscall(SYS_setregid32, rgid, egid);
+#else
+ return syscall(SYS_setregid, rgid, egid);
+#endif
+}
+
+static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+#if defined(SYS_setresuid32)
+ return syscall(SYS_setresuid32, ruid, euid, suid);
+#else
+ return syscall(SYS_setresuid, ruid, euid, suid);
+#endif
+}
+
/*
* initialise the session keyring for this process
*/
@@ -139,23 +167,25 @@ static void kill_keyrings(pam_handle_t *
/* switch to the real UID and GID so that we have permission to
* revoke the key */
- if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0)
+ if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0)
error(pamh, "Unable to change GID to %d temporarily\n",
revoke_as_gid);
- if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0)
+ if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0)
error(pamh, "Unable to change UID to %d temporarily\n",
revoke_as_uid);
+ if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
+ error(pamh, "Unable to change GID back to %d\n", old_gid);
syscall(__NR_keyctl,
KEYCTL_REVOKE,
my_session_keyring);
/* return to the orignal UID and GID (probably root) */
- if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0)
+ if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0)
error(pamh, "Unable to change UID back to %d\n", old_uid);
- if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0)
+ if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0)
error(pamh, "Unable to change GID back to %d\n", old_gid);
my_session_keyring = 0;
@@ -210,14 +240,14 @@ int pam_sm_open_session(pam_handle_t *pa
/* switch to the real UID and GID so that the keyring ends up owned by
* the right user */
- if (gid != old_gid && setregid(gid, -1) < 0) {
+ if (gid != old_gid && pam_setregid(gid, -1) < 0) {
error(pamh, "Unable to change GID to %d temporarily\n", gid);
return PAM_SESSION_ERR;
}
- if (uid != old_uid && setreuid(uid, -1) < 0) {
+ if (uid != old_uid && pam_setreuid(uid, -1) < 0) {
error(pamh, "Unable to change UID to %d temporarily\n", uid);
- if (setregid(old_gid, -1) < 0)
+ if (pam_setregid(old_gid, -1) < 0)
error(pamh, "Unable to change GID back to %d\n", old_gid);
return PAM_SESSION_ERR;
}
@@ -225,10 +255,10 @@ int pam_sm_open_session(pam_handle_t *pa
ret = init_keyrings(pamh, force);
/* return to the orignal UID and GID (probably root) */
- if (uid != old_uid && setreuid(old_uid, -1) < 0)
+ if (uid != old_uid && pam_setreuid(old_uid, -1) < 0)
ret = error(pamh, "Unable to change UID back to %d\n", old_uid);
- if (gid != old_gid && setregid(old_gid, -1) < 0)
+ if (gid != old_gid && pam_setregid(old_gid, -1) < 0)
ret = error(pamh, "Unable to change GID back to %d\n", old_gid);
return ret;

View File

@ -0,0 +1,29 @@
diff -up Linux-PAM-1.3.1/configure.ac.pam-misc-configurable Linux-PAM-1.3.1/configure.ac
--- Linux-PAM-1.3.1/configure.ac.pam-misc-configurable 2023-06-26 09:57:00.243146563 +0200
+++ Linux-PAM-1.3.1/configure.ac 2023-06-26 09:59:45.353636685 +0200
@@ -621,6 +621,13 @@ if test x"$opt_kerneloverflowuid" == x;
fi
AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.])
+AC_ARG_WITH([misc-conv-bufsize],
+AS_HELP_STRING([--with-misc-conv-bufsize=<number>],
+ [Size of input buffer for libpam_misc's misc_conv() conversation function, default=4096]),
+ [],
+ [with_misc_conv_bufsize=4096])
+AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.])
+
dnl Files to be created from when we run configure
AC_CONFIG_FILES([Makefile libpam/Makefile libpamc/Makefile libpamc/test/Makefile \
libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
diff -up Linux-PAM-1.3.1/libpam_misc/misc_conv.c.pam-misc-configurable Linux-PAM-1.3.1/libpam_misc/misc_conv.c
--- Linux-PAM-1.3.1/libpam_misc/misc_conv.c.pam-misc-configurable 2023-06-26 09:57:00.242146560 +0200
+++ Linux-PAM-1.3.1/libpam_misc/misc_conv.c 2023-06-26 10:00:38.023787972 +0200
@@ -18,7 +18,7 @@
#include <security/pam_appl.h>
#include <security/pam_misc.h>
-#define INPUTSIZE PAM_MAX_MSG_SIZE /* maximum length of input+1 */
+#define INPUTSIZE PAM_MISC_CONV_BUFSIZE /* maximum length of input+1 */
#define CONV_ECHO_ON 1 /* types of echo state */
#define CONV_ECHO_OFF 0

View File

@ -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

View File

@ -0,0 +1,57 @@
From 62cd745d730e5ba13d5d7092ac566fc0b2148e61 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 memory leak
pam_motd used to leak memory allocated for each motd file
successfully opened in try_to_display_directories_with_overrides.
* modules/pam_motd/pam_motd.c
(try_to_display_directories_with_overrides): Free abs_path.
Fixes: f9c9c721 ("pam_motd: Support multiple motd paths specified, with filename overrides (#69)")
---
modules/pam_motd/pam_motd.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
index f0cd317d..3be129a5 100644
--- a/modules/pam_motd/pam_motd.c
+++ b/modules/pam_motd/pam_motd.c
@@ -259,23 +259,23 @@ static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
for (j = 0; j < num_motd_dirs; j++) {
char *abs_path = NULL;
+ int fd;
if (join_dir_strings(&abs_path, motd_dir_path_split[j],
- dirnames_all[i]) < 0) {
+ dirnames_all[i]) < 0 || abs_path == NULL) {
continue;
}
- if (abs_path != NULL) {
- int fd = open(abs_path, O_RDONLY, 0);
- if (fd >= 0) {
- try_to_display_fd(pamh, fd);
- close(fd);
+ fd = open(abs_path, O_RDONLY, 0);
+ _pam_drop(abs_path);
- /* We displayed a file, skip to the next file name. */
- break;
- }
+ 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);
}
}
--
2.35.3

View File

@ -0,0 +1,133 @@
From 8eaf5570cf011148a0b55c53570df5edaafebdb0 Mon Sep 17 00:00:00 2001
From: Robert Fairley <rfairley@users.noreply.github.com>
Date: Wed, 21 Nov 2018 02:46:02 -0500
Subject: [PATCH] pam_motd: Fix segmentation fault when no motd_dir specified
(#76)
This fixes a regression introduced by #69, where motd_path was set
to NULL and passed into strdup() if the motd_dir argument was
not specified in the configuration file. This caused a segmentation
fault.
* modules/pam_motd/pam_motd.c: fix checks for NULL in arguments
* xtests/Makefile.am: add test scripts and config file
* xtests/tst-pam_motd.sh: add running tst-pam_motd4.sh
* xtests/tst-pam_motd4.pamd: create
* xtests/tst-pam_motd4.sh: create
---
modules/pam_motd/pam_motd.c | 15 ++++++++++-----
xtests/Makefile.am | 4 ++--
xtests/tst-pam_motd.sh | 1 +
xtests/tst-pam_motd4.pamd | 3 +++
xtests/tst-pam_motd4.sh | 27 +++++++++++++++++++++++++++
5 files changed, 43 insertions(+), 7 deletions(-)
create mode 100644 xtests/tst-pam_motd4.pamd
create mode 100755 xtests/tst-pam_motd4.sh
diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c
index 1c1cfcfa..ec3ebd58 100644
--- a/modules/pam_motd/pam_motd.c
+++ b/modules/pam_motd/pam_motd.c
@@ -132,7 +132,6 @@ static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim,
goto out;
}
-
arg_extracted = strtok_r(arg, delim_str, &arg);
while (arg_extracted != NULL && i < num_strs) {
arg_split[i++] = arg_extracted;
@@ -363,15 +362,21 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
motd_dir_path = default_motd_dir;
}
- motd_path_copy = strdup(motd_path);
+ if (motd_path != NULL) {
+ 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) {
+ if (pam_split_string(pamh, motd_path_copy, ':',
+ &motd_path_split, &num_motd_paths) == 0) {
goto out;
}
}
- motd_dir_path_copy = strdup(motd_dir_path);
+ if (motd_dir_path != NULL) {
+ motd_dir_path_copy = strdup(motd_dir_path);
+ }
+
if (motd_dir_path_copy != NULL) {
if (pam_split_string(pamh, motd_dir_path_copy, ':',
&motd_dir_path_split, &num_motd_dir_paths) == 0) {
diff --git a/xtests/Makefile.am b/xtests/Makefile.am
index 555d5e33..4d5aba3d 100644
--- a/xtests/Makefile.am
+++ b/xtests/Makefile.am
@@ -34,8 +34,8 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \
tst-pam_pwhistory1.pamd tst-pam_pwhistory1.sh \
tst-pam_time1.pamd time.conf \
tst-pam_motd.sh tst-pam_motd1.sh tst-pam_motd2.sh \
- tst-pam_motd3.sh tst-pam_motd1.pamd \
- tst-pam_motd2.pamd tst-pam_motd3.pamd
+ 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 \
diff --git a/xtests/tst-pam_motd.sh b/xtests/tst-pam_motd.sh
index 9b0c38f6..90801280 100755
--- a/xtests/tst-pam_motd.sh
+++ b/xtests/tst-pam_motd.sh
@@ -5,3 +5,4 @@ set -e
./tst-pam_motd1.sh
./tst-pam_motd2.sh
./tst-pam_motd3.sh
+./tst-pam_motd4.sh
diff --git a/xtests/tst-pam_motd4.pamd b/xtests/tst-pam_motd4.pamd
new file mode 100644
index 00000000..9dc311ad
--- /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 00000000..6022177f
--- /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
--
2.35.1

View File

@ -0,0 +1,691 @@
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.939663167 +0200
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml 2022-04-25 12:34:43.506582206 +0200
@@ -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,18 +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 and
- all files from <filename>/etc/motd.d</filename> are
- 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 in the directories listed above are displayed in lexicographic
+ order by name. Moreover, the files are filtered by reading them with the
+ credentials of the target user authenticating on the system.
</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 -sfn /dev/null /etc/motd.d/my_motd</command>
+ <command>ln -s /dev/null /etc/motd.d/my_motd</command>
</para>
</refsect1>
@@ -56,8 +90,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>
@@ -68,16 +104,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 -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c.pam_motd-support-multiple-motd-paths1 2018-05-18 11:50:46.000000000 +0200
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.c 2022-04-25 12:32:36.947663225 +0200
@@ -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,235 @@ static void try_to_display_directory(pam
}
}
+/*
+ * 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;
@@ -140,17 +363,47 @@ int pam_sm_open_session(pam_handle_t *pa
motd_dir_path = default_motd_dir;
}
- 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;
+ }
+ }
+
+ motd_dir_path_copy = strdup(motd_dir_path);
+ 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_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);
+ 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 != NULL)
- try_to_display_directory(pamh, motd_dir_path);
+ 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 -up Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/Makefile.am
--- Linux-PAM-1.3.1/xtests/Makefile.am.pam_motd-support-multiple-motd-paths1 2017-02-10 11:10:15.000000000 +0100
+++ Linux-PAM-1.3.1/xtests/Makefile.am 2022-04-25 12:32:36.947663225 +0200
@@ -32,7 +32,10 @@ EXTRA_DIST = run-xtests.sh tst-pam_dispa
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_motd1.pamd \
+ tst-pam_motd2.pamd tst-pam_motd3.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_dispa
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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd
--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.pamd 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh
--- Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd1.sh 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd
--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.pamd 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh
--- Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd2.sh 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd
--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.pamd 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh
--- Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd3.sh 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.c
--- Linux-PAM-1.3.1/xtests/tst-pam_motd.c.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd.c 2022-04-25 12:32:36.947663225 +0200
@@ -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 -up Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 Linux-PAM-1.3.1/xtests/tst-pam_motd.sh
--- Linux-PAM-1.3.1/xtests/tst-pam_motd.sh.pam_motd-support-multiple-motd-paths1 2022-04-25 12:32:36.947663225 +0200
+++ Linux-PAM-1.3.1/xtests/tst-pam_motd.sh 2022-04-25 12:32:36.947663225 +0200
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+set -e
+
+./tst-pam_motd1.sh
+./tst-pam_motd2.sh
+./tst-pam_motd3.sh

View File

@ -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

View File

@ -0,0 +1,75 @@
diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/configure.ac
--- Linux-PAM-1.3.1/configure.ac.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.169146826 +0200
+++ Linux-PAM-1.3.1/configure.ac 2022-06-22 16:43:54.343373619 +0200
@@ -615,12 +615,6 @@ if test x"$opt_uidmin" == x; then
fi
AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.])
-AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=<number>],[default value for system user min uid (101)]), opt_sysuidmin=$withval)
-if test x"$opt_sysuidmin" == x; then
- opt_sysuidmin=101
-fi
-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
-
AC_ARG_WITH([kerneloverflowuid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
if test x"$opt_kerneloverflowuid" == x; then
opt_kerneloverflowuid=65534
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.155146722 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml 2022-06-22 16:41:09.169146826 +0200
@@ -31,7 +31,7 @@
pam_usertype.so is designed to succeed or fail authentication
based on type of the account of the authenticated user.
The type of the account is decided with help of
- <emphasis>SYS_UID_MIN</emphasis> and <emphasis>SYS_UID_MAX</emphasis>
+ <emphasis>SYS_UID_MAX</emphasis>
settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
whether to load other modules based on this test.
</para>
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype-SYS_UID_MAX 2022-06-22 16:41:09.155146722 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2022-06-22 16:41:09.169146826 +0200
@@ -277,7 +277,6 @@ static int
pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
{
uid_t uid_min;
- uid_t sys_min;
uid_t sys_max;
if (uid == (uid_t)-1) {
@@ -285,21 +284,19 @@ pam_usertype_is_system(pam_handle_t *pam
return PAM_USER_UNKNOWN;
}
- if (uid <= 99) {
- /* Reserved. */
- return PAM_SUCCESS;
- }
-
if (uid == PAM_USERTYPE_OVERFLOW_UID) {
/* nobody */
return PAM_SUCCESS;
}
uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN);
- sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN);
sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1);
- return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR;
+ if (uid <= sys_max && uid < uid_min) {
+ return PAM_SUCCESS;
+ }
+
+ return PAM_AUTH_ERR;
}
static int
@@ -336,7 +333,7 @@ pam_usertype_evaluate(struct pam_usertyp
/**
* Arguments:
- * - issystem: uid in <SYS_UID_MIN, SYS_UID_MAX>
+ * - issystem: uid less than SYS_UID_MAX
* - isregular: not issystem
* - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if)
* - audit: log unknown users to syslog

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,4 @@
d /run/console 0755 root root -
d /run/faillock 0755 root root -
d /run/sepermit 0755 root root -
d /run/motd.d 0755 root root -

View File

@ -1,19 +1,4 @@
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authselect is run.
auth required pam_env.so
auth [success=done ignore=ignore default=die] pam_pkcs11.so wait_for_card
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_localuser.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
password optional pam_pkcs11.so
session optional pam_keyinit.so revoke
session required pam_limits.so
-session optional pam_systemd.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
auth sufficient pam_sss.so allow_missing_name

View File

@ -3,7 +3,7 @@
Summary: An extensible library which provides authentication for applications
Name: pam
Version: 1.3.1
Release: 16%{?dist}.1
Release: 27%{?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+.
@ -69,12 +69,37 @@ Patch49: pam-1.3.1-namespace-gdm-doc.patch
Patch50: pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch
# https://github.com/linux-pam/linux-pam/commit/3234488f2c52a021eec87df1990d256314c21bff
Patch51: pam-1.3.1-pam-limits-unlimited-value.patch
# https://github.com/linux-pam/linux-pam/commit/a35e092e24ee7632346a0e1b4a203c04d4cd2c62
Patch52: pam-1.3.1-pam-keyinit-thread-safe.patch
# https://github.com/linux-pam/linux-pam/commit/f9c9c72121eada731e010ab3620762bcf63db08f
Patch53: pam-1.3.1-pam-motd-support-multiple-motd-paths.patch
# https://github.com/linux-pam/linux-pam/commit/8eaf5570cf011148a0b55c53570df5edaafebdb0
Patch54: pam-1.3.1-pam-motd-fix-segmentation-fault.patch
# https://github.com/linux-pam/linux-pam/commit/62cd745d730e5ba13d5d7092ac566fc0b2148e61
Patch55: pam-1.3.1-pam-motd-fix-memory-leak.patch
# Needed by the next patch. Already upstreamed
Patch52: pam-1.3.1-pam-cc-compat.patch
Patch53: pam-1.3.1-inline.patch
Patch56: pam-1.3.1-pam-cc-compat.patch
Patch57: pam-1.3.1-inline.patch
# https://github.com/linux-pam/linux-pam/commit/9bcbe96d9e82a23d983c0618178a8dc25596ac2d
# https://github.com/linux-pam/linux-pam/commit/fc867a9e22eac2c9a0ed0577776bba4df21c9aad
Patch54: pam-1.3.1-faillock-load-conf-from-file.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
# https://github.com/linux-pam/linux-pam/commit/55f206447a1e4ee26e307e7a9c069236e823b1a5
# https://github.com/linux-pam/linux-pam/commit/80bfda5962e5be3daa70e0fc8c75fc97d1c55121
Patch65: pam-1.3.1-pam-misc-configurable.patch
%define _pamlibdir %{_libdir}
%define _moduledir %{_libdir}/security
@ -174,9 +199,20 @@ cp %{SOURCE18} .
%patch49 -p1 -b .namespace-gdm-doc
%patch50 -p1 -b .pam-userdb-prevent-garbage-characters-from-db
%patch51 -p1 -b .pam-limits-unlimited-value
%patch52 -p1 -b .pam-cc-compat
%patch53 -p1 -b .inline
%patch54 -p1 -b .faillock-load-conf-from-file
%patch52 -p1 -b .pam-keyinit-thread-safe
%patch53 -p1 -b .pam-motd-support-multiple-motd-paths
%patch54 -p1 -b .pam-motd-fix-segmentation-fault
%patch55 -p1 -b .pam-motd-fix-memory-leak
%patch56 -p1 -b .pam-cc-compat
%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
%patch65 -p1 -b .pam-misc-configurable
autoreconf -i
@ -231,6 +267,9 @@ install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_pamconfdir}/postlogin
install -m 600 /dev/null $RPM_BUILD_ROOT%{_secconfdir}/opasswd
install -d -m 755 $RPM_BUILD_ROOT/var/log
install -d -m 755 $RPM_BUILD_ROOT/var/run/faillock
install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/motd.d
install -d -m 755 $RPM_BUILD_ROOT/usr/lib/motd.d
install -d -m 755 $RPM_BUILD_ROOT/run/motd.d
# Install man pages.
install -m 644 %{SOURCE12} %{SOURCE13} %{SOURCE17} $RPM_BUILD_ROOT%{_mandir}/man5/
@ -398,6 +437,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
@ -408,6 +448,9 @@ done
%dir /var/run/sepermit
%endif
%dir /var/run/faillock
%dir %{_sysconfdir}/motd.d
%dir /run/motd.d
%dir /usr/lib/motd.d
%{_prefix}/lib/tmpfiles.d/pam.conf
%{_mandir}/man5/*
%{_mandir}/man8/*
@ -423,8 +466,40 @@ done
%doc doc/specs/rfc86.0.txt
%changelog
* Tue Aug 2 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-16.1
- faillock: load configuration from file. Resolves: #2112889
* Mon Jun 26 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-27
- pam_misc: make length of misc_conv() configurable and set to 4096. Resolves: #2209785
* Tue May 16 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-26
- smartcard-auth: modify the content to remove unnecessary modules. Resolves: #1983683
* 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
* Thu Jun 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-21
- pam_usertype: only use SYS_UID_MAX for system users. Resolves: #1949137
* Thu May 26 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-20
- faillock: load configuration from file. Resolves: #1978029
* Mon May 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-19
- Add the motd.d directories (empty) to silence warnings and to
provide proper ownership for them. Resolves: #2014458
* Thu May 19 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-18
- pam_motd: fix memory leak. Resolves: #2014458
* Tue May 17 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-17
- pam_keyinit: thread-safe implementation. Resolves: #1997969
- pam_motd: support multiple motd paths specified, with filename overrides. Resolves: #2014458
* Fri Jan 28 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-16
- pam_limits: "Unlimited" is not a valid value for RLIMIT_NOFILE. Resolves: #2047655