Compare commits

..

No commits in common. 'c9' and 'i8c-beta' have entirely different histories.
c9 ... i8c-beta

4
.gitignore vendored

@ -1,2 +1,2 @@
SOURCES/Linux-PAM-1.5.1.tar.xz
SOURCES/pam-redhat-1.1.4.tar.bz2
SOURCES/Linux-PAM-1.3.1.tar.xz
SOURCES/pam-redhat-0.99.11.tar.bz2

@ -1,2 +1,2 @@
ad43b7fbdfdd38886fdf27e098b49f2db1c2a13d SOURCES/Linux-PAM-1.5.1.tar.xz
bf661c44f34c2d4d34eaee695b36e638f4d44ba8 SOURCES/pam-redhat-1.1.4.tar.bz2
e89b6d279c9bf8cb495dfc0b3f3931eb50f818e9 SOURCES/Linux-PAM-1.3.1.tar.xz
42206fe8319723ef23ab646b2eab496c86de3f5b SOURCES/pam-redhat-0.99.11.tar.bz2

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iD8DBQBa/r62bRp/BS5ZJLsRArnKAJ9pGaJHpsEsbOVa5dBQLHYC4DhPuACeJNrg
+DaNc8W13E4Z2ZEUSsgUGe4=
=aSTW
-----END PGP SIGNATURE-----

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIcBAABCAAGBQJfvo0CAAoJEKgEH6g54W42L+0P/19bgVH4cRd7ONZLwYvWvWlQ
NXkjwn26MEXElWESlKnQQz08W5QASWCz3vgAn9NGDmS+lJ38i4Li4aGpn3COPE2g
BAN9LEaAErK60b3ZkWwDEARDs1JntA1vUuuHx0EoLEMtFEeU20h5PPMrsDwu7LGF
sD6KYdM6TWLMXcRybqGOeWmWxfp8S8MVNwVN3C3q0aVIOMxky0i4rzCL7zRTJztQ
q7FaX2xrTGfUiAI7smT/KGoK7pbQTzZtoR67uE/2WZ4bSyWMZcuDkt16WP/L6x9v
c5DnVaLazM9xYUAOn4tlPiG8LLmfXo1MjD+KOS9byAx+uTij3avxaC/vv0BDcATH
jywxH8iTPkvYXP0uJIa4Gbs1qi3vNZn+gaQt/T+rCVNo3dfFZZxBvLbTQ8AN1hKr
MnoQbIQh0buuSuwmAxF0EDIefX3bDCurKOTQrRajK7huFm0w2NgBqL8WR8f1Wmm9
mGSdKuVpWSk5uEygCUFOfwviYbi1I1K2Dmo3TsLBgNPKvAF3LAGJC7KzD+Q+Nmos
XBOljilcAfdJ7t2P8W7xTSMEnXu7nI1TM+Er80ukfu0fipJEP0xyi+XWh+2n0Bx+
3wwt8fSL7rmI4I4l6GRb3Jk/Gq1bKy956tgm3TE6gXTXVGZqNs0E28rNRURXDqZu
XrjVwhlpsH/Auk17hU65
=E0ev
-----END PGP SIGNATURE-----

@ -1,144 +0,0 @@
From 244b46908df930626535c0cd7c2867407fe8714a Mon Sep 17 00:00:00 2001
From: Thorsten Kukuk <kukuk@suse.com>
Date: Tue, 14 Feb 2023 14:57:40 +0100
Subject: [PATCH] libpam: use getlogin() from libc and not utmp
utmp uses 32bit time_t for compatibility with 32bit userland on some
64bit systems and is thus not Y2038 safe. Use getlogin() from libc
which avoids using utmp and is more safe than the old utmp-based
implementation by using /proc/self/loginuid.
* libpam/pam_modutil_getlogin.c: Use getlogin() instead of parsing utmp
---
libpam/pam_modutil_getlogin.c | 52 ++++++++---------------------------
1 file changed, 11 insertions(+), 41 deletions(-)
diff --git a/libpam/pam_modutil_getlogin.c b/libpam/pam_modutil_getlogin.c
index 04a20fd8..633dd676 100644
--- a/libpam/pam_modutil_getlogin.c
+++ b/libpam/pam_modutil_getlogin.c
@@ -10,7 +10,6 @@
#include <stdlib.h>
#include <unistd.h>
-#include <utmp.h>
#define _PAMMODUTIL_GETLOGIN "_pammodutil_getlogin"
@@ -19,62 +18,33 @@ pam_modutil_getlogin(pam_handle_t *pamh)
{
int status;
const void *logname;
- const void *void_curr_tty;
- const char *curr_tty;
char *curr_user;
- struct utmp *ut, line;
+ size_t curr_user_len;
status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN, &logname);
if (status == PAM_SUCCESS) {
return logname;
}
- status = pam_get_item(pamh, PAM_TTY, &void_curr_tty);
- if ((status != PAM_SUCCESS) || (void_curr_tty == NULL))
- curr_tty = ttyname(0);
- else
- curr_tty = (const char*)void_curr_tty;
-
- if (curr_tty == NULL) {
- return NULL;
- }
-
- if (curr_tty[0] == '/') { /* full path */
- const char *t;
- curr_tty++;
- if ((t = strchr(curr_tty, '/')) != NULL) {
- curr_tty = t + 1;
- }
+ logname = getlogin();
+ if (logname == NULL) {
+ return NULL;
}
- logname = NULL;
- setutent();
- strncpy(line.ut_line, curr_tty, sizeof(line.ut_line));
-
- if ((ut = getutline(&line)) == NULL) {
- goto clean_up_and_go_home;
- }
-
- curr_user = calloc(sizeof(line.ut_user)+1, 1);
+ curr_user_len = strlen(logname)+1;
+ curr_user = calloc(curr_user_len, 1);
if (curr_user == NULL) {
- goto clean_up_and_go_home;
+ return NULL;
}
- strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user));
- /* calloc already zeroed the memory */
+ memcpy(curr_user, logname, curr_user_len);
status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
pam_modutil_cleanup);
if (status != PAM_SUCCESS) {
- free(curr_user);
- goto clean_up_and_go_home;
+ free(curr_user);
+ return NULL;
}
- logname = curr_user;
-
-clean_up_and_go_home:
-
- endutent();
-
- return logname;
+ return curr_user;
}
--
2.43.0
From f26d873435be9f35fa7953493cc07a9bc4e31876 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Sat, 18 Feb 2023 14:37:04 +0100
Subject: [PATCH] libpam: simplify string copying using strdup
---
libpam/pam_modutil_getlogin.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libpam/pam_modutil_getlogin.c b/libpam/pam_modutil_getlogin.c
index 633dd676..2e7a0116 100644
--- a/libpam/pam_modutil_getlogin.c
+++ b/libpam/pam_modutil_getlogin.c
@@ -19,7 +19,6 @@ pam_modutil_getlogin(pam_handle_t *pamh)
int status;
const void *logname;
char *curr_user;
- size_t curr_user_len;
status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN, &logname);
if (status == PAM_SUCCESS) {
@@ -31,14 +30,11 @@ pam_modutil_getlogin(pam_handle_t *pamh)
return NULL;
}
- curr_user_len = strlen(logname)+1;
- curr_user = calloc(curr_user_len, 1);
+ curr_user = strdup(logname);
if (curr_user == NULL) {
return NULL;
}
- memcpy(curr_user, logname, curr_user_len);
-
status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
pam_modutil_cleanup);
if (status != PAM_SUCCESS) {
--
2.43.0

@ -0,0 +1,26 @@
diff -up Linux-PAM-1.1.0/modules/pam_console/console.handlers.nochmod Linux-PAM-1.1.0/modules/pam_console/console.handlers
--- Linux-PAM-1.1.0/modules/pam_console/console.handlers.nochmod 2008-12-16 13:37:52.000000000 +0100
+++ Linux-PAM-1.1.0/modules/pam_console/console.handlers 2009-09-01 17:20:08.000000000 +0200
@@ -15,5 +15,3 @@
# touch unlock wait /var/run/console-unlocked
console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]+\.[0-9]+ :[0-9]+
-/sbin/pam_console_apply lock logfail wait -t tty -s
-/sbin/pam_console_apply unlock logfail wait -r -t tty -s
diff -up Linux-PAM-1.1.0/modules/pam_console/Makefile.am.nochmod Linux-PAM-1.1.0/modules/pam_console/Makefile.am
--- Linux-PAM-1.1.0/modules/pam_console/Makefile.am.nochmod 2008-12-16 13:37:52.000000000 +0100
+++ Linux-PAM-1.1.0/modules/pam_console/Makefile.am 2009-09-01 17:42:47.000000000 +0200
@@ -38,7 +38,6 @@ sbin_PROGRAMS = pam_console_apply
secureconf_DATA = console.perms console.handlers
-permsd_DATA = 50-default.perms
FLEX_OPTS = -Cr
BISON_OPTS = -d
@@ -62,4 +61,5 @@ configfile.c: configfile.tab.c configfil
install-data-local:
mkdir -p $(DESTDIR)$(secureconfdir)/console.apps
+ mkdir -p $(DESTDIR)$(permsddir)
mkdir -m $(LOCKMODE) -p -p $(DESTDIR)$(LOCKDIR)

@ -0,0 +1,12 @@
diff -up Linux-PAM-1.1.0/modules/Makefile.am.notally Linux-PAM-1.1.0/modules/Makefile.am
--- Linux-PAM-1.1.0/modules/Makefile.am.notally 2009-07-27 17:39:25.000000000 +0200
+++ Linux-PAM-1.1.0/modules/Makefile.am 2009-09-01 17:40:16.000000000 +0200
@@ -10,7 +10,7 @@ SUBDIRS = pam_access pam_cracklib pam_de
pam_mkhomedir pam_motd pam_namespace pam_nologin \
pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \
pam_selinux pam_sepermit pam_shells pam_stress \
- pam_succeed_if pam_tally pam_tally2 pam_time pam_timestamp \
+ pam_succeed_if pam_time pam_timestamp \
pam_tty_audit pam_umask \
pam_unix pam_userdb pam_warn pam_wheel pam_xauth

@ -0,0 +1,12 @@
diff -up Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c.errmsg Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c
--- Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c.errmsg 2008-12-16 13:37:52.000000000 +0100
+++ Linux-PAM-1.1.1/modules/pam_console/pam_console_apply.c 2014-06-19 13:23:28.948343737 +0200
@@ -65,7 +65,7 @@ parse_files(void)
on system locale */
oldlocale = setlocale(LC_COLLATE, "C");
- rc = glob(PERMS_GLOB, GLOB_NOCHECK, NULL, &globbuf);
+ rc = glob(PERMS_GLOB, 0, NULL, &globbuf);
setlocale(LC_COLLATE, oldlocale);
if (rc)
return;

@ -0,0 +1,27 @@
diff -up pam/modules/pam_env/pam_env.c.nouserenv pam/modules/pam_env/pam_env.c
--- pam/modules/pam_env/pam_env.c.nouserenv 2010-10-20 09:59:30.000000000 +0200
+++ pam/modules/pam_env/pam_env.c 2010-11-01 14:42:01.000000000 +0100
@@ -10,7 +10,7 @@
#define DEFAULT_READ_ENVFILE 1
#define DEFAULT_USER_ENVFILE ".pam_environment"
-#define DEFAULT_USER_READ_ENVFILE 1
+#define DEFAULT_USER_READ_ENVFILE 0
#include "config.h"
diff -up pam/modules/pam_env/pam_env.8.xml.nouserenv pam/modules/pam_env/pam_env.8.xml
--- pam/modules/pam_env/pam_env.8.xml.nouserenv 2010-10-20 09:59:30.000000000 +0200
+++ pam/modules/pam_env/pam_env.8.xml 2010-11-01 14:42:01.000000000 +0100
@@ -147,7 +147,10 @@
<listitem>
<para>
Turns on or off the reading of the user specific environment
- file. 0 is off, 1 is on. By default this option is on.
+ file. 0 is off, 1 is on. By default this option is off as user
+ supplied environment variables in the PAM environment could affect
+ behavior of subsequent modules in the stack without the consent
+ of the system administrator.
</para>
</listitem>
</varlistentry>

@ -0,0 +1,20 @@
diff -up Linux-PAM-1.1.6/modules/pam_limits/limits.conf.limits Linux-PAM-1.1.6/modules/pam_limits/limits.conf
--- Linux-PAM-1.1.6/modules/pam_limits/limits.conf.limits 2012-08-15 13:08:43.000000000 +0200
+++ Linux-PAM-1.1.6/modules/pam_limits/limits.conf 2013-03-14 16:43:37.615087671 +0100
@@ -1,5 +1,16 @@
# /etc/security/limits.conf
#
+#This file sets the resource limits for the users logged in via PAM.
+#It does not affect resource limits of the system services.
+#
+#Also note that configuration files in /etc/security/limits.d directory,
+#which are read in alphabetical order, override the settings in this
+#file in case the domain is the same or more specific.
+#That means for example that setting a limit for wildcard domain here
+#can be overriden with a wildcard setting in a config file in the
+#subdirectory, but a user specific setting here can be overriden only
+#with a user specific setting in the subdirectory.
+#
#Each line describes a limit for a user in the form:
#
#<domain> <type> <item> <value>

@ -0,0 +1,31 @@
diff -up Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c.audit-user-mgmt Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c
--- Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c.audit-user-mgmt 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_tally2/pam_tally2.c 2014-10-17 12:09:12.965490940 +0200
@@ -997,9 +997,9 @@ main( int argc UNUSED, char **argv )
#ifdef HAVE_LIBAUDIT
char buf[64];
int audit_fd = audit_open();
- snprintf(buf, sizeof(buf), "pam_tally2 uid=%u reset=%hu", uid, cline_reset);
- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
- buf, NULL, NULL, ttyname(STDIN_FILENO), 1);
+ snprintf(buf, sizeof(buf), "pam_tally2 reset=%hu", cline_reset);
+ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
+ buf, NULL, uid, NULL, NULL, ttyname(STDIN_FILENO), 1);
if (audit_fd >=0)
close(audit_fd);
#endif
@@ -1040,11 +1040,10 @@ main( int argc UNUSED, char **argv )
}
else if ( !cline_reset ) {
#ifdef HAVE_LIBAUDIT
- char buf[64];
int audit_fd = audit_open();
- snprintf(buf, sizeof(buf), "pam_tally2 uid=all reset=0");
- audit_log_user_message(audit_fd, AUDIT_USER_ACCT,
- buf, NULL, NULL, ttyname(STDIN_FILENO), 1);
+ audit_log_acct_message(audit_fd, AUDIT_USER_MGMT, NULL,
+ "pam_tally2-reset-all-accts reset=0", "*", -1,
+ NULL, NULL, ttyname(STDIN_FILENO), 1);
if (audit_fd >=0)
close(audit_fd);
#endif

@ -0,0 +1,88 @@
diff -up Linux-PAM-1.1.8/modules/pam_console/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_console/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_console/Makefile.am.relro 2014-08-13 16:02:49.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_console/Makefile.am 2014-09-10 17:14:33.245554314 +0200
@@ -33,6 +33,8 @@ pam_console_la_LIBADD = -L$(top_builddir
pam_console_apply_LDADD = -L$(top_builddir)/libpam -lpam
+pam_console_apply_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+
securelib_LTLIBRARIES = pam_console.la
sbin_PROGRAMS = pam_console_apply
@@ -47,7 +49,7 @@ pam_console_apply_SOURCES = pam_console_
configfile.c configfile.h hashtable.c hashtable.h hashtable_private.h
pam_console_la_CFLAGS = $(AM_CFLAGS)
-pam_console_apply_CFLAGS = $(AM_CFLAGS)
+pam_console_apply_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
configfile.tab.c: configfile.y
$(YACC) $(BISON_OPTS) -o $@ -p _pc_yy $<
diff -up Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am.relro 2014-09-10 17:17:20.273401344 +0200
+++ Linux-PAM-1.1.8/modules/pam_filter/upperLOWER/Makefile.am 2014-09-10 17:17:07.857115369 +0200
@@ -9,7 +9,7 @@ securelibfilterdir = $(SECUREDIR)/pam_fi
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-I$(srcdir)/.. @PIE_CFLAGS@
-AM_LDFLAGS = @PIE_LDFLAGS@
+AM_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
LDADD = $(top_builddir)/libpam/libpam.la
securelibfilter_PROGRAMS = upperLOWER
diff -up Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_mkhomedir/Makefile.am 2014-09-10 17:18:42.922304935 +0200
@@ -30,6 +30,8 @@ endif
sbin_PROGRAMS = mkhomedir_helper
mkhomedir_helper_SOURCES = mkhomedir_helper.c
+mkhomedir_helper_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+mkhomedir_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
mkhomedir_helper_LDADD = $(top_builddir)/libpam/libpam.la
if ENABLE_REGENERATE_MAN
diff -up Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_tally2/Makefile.am 2014-09-10 17:22:04.339944040 +0200
@@ -26,6 +26,8 @@ if HAVE_VERSIONING
pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
+pam_tally2_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
+pam_tally2_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
pam_tally2_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT)
securelib_LTLIBRARIES = pam_tally2.la
diff -up Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_timestamp/Makefile.am 2014-08-13 16:02:49.906688139 +0200
@@ -36,7 +36,7 @@ pam_timestamp_la_CFLAGS = $(AM_CFLAGS)
pam_timestamp_check_SOURCES = pam_timestamp_check.c
pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@
pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la
-pam_timestamp_check_LDFLAGS = @PIE_LDFLAGS@
+pam_timestamp_check_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c
hmacfile_LDADD = $(top_builddir)/libpam/libpam.la
diff -up Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro Linux-PAM-1.1.8/modules/pam_unix/Makefile.am
--- Linux-PAM-1.1.8/modules/pam_unix/Makefile.am.relro 2013-06-18 16:11:21.000000000 +0200
+++ Linux-PAM-1.1.8/modules/pam_unix/Makefile.am 2014-08-13 16:02:49.906688139 +0200
@@ -55,13 +55,13 @@ bigcrypt_LDADD = @LIBCRYPT@
unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \
passverify.c
unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\"
-unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@
+unix_chkpwd_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@
unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \
passverify.c
unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\"
-unix_update_LDFLAGS = @PIE_LDFLAGS@
+unix_update_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
if ENABLE_REGENERATE_MAN

@ -0,0 +1,23 @@
diff -up Linux-PAM-1.2.0/configure.ac.redhat-modules Linux-PAM-1.2.0/configure.ac
--- Linux-PAM-1.2.0/configure.ac.redhat-modules 2015-03-25 16:50:10.000000000 +0100
+++ Linux-PAM-1.2.0/configure.ac 2015-05-15 15:46:50.996074677 +0200
@@ -616,6 +616,8 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
libpam_misc/Makefile conf/Makefile conf/pam_conv1/Makefile \
po/Makefile.in \
modules/Makefile \
+ modules/pam_chroot/Makefile modules/pam_console/Makefile \
+ modules/pam_postgresok/Makefile \
modules/pam_access/Makefile modules/pam_cracklib/Makefile \
modules/pam_debug/Makefile modules/pam_deny/Makefile \
modules/pam_echo/Makefile modules/pam_env/Makefile \
diff -up Linux-PAM-1.2.0/modules/Makefile.am.redhat-modules Linux-PAM-1.2.0/modules/Makefile.am
--- Linux-PAM-1.2.0/modules/Makefile.am.redhat-modules 2015-03-24 13:02:32.000000000 +0100
+++ Linux-PAM-1.2.0/modules/Makefile.am 2015-05-15 15:46:50.995074654 +0200
@@ -3,6 +3,7 @@
#
SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \
+ pam_chroot pam_console pam_postgresok \
pam_env pam_exec pam_faildelay pam_filter pam_ftp \
pam_group pam_issue pam_keyinit pam_lastlog pam_limits \
pam_listfile pam_localuser pam_loginuid pam_mail \

@ -0,0 +1,73 @@
diff -up Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml.no-fallback Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml
--- Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml.no-fallback 2015-04-27 16:38:03.000000000 +0200
+++ Linux-PAM-1.2.0/modules/pam_unix/pam_unix.8.xml 2015-05-15 15:54:21.524440864 +0200
@@ -284,11 +284,10 @@
<listitem>
<para>
When a user changes their password next,
- encrypt it with the SHA256 algorithm. If the
- SHA256 algorithm is not known to the <citerefentry>
+ encrypt it with the SHA256 algorithm. The
+ SHA256 algorithm must be supported by the <citerefentry>
<refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
- </citerefentry> function,
- fall back to MD5.
+ </citerefentry> function.
</para>
</listitem>
</varlistentry>
@@ -299,11 +298,10 @@
<listitem>
<para>
When a user changes their password next,
- encrypt it with the SHA512 algorithm. If the
- SHA512 algorithm is not known to the <citerefentry>
+ encrypt it with the SHA512 algorithm. The
+ SHA512 algorithm must be supported by the <citerefentry>
<refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
- </citerefentry> function,
- fall back to MD5.
+ </citerefentry> function.
</para>
</listitem>
</varlistentry>
@@ -314,11 +312,10 @@
<listitem>
<para>
When a user changes their password next,
- encrypt it with the blowfish algorithm. If the
- blowfish algorithm is not known to the <citerefentry>
+ encrypt it with the blowfish algorithm. The
+ blowfish algorithm must be supported by the <citerefentry>
<refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
- </citerefentry> function,
- fall back to MD5.
+ </citerefentry> function.
</para>
</listitem>
</varlistentry>
diff -up Linux-PAM-1.2.0/modules/pam_unix/passverify.c.no-fallback Linux-PAM-1.2.0/modules/pam_unix/passverify.c
--- Linux-PAM-1.2.0/modules/pam_unix/passverify.c.no-fallback 2015-05-15 15:54:21.525440887 +0200
+++ Linux-PAM-1.2.0/modules/pam_unix/passverify.c 2015-05-15 15:57:23.138613273 +0200
@@ -437,10 +437,9 @@ PAMH_ARG_DECL(char * create_password_has
sp = crypt(password, salt);
#endif
if (!sp || strncmp(algoid, sp, strlen(algoid)) != 0) {
- /* libxcrypt/libc doesn't know the algorithm, use MD5 */
+ /* libxcrypt/libc doesn't know the algorithm, error out */
pam_syslog(pamh, LOG_ERR,
- "Algo %s not supported by the crypto backend, "
- "falling back to MD5\n",
+ "Algo %s not supported by the crypto backend.\n",
on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
@@ -450,7 +449,7 @@ PAMH_ARG_DECL(char * create_password_has
#ifdef HAVE_CRYPT_R
free(cdata);
#endif
- return crypt_md5_wrapper(password);
+ return NULL;
}
sp = x_strdup(sp);
#ifdef HAVE_CRYPT_R

@ -0,0 +1,9 @@
diff -up Linux-PAM-1.2.1/modules/pam_console/console.handlers.devname Linux-PAM-1.2.1/modules/pam_console/console.handlers
--- Linux-PAM-1.2.1/modules/pam_console/console.handlers.devname 2015-10-16 14:15:48.000000000 +0200
+++ Linux-PAM-1.2.1/modules/pam_console/console.handlers 2016-02-05 17:47:26.056787517 +0100
@@ -14,4 +14,4 @@
# echo lock wait Locking console for user on tty
# touch unlock wait /var/run/console-unlocked
-console consoledevs tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]+\.[0-9]+ :[0-9]+
+console consoledevs /dev/tty[0-9][0-9]* tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]+\.[0-9]+ :[0-9]+

@ -0,0 +1,133 @@
diff -up Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c.admin-group Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c
--- Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c.admin-group 2016-04-04 16:37:38.696260359 +0200
+++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.c 2017-08-21 16:40:01.624706864 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Tomas Mraz <tmraz@redhat.com>
+ * Copyright (c) 2010, 2017 Tomas Mraz <tmraz@redhat.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -78,9 +78,11 @@ struct options {
unsigned int root_unlock_time;
const char *dir;
const char *user;
+ const char *admin_group;
int failures;
uint64_t latest_time;
uid_t uid;
+ int is_admin;
uint64_t now;
};
@@ -152,6 +154,9 @@ args_parse(pam_handle_t *pamh, int argc,
opts->root_unlock_time = temp;
}
}
+ else if (strncmp(argv[i], "admin_group=", 12) == 0) {
+ opts->admin_group = argv[i] + 12;
+ }
else if (strcmp(argv[i], "preauth") == 0) {
opts->action = FAILLOCK_ACTION_PREAUTH;
}
@@ -209,6 +214,17 @@ static int get_pam_user(pam_handle_t *pa
}
opts->user = user;
opts->uid = pwd->pw_uid;
+
+ if (pwd->pw_uid == 0) {
+ opts->is_admin = 1;
+ return PAM_SUCCESS;
+ }
+
+ if (opts->admin_group && *opts->admin_group) {
+ opts->is_admin = pam_modutil_user_in_group_uid_nam(pamh,
+ pwd->pw_uid, opts->admin_group);
+ }
+
return PAM_SUCCESS;
}
@@ -239,7 +255,7 @@ check_tally(pam_handle_t *pamh, struct o
return PAM_SYSTEM_ERR;
}
- if (opts->uid == 0 && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) {
+ if (opts->is_admin && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) {
return PAM_SUCCESS;
}
@@ -262,13 +278,9 @@ check_tally(pam_handle_t *pamh, struct o
opts->failures = failures;
- if (opts->uid == 0 && !(opts->flags & FAILLOCK_FLAG_DENY_ROOT)) {
- return PAM_SUCCESS;
- }
-
if (opts->deny && failures >= opts->deny) {
- if ((opts->uid && opts->unlock_time && latest_time + opts->unlock_time < opts->now) ||
- (!opts->uid && opts->root_unlock_time && latest_time + opts->root_unlock_time < opts->now)) {
+ if ((!opts->is_admin && opts->unlock_time && latest_time + opts->unlock_time < opts->now) ||
+ (opts->is_admin && opts->root_unlock_time && latest_time + opts->root_unlock_time < opts->now)) {
#ifdef HAVE_LIBAUDIT
if (opts->action != FAILLOCK_ACTION_PREAUTH) { /* do not audit in preauth */
char buf[64];
@@ -401,7 +413,7 @@ write_tally(pam_handle_t *pamh, struct o
audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf,
NULL, NULL, NULL, 1);
- if (opts->uid != 0 || (opts->flags & FAILLOCK_FLAG_DENY_ROOT)) {
+ if (!opts->is_admin || (opts->flags & FAILLOCK_FLAG_DENY_ROOT)) {
audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_LOCK, buf,
NULL, NULL, NULL, 1);
}
@@ -425,11 +437,11 @@ faillock_message(pam_handle_t *pamh, str
int64_t left;
if (!(opts->flags & FAILLOCK_FLAG_SILENT)) {
- if (opts->uid) {
- left = opts->latest_time + opts->unlock_time - opts->now;
+ if (opts->is_admin) {
+ left = opts->latest_time + opts->root_unlock_time - opts->now;
}
else {
- left = opts->latest_time + opts->root_unlock_time - opts->now;
+ left = opts->latest_time + opts->unlock_time - opts->now;
}
if (left > 0) {
diff -up Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml.admin-group Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml
--- Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml.admin-group 2016-05-06 15:24:10.328281818 +0200
+++ Linux-PAM-1.3.0/modules/pam_faillock/pam_faillock.8.xml 2017-08-21 16:16:09.448033843 +0200
@@ -40,6 +40,9 @@
root_unlock_time=<replaceable>n</replaceable>
</arg>
<arg choice="opt">
+ admin_group=<replaceable>name</replaceable>
+ </arg>
+ <arg choice="opt">
audit
</arg>
<arg choice="opt">
@@ -243,6 +246,20 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>admin_group=<replaceable>name</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ If a group name is specified with this option, members
+ of the group will be handled by this module the same as
+ the root account (the options <option>even_deny_root></option>
+ and <option>root_unlock_time</option> will apply to them.
+ By default the option is not set.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,806 @@
diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am
--- Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am.pwhhelper 2016-03-24 12:45:42.000000000 +0100
+++ Linux-PAM-1.3.0/modules/pam_pwhistory/Makefile.am 2016-05-06 15:18:42.307637933 +0200
@@ -1,5 +1,6 @@
#
# Copyright (c) 2008, 2009 Thorsten Kukuk <kukuk@suse.de>
+# Copyright (c) 2013 Red Hat, Inc.
#
CLEANFILES = *~
@@ -9,25 +10,34 @@ EXTRA_DIST = README $(MANS) $(XMLS) tst-
TESTS = tst-pam_pwhistory
-man_MANS = pam_pwhistory.8
+man_MANS = pam_pwhistory.8 pwhistory_helper.8
-XMLS = README.xml pam_pwhistory.8.xml
+XMLS = README.xml pam_pwhistory.8.xml pwhistory_helper.8.xml
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
-AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
-AM_LDFLAGS = -no-undefined -avoid-version -module
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ -DPWHISTORY_HELPER=\"$(sbindir)/pwhistory_helper\"
+
+pam_pwhistory_la_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
- AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+ pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
noinst_HEADERS = opasswd.h
securelib_LTLIBRARIES = pam_pwhistory.la
-pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
+pam_pwhistory_la_CFLAGS = $(AM_CFLAGS)
+pam_pwhistory_la_LIBADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@ @LIBSELINUX@
pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c
+sbin_PROGRAMS = pwhistory_helper
+pwhistory_helper_CFLAGS = $(AM_CFLAGS) -DHELPER_COMPILE=\"pwhistory_helper\" @PIE_CFLAGS@
+pwhistory_helper_SOURCES = pwhistory_helper.c opasswd.c
+pwhistory_helper_LDFLAGS = -Wl,-z,now @PIE_LDFLAGS@
+pwhistory_helper_LDADD = $(top_builddir)/libpam/libpam.la @LIBCRYPT@
+
if ENABLE_REGENERATE_MAN
noinst_DATA = README
README: pam_pwhistory.8.xml
diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c
--- Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c.pwhhelper 2016-03-24 12:45:42.000000000 +0100
+++ Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.c 2016-05-06 15:18:42.307637933 +0200
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
+ * Copyright (c) 2013 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -38,6 +39,7 @@
#endif
#include <pwd.h>
+#include <shadow.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
@@ -47,6 +49,7 @@
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
+#include <stdarg.h>
#include <sys/stat.h>
#if defined (HAVE_XCRYPT_H)
@@ -55,7 +58,14 @@
#include <crypt.h>
#endif
+#ifdef HELPER_COMPILE
+#define pam_modutil_getpwnam(h,n) getpwnam(n)
+#define pam_modutil_getspnam(h,n) getspnam(n)
+#define pam_syslog(h,a,...) helper_log_err(a,__VA_ARGS__)
+#else
+#include <security/pam_modutil.h>
#include <security/pam_ext.h>
+#endif
#include <security/pam_modules.h>
#include "opasswd.h"
@@ -76,6 +86,19 @@ typedef struct {
char *old_passwords;
} opwd;
+#ifdef HELPER_COMPILE
+void
+helper_log_err(int err, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ openlog(HELPER_COMPILE, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
+ vsyslog(err, format, args);
+ va_end(args);
+ closelog();
+}
+#endif
static int
parse_entry (char *line, opwd *data)
@@ -117,8 +140,8 @@ compare_password(const char *newpass, co
}
/* Check, if the new password is already in the opasswd file. */
-int
-check_old_pass (pam_handle_t *pamh, const char *user,
+PAMH_ARG_DECL(int
+check_old_pass, const char *user,
const char *newpass, int debug)
{
int retval = PAM_SUCCESS;
@@ -128,6 +151,11 @@ check_old_pass (pam_handle_t *pamh, cons
opwd entry;
int found = 0;
+#ifndef HELPER_COMPILE
+ if (SELINUX_ENABLED)
+ return PAM_PWHISTORY_RUN_HELPER;
+#endif
+
if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL)
{
if (errno != ENOENT)
@@ -213,9 +241,9 @@ check_old_pass (pam_handle_t *pamh, cons
return retval;
}
-int
-save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
- const char *oldpass, int howmany, int debug UNUSED)
+PAMH_ARG_DECL(int
+save_old_pass, const char *user,
+ int howmany, int debug UNUSED)
{
char opasswd_tmp[] = TMP_PASSWORDS_FILE;
struct stat opasswd_stat;
@@ -226,10 +254,35 @@ save_old_pass (pam_handle_t *pamh, const
char *buf = NULL;
size_t buflen = 0;
int found = 0;
+ struct passwd *pwd;
+ const char *oldpass;
+
+ pwd = pam_modutil_getpwnam (pamh, user);
+ if (pwd == NULL)
+ return PAM_USER_UNKNOWN;
if (howmany <= 0)
return PAM_SUCCESS;
+#ifndef HELPER_COMPILE
+ if (SELINUX_ENABLED)
+ return PAM_PWHISTORY_RUN_HELPER;
+#endif
+
+ if ((strcmp(pwd->pw_passwd, "x") == 0) ||
+ ((pwd->pw_passwd[0] == '#') &&
+ (pwd->pw_passwd[1] == '#') &&
+ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
+ {
+ struct spwd *spw = pam_modutil_getspnam (pamh, user);
+
+ if (spw == NULL)
+ return PAM_USER_UNKNOWN;
+ oldpass = spw->sp_pwdp;
+ }
+ else
+ oldpass = pwd->pw_passwd;
+
if (oldpass == NULL || *oldpass == '\0')
return PAM_SUCCESS;
@@ -452,7 +505,7 @@ save_old_pass (pam_handle_t *pamh, const
{
char *out;
- if (asprintf (&out, "%s:%d:1:%s\n", user, uid, oldpass) < 0)
+ if (asprintf (&out, "%s:%d:1:%s\n", user, pwd->pw_uid, oldpass) < 0)
{
retval = PAM_AUTHTOK_ERR;
if (oldpf)
diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h
--- Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h.pwhhelper 2016-03-24 12:45:42.000000000 +0100
+++ Linux-PAM-1.3.0/modules/pam_pwhistory/opasswd.h 2016-05-06 15:18:42.307637933 +0200
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Thorsten Kukuk <kukuk@suse.de>
+ * Copyright (c) 2013 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,10 +37,32 @@
#ifndef __OPASSWD_H__
#define __OPASSWD_H__
-extern int check_old_pass (pam_handle_t *pamh, const char *user,
- const char *newpass, int debug);
-extern int save_old_pass (pam_handle_t *pamh, const char *user,
- uid_t uid, const char *oldpass,
- int howmany, int debug);
+#define PAM_PWHISTORY_RUN_HELPER PAM_CRED_INSUFFICIENT
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#define SELINUX_ENABLED is_selinux_enabled()>0
+#else
+#define SELINUX_ENABLED 0
+#endif
+
+#ifdef HELPER_COMPILE
+#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__)
+#define PAMH_ARG(...) __VA_ARGS__
+#else
+#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__)
+#define PAMH_ARG(...) pamh, __VA_ARGS__
+#endif
+
+#ifdef HELPER_COMPILE
+void
+helper_log_err(int err, const char *format, ...);
+#endif
+
+PAMH_ARG_DECL(int
+check_old_pass, const char *user, const char *newpass, int debug);
+
+PAMH_ARG_DECL(int
+save_old_pass, const char *user, int howmany, int debug);
#endif /* __OPASSWD_H__ */
diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c
--- Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c.pwhhelper 2016-04-04 11:22:28.000000000 +0200
+++ Linux-PAM-1.3.0/modules/pam_pwhistory/pam_pwhistory.c 2016-05-06 15:19:31.610785512 +0200
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2008, 2012 Thorsten Kukuk
* Author: Thorsten Kukuk <kukuk@thkukuk.de>
+ * Copyright (c) 2013 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,10 +47,14 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <shadow.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
#include <security/pam_modules.h>
#include <security/pam_modutil.h>
@@ -59,6 +64,7 @@
#include "opasswd.h"
#define DEFAULT_BUFLEN 2048
+#define MAX_FD_NO 20000
struct options_t {
int debug;
@@ -102,6 +108,184 @@ parse_option (pam_handle_t *pamh, const
pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv);
}
+static int
+run_save_helper(pam_handle_t *pamh, const char *user,
+ int howmany, int debug)
+{
+ int retval, child;
+ struct sigaction newsa, oldsa;
+
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
+
+ child = fork();
+ if (child == 0)
+ {
+ int i = 0;
+ struct rlimit rlim;
+ int dummyfds[2];
+ static char *envp[] = { NULL };
+ char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
+
+ /* replace std file descriptors with a dummy pipe */
+ if (pipe2(dummyfds, O_NONBLOCK) == 0)
+ {
+ dup2(dummyfds[0], STDIN_FILENO);
+ dup2(dummyfds[1], STDOUT_FILENO);
+ dup2(dummyfds[1], STDERR_FILENO);
+ }
+
+ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0)
+ {
+ if (rlim.rlim_max >= MAX_FD_NO)
+ rlim.rlim_max = MAX_FD_NO;
+ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++)
+ {
+ if (i != dummyfds[0])
+ close(i);
+ }
+ }
+
+ /* exec binary helper */
+ args[0] = strdup(PWHISTORY_HELPER);
+ args[1] = strdup("save");
+ args[2] = x_strdup(user);
+ asprintf(&args[3], "%d", howmany);
+ asprintf(&args[4], "%d", debug);
+
+ execve(args[0], args, envp);
+
+ _exit(PAM_SYSTEM_ERR);
+ }
+ else if (child > 0)
+ {
+ /* wait for child */
+ int rc = 0;
+ rc = waitpid(child, &retval, 0); /* wait for helper to complete */
+ if (rc < 0)
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save waitpid returned %d: %m", rc);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else if (!WIFEXITED(retval))
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper save abnormal exit: %d", retval);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else
+ {
+ retval = WEXITSTATUS(retval);
+ }
+ }
+ else
+ {
+ retval = PAM_SYSTEM_ERR;
+ }
+
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
+
+ return retval;
+}
+
+static int
+run_check_helper(pam_handle_t *pamh, const char *user,
+ const char *newpass, int debug)
+{
+ int retval, child, fds[2];
+ struct sigaction newsa, oldsa;
+
+ /* create a pipe for the password */
+ if (pipe(fds) != 0)
+ return PAM_SYSTEM_ERR;
+
+ memset(&newsa, '\0', sizeof(newsa));
+ newsa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &newsa, &oldsa);
+
+ child = fork();
+ if (child == 0)
+ {
+ int i = 0;
+ struct rlimit rlim;
+ int dummyfds[2];
+ static char *envp[] = { NULL };
+ char *args[] = { NULL, NULL, NULL, NULL, NULL };
+
+ /* reopen stdin as pipe */
+ dup2(fds[0], STDIN_FILENO);
+
+ /* replace std file descriptors with a dummy pipe */
+ if (pipe2(dummyfds, O_NONBLOCK) == 0)
+ {
+ dup2(dummyfds[1], STDOUT_FILENO);
+ dup2(dummyfds[1], STDERR_FILENO);
+ }
+
+ if (getrlimit(RLIMIT_NOFILE,&rlim) == 0)
+ {
+ if (rlim.rlim_max >= MAX_FD_NO)
+ rlim.rlim_max = MAX_FD_NO;
+ for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++)
+ {
+ if (i != dummyfds[0])
+ close(i);
+ }
+ }
+
+ /* exec binary helper */
+ args[0] = strdup(PWHISTORY_HELPER);
+ args[1] = strdup("check");
+ args[2] = x_strdup(user);
+ asprintf(&args[3], "%d", debug);
+
+ execve(args[0], args, envp);
+
+ _exit(PAM_SYSTEM_ERR);
+ }
+ else if (child > 0)
+ {
+ /* wait for child */
+ int rc = 0;
+ if (newpass == NULL)
+ newpass = "";
+
+ /* send the password to the child */
+ if (write(fds[1], newpass, strlen(newpass)+1) == -1)
+ {
+ pam_syslog(pamh, LOG_ERR, "Cannot send password to helper: %m");
+ retval = PAM_SYSTEM_ERR;
+ }
+ newpass = NULL;
+ close(fds[0]); /* close here to avoid possible SIGPIPE above */
+ close(fds[1]);
+ rc = waitpid(child, &retval, 0); /* wait for helper to complete */
+ if (rc < 0)
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check waitpid returned %d: %m", rc);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else if (!WIFEXITED(retval))
+ {
+ pam_syslog(pamh, LOG_ERR, "pwhistory_helper check abnormal exit: %d", retval);
+ retval = PAM_SYSTEM_ERR;
+ }
+ else
+ {
+ retval = WEXITSTATUS(retval);
+ }
+ }
+ else
+ {
+ close(fds[0]);
+ close(fds[1]);
+ retval = PAM_SYSTEM_ERR;
+ }
+
+ sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */
+
+ return retval;
+}
/* This module saves the current crypted password in /etc/security/opasswd
and then compares the new password with all entries in this file. */
@@ -109,7 +293,6 @@ parse_option (pam_handle_t *pamh, const
int
pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- struct passwd *pwd;
const char *newpass;
const char *user;
int retval, tries;
@@ -154,31 +337,13 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
return PAM_SUCCESS;
}
- pwd = pam_modutil_getpwnam (pamh, user);
- if (pwd == NULL)
- return PAM_USER_UNKNOWN;
-
- if ((strcmp(pwd->pw_passwd, "x") == 0) ||
- ((pwd->pw_passwd[0] == '#') &&
- (pwd->pw_passwd[1] == '#') &&
- (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)))
- {
- struct spwd *spw = pam_modutil_getspnam (pamh, user);
- if (spw == NULL)
- return PAM_USER_UNKNOWN;
+ retval = save_old_pass (pamh, user, options.remember, options.debug);
- retval = save_old_pass (pamh, user, pwd->pw_uid, spw->sp_pwdp,
- options.remember, options.debug);
- if (retval != PAM_SUCCESS)
- return retval;
- }
- else
- {
- retval = save_old_pass (pamh, user, pwd->pw_uid, pwd->pw_passwd,
- options.remember, options.debug);
- if (retval != PAM_SUCCESS)
- return retval;
- }
+ if (retval == PAM_PWHISTORY_RUN_HELPER)
+ retval = run_save_helper(pamh, user, options.remember, options.debug);
+
+ if (retval != PAM_SUCCESS)
+ return retval;
newpass = NULL;
tries = 0;
@@ -207,8 +372,11 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
if (options.debug)
pam_syslog (pamh, LOG_DEBUG, "check against old password file");
- if (check_old_pass (pamh, user, newpass,
- options.debug) != PAM_SUCCESS)
+ retval = check_old_pass (pamh, user, newpass, options.debug);
+ if (retval == PAM_PWHISTORY_RUN_HELPER)
+ retval = run_check_helper(pamh, user, newpass, options.debug);
+
+ if (retval != PAM_SUCCESS)
{
if (getuid() || options.enforce_for_root ||
(flags & PAM_CHANGE_EXPIRED_AUTHTOK))
diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c
--- Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c.pwhhelper 2016-05-06 15:18:42.308637957 +0200
+++ Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.c 2016-05-06 15:18:42.308637957 +0200
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013 Red Hat, Inc.
+ * Author: Tomas Mraz <tmraz@redhat.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <security/_pam_types.h>
+#include <security/_pam_macros.h>
+#include "opasswd.h"
+
+#define MAXPASS 200
+
+static void
+su_sighandler(int sig)
+{
+#ifndef SA_RESETHAND
+ /* emulate the behaviour of the SA_RESETHAND flag */
+ if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) {
+ struct sigaction sa;
+ memset(&sa, '\0', sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ sigaction(sig, &sa, NULL);
+ }
+#endif
+ if (sig > 0) {
+ _exit(sig);
+ }
+}
+
+static void
+setup_signals(void)
+{
+ struct sigaction action; /* posix signal structure */
+
+ /*
+ * Setup signal handlers
+ */
+ (void) memset((void *) &action, 0, sizeof(action));
+ action.sa_handler = su_sighandler;
+#ifdef SA_RESETHAND
+ action.sa_flags = SA_RESETHAND;
+#endif
+ (void) sigaction(SIGILL, &action, NULL);
+ (void) sigaction(SIGTRAP, &action, NULL);
+ (void) sigaction(SIGBUS, &action, NULL);
+ (void) sigaction(SIGSEGV, &action, NULL);
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ (void) sigaction(SIGTERM, &action, NULL);
+ (void) sigaction(SIGHUP, &action, NULL);
+ (void) sigaction(SIGINT, &action, NULL);
+ (void) sigaction(SIGQUIT, &action, NULL);
+}
+
+static int
+read_passwords(int fd, int npass, char **passwords)
+{
+ int rbytes = 0;
+ int offset = 0;
+ int i = 0;
+ char *pptr;
+ while (npass > 0)
+ {
+ rbytes = read(fd, passwords[i]+offset, MAXPASS-offset);
+
+ if (rbytes < 0)
+ {
+ if (errno == EINTR) continue;
+ break;
+ }
+ if (rbytes == 0)
+ break;
+
+ while (npass > 0 && (pptr=memchr(passwords[i]+offset, '\0', rbytes))
+ != NULL)
+ {
+ rbytes -= pptr - (passwords[i]+offset) + 1;
+ i++;
+ offset = 0;
+ npass--;
+ if (rbytes > 0)
+ {
+ if (npass > 0)
+ memcpy(passwords[i], pptr+1, rbytes);
+ memset(pptr+1, '\0', rbytes);
+ }
+ }
+ offset += rbytes;
+ }
+
+ /* clear up */
+ if (offset > 0 && npass > 0)
+ memset(passwords[i], '\0', offset);
+
+ return i;
+}
+
+
+static int
+check_history(const char *user, const char *debug)
+{
+ char pass[MAXPASS + 1];
+ char *passwords[] = { pass };
+ int npass;
+ int dbg = atoi(debug); /* no need to be too fancy here */
+ int retval;
+
+ /* read the password from stdin (a pipe from the pam_pwhistory module) */
+ npass = read_passwords(STDIN_FILENO, 1, passwords);
+
+ if (npass != 1)
+ { /* is it a valid password? */
+ helper_log_err(LOG_DEBUG, "no password supplied");
+ return PAM_AUTHTOK_ERR;
+ }
+
+ retval = check_old_pass(user, pass, dbg);
+
+ memset(pass, '\0', MAXPASS); /* clear memory of the password */
+
+ return retval;
+}
+
+static int
+save_history(const char *user, const char *howmany, const char *debug)
+{
+ int num = atoi(howmany);
+ int dbg = atoi(debug); /* no need to be too fancy here */
+ int retval;
+
+ retval = save_old_pass(user, num, dbg);
+
+ return retval;
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *option;
+ const char *user;
+
+ /*
+ * Catch or ignore as many signal as possible.
+ */
+ setup_signals();
+
+ /*
+ * we establish that this program is running with non-tty stdin.
+ * this is to discourage casual use.
+ */
+
+ if (isatty(STDIN_FILENO) || argc < 4)
+ {
+ fprintf(stderr,
+ "This binary is not designed for running in this way.\n");
+ sleep(10); /* this should discourage/annoy the user */
+ return PAM_SYSTEM_ERR;
+ }
+
+ option = argv[1];
+ user = argv[2];
+
+ if (strcmp(option, "check") == 0 && argc == 4)
+ return check_history(user, argv[3]);
+ else if (strcmp(option, "save") == 0 && argc == 5)
+ return save_history(user, argv[3], argv[4]);
+
+ return PAM_SYSTEM_ERR;
+}
+
diff -up Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml.pwhhelper Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml
--- Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml.pwhhelper 2016-05-06 15:18:42.308637957 +0200
+++ Linux-PAM-1.3.0/modules/pam_pwhistory/pwhistory_helper.8.xml 2016-05-06 15:18:42.308637957 +0200
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<refentry id="pwhistory_helper">
+
+ <refmeta>
+ <refentrytitle>pwhistory_helper</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id="pwhistory_helper-name">
+ <refname>pwhistory_helper</refname>
+ <refpurpose>Helper binary that transfers password hashes from passwd or shadow to opasswd</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis id="pwhistory_helper-cmdsynopsis">
+ <command>pwhistory_helper</command>
+ <arg choice="opt">
+ ...
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="pwhistory_helper-description">
+
+ <title>DESCRIPTION</title>
+
+ <para>
+ <emphasis>pwhistory_helper</emphasis> is a helper program for the
+ <emphasis>pam_pwhistory</emphasis> module that transfers password hashes
+ from passwd or shadow file to the opasswd file and checks a password
+ supplied by user against the existing hashes in the opasswd file.
+ </para>
+
+ <para>
+ The purpose of the helper is to enable tighter confinement of
+ login and password changing services. The helper is thus called only
+ when SELinux is enabled on the system.
+ </para>
+
+ <para>
+ The interface of the helper - command line options, and input/output
+ data format are internal to the <emphasis>pam_pwhistory</emphasis>
+ module and it should not be called directly from applications.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pwhistory_helper-see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>pam_pwhistory</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pwhistory_helper-author'>
+ <title>AUTHOR</title>
+ <para>
+ Written by Tomas Mraz based on the code originally in
+ <emphasis>pam_pwhistory and pam_unix</emphasis> modules.
+ </para>
+ </refsect1>
+
+</refentry>

@ -1,16 +1,7 @@
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames Linux-PAM-1.5.1/modules/pam_access/pam_access.c
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.c 2024-01-22 15:56:09.977868880 +0100
@@ -662,7 +662,7 @@ from_match (pam_handle_t *pamh UNUSED, c
}
}
} else {
- /* Assume network/netmask with a IP of a host. */
+ /* Assume network/netmask, IP address or hostname. */
if (network_netmask_match(pamh, tok, string, item))
return YES;
}
@@ -684,7 +684,7 @@ string_match (pam_handle_t *pamh, const
diff -up Linux-PAM-1.3.1/modules/pam_access/pam_access.c.access-handle-hostnames Linux-PAM-1.3.1/modules/pam_access/pam_access.c
--- Linux-PAM-1.3.1/modules/pam_access/pam_access.c.access-handle-hostnames 2024-01-19 16:45:18.319862531 +0100
+++ Linux-PAM-1.3.1/modules/pam_access/pam_access.c 2024-01-19 16:50:34.239545948 +0100
@@ -683,7 +683,7 @@ string_match (pam_handle_t *pamh, const
/*
* If the token has the magic value "ALL" the match always succeeds.
* Otherwise, return YES if the token fully matches the string.
@ -19,7 +10,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames
*/
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
@@ -702,7 +702,8 @@ string_match (pam_handle_t *pamh, const
@@ -701,7 +701,8 @@ string_match (pam_handle_t *pamh, const
/* network_netmask_match - match a string against one token
* where string is a hostname or ip (v4,v6) address and tok
@ -29,7 +20,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames
*/
static int
network_netmask_match (pam_handle_t *pamh,
@@ -711,10 +712,12 @@ network_netmask_match (pam_handle_t *pam
@@ -710,10 +711,12 @@ network_netmask_match (pam_handle_t *pam
char *netmask_ptr;
char netmask_string[MAXHOSTNAMELEN + 1];
int addr_type;
@ -43,7 +34,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames
/* OK, check if tok is of type addr/mask */
if ((netmask_ptr = strchr(tok, '/')) != NULL)
{
@@ -748,54 +751,108 @@ network_netmask_match (pam_handle_t *pam
@@ -745,52 +748,109 @@ network_netmask_match (pam_handle_t *pam
netmask_ptr = number_to_netmask(netmask, addr_type,
netmask_string, MAXHOSTNAMELEN);
}
@ -68,7 +59,8 @@ diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames
+ */
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
{
+ pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok);
+ if (item->debug)
+ pam_syslog(pamh, LOG_DEBUG, "cannot resolve hostname \"%s\"", tok);
+
return NO;
}
@ -105,13 +97,11 @@ diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.access-handle-hostnames
{
char buf[INET6_ADDRSTRLEN];
- DIAG_PUSH_IGNORE_CAST_ALIGN;
- inet_ntop (runp->ai_family,
- runp->ai_family == AF_INET
- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr
- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr,
- buf, sizeof (buf));
- DIAG_POP_IGNORE_CAST_ALIGN;
+ if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0)
+ {
+ freeaddrinfo(ai);

@ -0,0 +1,35 @@
From b429ea18b1c9c8953df5169c6a453b4255a6f23d Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ikerpedrosam@gmail.com>
Date: Thu, 27 Feb 2020 11:48:47 +0100
Subject: [PATCH] pam_tty_audit: if kernel audit is disabled return PAM_IGNORE
If kernel audit is disabled the socket open will return
EPROTONOSUPPORT.
Return PAM_IGNORE from pam_tty_audit and log a warning
in this situation so login is not blocked by the module.
---
modules/pam_tty_audit/pam_tty_audit.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c
index 7dbcada2..589c60a2 100644
--- a/modules/pam_tty_audit/pam_tty_audit.c
+++ b/modules/pam_tty_audit/pam_tty_audit.c
@@ -351,6 +351,14 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv)
fd = nl_open ();
if (fd == -1
+ && errno == EPROTONOSUPPORT)
+ {
+ pam_syslog (pamh, LOG_WARNING, "unable to open audit socket, audit not "
+ "supported; tty_audit skipped");
+ free (old_status);
+ return PAM_IGNORE;
+ }
+ else if (fd == -1
|| nl_send (fd, AUDIT_TTY_GET, 0, NULL, 0) != 0
|| nl_recv (fd, AUDIT_TTY_GET, old_status, sizeof (*old_status)) != 0)
{
--
2.25.2

@ -0,0 +1,88 @@
From 27d04a849fd9f9cfd4b35eb80d687817830183df Mon Sep 17 00:00:00 2001
From: Tomas Mraz <tmraz@fedoraproject.org>
Date: Wed, 7 Aug 2019 12:22:55 +0200
Subject: [PATCH] pam_get_authtok_verify: Avoid duplicate password verification
If password was already verified by previous modules in the stack
it does not need to be verified by pam_get_authtok_verify either.
* libpam/pam_get_authtok.c (pam_get_authtok_internal): Set the authtok_verified
appropriately.
(pam_get_authtok_verify): Do not prompt if authtok_verified is set and
set it when the password is verified.
* libpam/pam_private.h: Add authtok_verified to the pam handle struct.
* libpam/pam_start.c (pam_start): Initialize authtok_verified.
---
libpam/pam_get_authtok.c | 10 ++++++++++
libpam/pam_private.h | 1 +
libpam/pam_start.c | 1 +
3 files changed, 12 insertions(+)
diff --git a/libpam/pam_get_authtok.c b/libpam/pam_get_authtok.c
index 800c6e5..99eb25f 100644
--- a/libpam/pam_get_authtok.c
+++ b/libpam/pam_get_authtok.c
@@ -140,6 +140,8 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
}
else if (chpass)
{
+ pamh->authtok_verified = 0;
+
retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0],
PROMPT1, authtok_type,
strlen (authtok_type) > 0?" ":"");
@@ -184,6 +186,9 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
if (retval != PAM_SUCCESS)
return retval;
+ if (chpass > 1)
+ pamh->authtok_verified = 1;
+
return pam_get_item(pamh, item, (const void **)authtok);
}
@@ -214,6 +219,9 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
if (authtok == NULL || pamh->choice != PAM_CHAUTHTOK)
return PAM_SYSTEM_ERR;
+ if (pamh->authtok_verified)
+ return pam_get_item (pamh, PAM_AUTHTOK, (const void **)authtok);
+
if (prompt != NULL)
{
retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
@@ -252,5 +260,7 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
if (retval != PAM_SUCCESS)
return retval;
+ pamh->authtok_verified = 1;
+
return pam_get_item(pamh, PAM_AUTHTOK, (const void **)authtok);
}
diff --git a/libpam/pam_private.h b/libpam/pam_private.h
index 7ff9f75..58a26f5 100644
--- a/libpam/pam_private.h
+++ b/libpam/pam_private.h
@@ -172,6 +172,7 @@ struct pam_handle {
#ifdef HAVE_LIBAUDIT
int audit_state; /* keep track of reported audit messages */
#endif
+ int authtok_verified;
};
/* Values for select arg to _pam_dispatch() */
diff --git a/libpam/pam_start.c b/libpam/pam_start.c
index 328416d..e27c64b 100644
--- a/libpam/pam_start.c
+++ b/libpam/pam_start.c
@@ -94,6 +94,7 @@ int pam_start (
#endif
(*pamh)->xdisplay = NULL;
(*pamh)->authtok_type = NULL;
+ (*pamh)->authtok_verified = 0;
memset (&((*pamh)->xauth), 0, sizeof ((*pamh)->xauth));
if (((*pamh)->pam_conversation = (struct pam_conv *)
--
2.20.1

@ -0,0 +1,11 @@
diff -up Linux-PAM-1.3.1/modules/pam_console/sed-static.console-build Linux-PAM-1.3.1/modules/pam_console/sed-static
--- Linux-PAM-1.3.1/modules/pam_console/sed-static.console-build 2014-01-31 14:17:53.000000000 +0100
+++ Linux-PAM-1.3.1/modules/pam_console/sed-static 2018-09-10 15:06:04.115302315 +0200
@@ -13,6 +13,7 @@ sed '
/^YY_BUFFER_STATE yy_scan_buffer/s/^/STATIC /
/^YY_BUFFER_STATE yy_scan_string/s/^/STATIC /
/^void yy_switch_to_buffer/s/^/STATIC /
+/^extern int yylex/s/^extern /STATIC /
/define YY_DECL int yylex/s/YY_DECL /YY_DECL STATIC /
/^int yyparse/s/^/STATIC /
/^void yyrestart/s/^/STATIC /

@ -0,0 +1,185 @@
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index 106ef7c..b2e94c7 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -282,7 +282,6 @@ _pam_open_config_file(pam_handle_t *pamh
{
char *p;
FILE *f;
- int err = 0;
/* Absolute path */
if (service[0] == '/') {
diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c
index be53f34..07dce36 100644
--- a/libpam_misc/misc_conv.c
+++ b/libpam_misc/misc_conv.c
@@ -211,7 +211,7 @@ static int read_string(int echo, const char *prompt, char **retstr)
line[nc] = '\0';
}
*retstr = strdup(line);
- _pam_overwrite(line);
+ _pam_overwrite_n(line, sizeof(line));
if (!*retstr) {
D(("no memory for response string"));
nc = -1;
@@ -244,7 +244,7 @@ static int read_string(int echo, const char *prompt, char **retstr)
D(("the timer appears to have expired"));
*retstr = NULL;
- _pam_overwrite(line);
+ _pam_overwrite_n(line, sizeof(line));
cleanexit:
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
index 80d885d..3801862 100644
--- a/modules/pam_access/pam_access.c
+++ b/modules/pam_access/pam_access.c
@@ -806,7 +806,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
const char *user=NULL;
const void *void_from=NULL;
const char *from;
- const char const *default_config = PAM_ACCESS_CONFIG;
+ const char * const default_config = PAM_ACCESS_CONFIG;
struct passwd *user_pw;
char hostname[MAXHOSTNAMELEN + 1];
int rv;
diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
index 4bc4ae7..f8476b4 100644
--- a/modules/pam_limits/pam_limits.c
+++ b/modules/pam_limits/pam_limits.c
@@ -342,7 +342,7 @@ static const char *lnames[RLIM_NLIMITS] = {
#endif
};
-static int str2rlimit(char *name) {
+static int str2rlimit(const char *name) {
int i;
if (!name || *name == '\0')
return -1;
@@ -352,7 +352,7 @@ static int str2rlimit(char *name) {
return -1;
}
-static rlim_t str2rlim_t(char *value) {
+static rlim_t str2rlim_t(const char *value) {
unsigned long long rlimit = 0;
if (!value) return (rlim_t)rlimit;
@@ -384,7 +384,7 @@ static void parse_kernel_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int
FILE *limitsfile;
const char *proclimits = "/proc/1/limits";
char line[256];
- char *units, *hard, *soft, *name;
+ const char *units, *hard, *soft, *name;
if (!(limitsfile = fopen(proclimits, "r"))) {
pam_syslog(pamh, LOG_WARNING, "Could not read %s (%s), using PAM defaults", proclimits, strerror(errno));
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index 96bfd98..66d202c 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -64,7 +64,7 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
fd = open("/proc/self/uid_map", O_RDONLY);
if (fd >= 0) {
count = pam_modutil_read(fd, uid_map, sizeof(uid_map));
- if (strncmp(uid_map, host_uid_map, count) != 0)
+ if (count <= 0 || strncmp(uid_map, host_uid_map, count) != 0)
rc = PAM_IGNORE;
close(fd);
}
diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c
index 9e204c1..4b8d6b7 100644
--- a/modules/pam_mkhomedir/mkhomedir_helper.c
+++ b/modules/pam_mkhomedir/mkhomedir_helper.c
@@ -232,6 +232,8 @@ create_homedir(const struct passwd *pwd,
{
pam_syslog(NULL, LOG_DEBUG,
"unable to open or stat src file %s: %m", newsource);
+ if (srcfd >= 0)
+ close(srcfd);
closedir(d);
#ifndef PATH_MAX
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
index f541f89..85f5efa 100644
--- a/modules/pam_namespace/pam_namespace.c
+++ b/modules/pam_namespace/pam_namespace.c
@@ -1418,6 +1418,7 @@ static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat *
if (fstat(fd, &newstatbuf) < 0) {
pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m",
ipath);
+ close(fd);
rmdir(ipath);
return PAM_SESSION_ERR;
}
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
index e6cf346..813f579 100644
--- a/modules/pam_pwhistory/opasswd.c
+++ b/modules/pam_pwhistory/opasswd.c
@@ -326,6 +326,9 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
n = strlen (buf);
#endif /* HAVE_GETLINE / HAVE_GETDELIM */
+ if (n < 1)
+ break;
+
cp = buf;
save = strdup (buf); /* Copy to write the original data back. */
if (save == NULL)
@@ -336,9 +339,6 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid,
goto error_opasswd;
}
- if (n < 1)
- break;
-
tmp = strchr (cp, '#'); /* remove comments */
if (tmp)
*tmp = '\0';
diff --git a/modules/pam_rootok/pam_rootok.c b/modules/pam_rootok/pam_rootok.c
index 17baabe..a9d9140 100644
--- a/modules/pam_rootok/pam_rootok.c
+++ b/modules/pam_rootok/pam_rootok.c
@@ -66,14 +66,17 @@ log_callback (int type, const char *fmt, ...)
int audit_fd;
va_list ap;
- va_start(ap, fmt);
#ifdef HAVE_LIBAUDIT
audit_fd = audit_open();
if (audit_fd >= 0) {
char *buf;
+ int ret;
- if (vasprintf (&buf, fmt, ap) < 0)
+ va_start(ap, fmt);
+ ret = vasprintf (&buf, fmt, ap);
+ va_end(ap);
+ if (ret < 0)
return 0;
audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
NULL, 0);
@@ -83,6 +86,7 @@ log_callback (int type, const char *fmt, ...)
}
#endif
+ va_start(ap, fmt);
vsyslog (LOG_USER | LOG_INFO, fmt, ap);
va_end(ap);
return 0;
diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c
index c653290..f37af0f 100644
--- a/modules/pam_sepermit/pam_sepermit.c
+++ b/modules/pam_sepermit/pam_sepermit.c
@@ -353,7 +353,7 @@ sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user,
if (*sense == PAM_SUCCESS) {
if (ignore)
*sense = PAM_IGNORE;
- if (geteuid() == 0 && exclusive && get_loginuid(pamh) == -1)
+ if (geteuid() == 0 && exclusive && get_loginuid(pamh) == (uid_t)-1)
if (sepermit_lock(pamh, user, debug) < 0)
*sense = PAM_AUTH_ERR;
}

@ -0,0 +1,13 @@
diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-create-tallydir Linux-PAM-1.3.1/modules/pam_faillock/faillock.c
--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.c.faillock-create-tallydir 2024-01-08 11:32:02.122392119 +0100
+++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.c 2024-01-08 11:33:10.916515943 +0100
@@ -74,6 +74,9 @@ open_tally (const char *dir, const char
if (create) {
flags |= O_CREAT;
+ if (access(dir, F_OK) != 0) {
+ mkdir(dir, 0755);
+ }
}
fd = open(path, flags, 0600);

@ -1,6 +1,6 @@
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml 2022-05-25 15:30:33.700518571 +0200
diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml
--- Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-from-file 2022-05-26 10:57:11.713067506 +0200
+++ Linux-PAM-1.3.1/modules/pam_faillock/faillock.8.xml 2022-05-26 10:57:11.747067749 +0200
@@ -57,12 +57,29 @@
<variablelist>
<varlistentry>
@ -33,10 +33,10 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.8.xml.faillock-load-conf-
</para>
</listitem>
</varlistentry>
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file 2022-05-25 15:30:33.699518564 +0200
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c 2022-05-25 15:30:33.700518571 +0200
@@ -0,0 +1,263 @@
diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c
--- Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c.faillock-load-conf-from-file 2022-05-26 10:57:11.747067749 +0200
+++ Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.c 2022-05-26 10:57:11.747067749 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2022 Tomas Mraz <tm@t8m.info>
+ * Copyright (c) 2022 Iker Pedrosa <ipedrosa@redhat.com>
@ -88,6 +88,9 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-co
+#include "faillock.h"
+
+#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf"
+#ifdef VENDOR_SCONFIGDIR
+#define VENDOR_FAILLOCK_DEFAULT_CONF VENDOR_SCONFIGDIR "/faillock.conf"
+#endif
+
+static void PAM_FORMAT((printf, 3, 4)) PAM_NONNULL((3))
+config_log(const pam_handle_t *pamh, int priority, const char *fmt, ...)
@ -300,9 +303,9 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.c.faillock-load-co
+{
+ return (opts->dir != NULL) ? opts->dir : FAILLOCK_DEFAULT_TALLYDIR;
+}
diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h
--- Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file 2022-05-25 15:30:33.699518564 +0200
+++ Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h 2022-05-25 15:30:33.700518571 +0200
diff -up Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h
--- Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h.faillock-load-conf-from-file 2022-05-26 10:57:11.747067749 +0200
+++ Linux-PAM-1.3.1/modules/pam_faillock/faillock_config.h 2022-05-26 10:57:11.747067749 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2022 Tomas Mraz <tm@t8m.info>
@ -393,11 +396,11 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock_config.h.faillock-load-co
+const char *get_tally_dir(const struct options *opts);
+
+#endif /* _FAILLOCK_CONFIG_H */
diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/main.c
--- Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_faillock/main.c 2022-05-25 15:37:05.801216176 +0200
@@ -51,33 +51,40 @@
#define AUDIT_NO_ID ((unsigned int) -1)
diff -up Linux-PAM-1.3.1/modules/pam_faillock/main.c.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/main.c
--- Linux-PAM-1.3.1/modules/pam_faillock/main.c.faillock-load-conf-from-file 2022-05-26 10:57:11.713067506 +0200
+++ Linux-PAM-1.3.1/modules/pam_faillock/main.c 2022-05-26 10:57:11.747067749 +0200
@@ -48,43 +48,50 @@
#include <libaudit.h>
#endif
+#include "pam_inline.h"
@ -445,20 +448,25 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-fil
return -1;
}
- opts->dir = argv[i];
- }
+ dir = argv[i];
}
+ }
else if (strcmp(argv[i], "--user") == 0) {
++i;
@@ -85,7 +92,7 @@ args_parse(int argc, char **argv, struct
fprintf(stderr, "%s: No user name supplied.\n", argv[0]);
if (i >= argc || strlen(argv[i]) == 0) {
- fprintf(stderr, "%s: No user name supplied.\n", argv[0]);
+ fprintf(stderr, "%s: No user name supplied.\n", argv[0]);
return -1;
}
- opts->user = argv[i];
+ opts->user = argv[i];
}
else if (strcmp(argv[i], "--reset") == 0) {
- else if (strcmp(argv[i], "--reset") == 0) {
+ else if (strcmp(argv[i], "--reset") == 0) {
opts->reset = 1;
@@ -95,6 +102,21 @@ args_parse(int argc, char **argv, struct
}
else {
@@ -92,6 +99,21 @@ args_parse(int argc, char **argv, struct
return -1;
}
}
@ -480,7 +488,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-fil
return 0;
}
@@ -112,10 +134,11 @@ do_user(struct options *opts, const char
@@ -109,10 +131,11 @@ do_user(struct options *opts, const char
int rv;
struct tally_data tallies;
struct passwd *pwd;
@ -493,7 +501,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-fil
if (fd == -1) {
if (errno == ENOENT) {
@@ -191,8 +214,9 @@ do_allusers(struct options *opts)
@@ -189,11 +212,11 @@ do_allusers(struct options *opts)
{
struct dirent **userlist;
int rv, i;
@ -502,21 +510,25 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/main.c.faillock-load-conf-from-fil
- rv = scandir(opts->dir, &userlist, NULL, alphasort);
+ rv = scandir(dir, &userlist, NULL, alphasort);
if (rv < 0) {
fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname);
- fprintf(stderr, "%s: Error reading tally directory: ", opts->progname);
- perror(NULL);
+ fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname);
return 2;
diff -up Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am
--- Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am 2022-05-25 15:30:33.700518571 +0200
@@ -20,7 +20,7 @@ TESTS = $(dist_check_SCRIPTS)
}
diff -up Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am
--- Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am.faillock-load-conf-from-file 2022-05-26 10:57:11.727067606 +0200
+++ Linux-PAM-1.3.1/modules/pam_faillock/Makefile.am 2022-05-26 10:57:59.032406450 +0200
@@ -17,7 +17,7 @@ TESTS = tst-pam_faillock
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
-noinst_HEADERS = faillock.h
+noinst_HEADERS = faillock.h faillock_config.h
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
$(WARN_CFLAGS)
@@ -41,8 +41,8 @@ dist_secureconf_DATA = faillock.conf
faillock_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include @PIE_CFLAGS@
pam_faillock_la_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include
@@ -36,8 +36,8 @@ secureconf_DATA = faillock.conf
securelib_LTLIBRARIES = pam_faillock.la
sbin_PROGRAMS = faillock
@ -526,10 +538,10 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/Makefile.am.faillock-load-conf-fro
+faillock_SOURCES = main.c faillock.c faillock_config.c
if ENABLE_REGENERATE_MAN
dist_noinst_DATA = README
diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c
--- Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c 2022-05-25 15:33:03.885551825 +0200
noinst_DATA = README
diff -up Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c
--- Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-from-file 2022-05-26 10:57:11.727067606 +0200
+++ Linux-PAM-1.3.1/modules/pam_faillock/pam_faillock.c 2022-05-26 10:57:11.748067756 +0200
@@ -38,7 +38,6 @@
#include <stdio.h>
#include <string.h>
@ -538,10 +550,15 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
#include <stdlib.h>
#include <errno.h>
#include <time.h>
@@ -56,55 +55,12 @@
@@ -54,83 +53,50 @@
#include <security/pam_modutil.h>
#include <security/pam_ext.h>
#include "pam_inline.h"
+#include "pam_inline.h"
#include "faillock.h"
-
-#define PAM_SM_AUTH
-#define PAM_SM_ACCOUNT
+#include "faillock_config.h"
#define FAILLOCK_ACTION_PREAUTH 0
@ -554,12 +571,13 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
-#define FAILLOCK_FLAG_NO_LOG_INFO 0x8
-#define FAILLOCK_FLAG_UNLOCKED 0x10
-#define FAILLOCK_FLAG_LOCAL_ONLY 0x20
-#define FAILLOCK_FLAG_NO_DELAY 0x40
-
-#define MAX_TIME_INTERVAL 604800 /* 7 days */
-#define FAILLOCK_CONF_MAX_LINELEN 1023
-#define FAILLOCK_ERROR_CONF_OPEN -3
-#define FAILLOCK_ERROR_CONF_MALFORMED -4
-
-static const char default_faillock_conf[] = FAILLOCK_DEFAULT_CONF;
-#define PATH_PASSWD "/etc/passwd"
-
-struct options {
- unsigned int action;
@ -569,6 +587,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- unsigned int unlock_time;
- unsigned int root_unlock_time;
- char *dir;
- const char *conf;
- const char *user;
- char *admin_group;
- int failures;
@ -579,36 +598,66 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- int fatal_error;
-};
-
-static int read_config_file(
-int read_config_file(
- pam_handle_t *pamh,
- struct options *opts,
- const char *cfgfile
-);
-
-static void set_conf_opt(
-void set_conf_opt(
- pam_handle_t *pamh,
- struct options *opts,
- const char *name,
- const char *value
-);
-
static int
-static void
+static int
args_parse(pam_handle_t *pamh, int argc, const char **argv,
int flags, struct options *opts)
@@ -112,11 +68,10 @@ args_parse(pam_handle_t *pamh, int argc,
{
int i;
int config_arg_index = -1;
+ int config_arg_index = -1;
int rv;
- const char *conf = default_faillock_conf;
+ const char *conf = NULL;
+
memset(opts, 0, sizeof(*opts));
- opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR);
- opts->conf = FAILLOCK_DEFAULT_CONF;
opts->deny = 3;
opts->fail_interval = 900;
opts->unlock_time = 600;
@@ -174,185 +129,11 @@ args_parse(pam_handle_t *pamh, int argc,
opts->root_unlock_time = MAX_TIME_INTERVAL+1;
- if ((rv=read_config_file(pamh, opts, opts->conf)) != PAM_SUCCESS) {
- pam_syslog(pamh, LOG_DEBUG,
- "Configuration file missing");
+ for (i = 0; i < argc; ++i) {
+ const char *str = pam_str_skip_prefix(argv[i], "conf=");
+
+ if (str != NULL) {
+ conf = str;
+ config_arg_index = i;
+ }
+ }
+
+ if ((rv = read_config_file(pamh, opts, conf)) != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR,
+ "Configuration file missing or broken");
+ return rv;
}
for (i = 0; i < argc; ++i) {
- if (strcmp(argv[i], "preauth") == 0) {
+ if (i == config_arg_index) {
+ continue;
+ }
+ else if (strcmp(argv[i], "preauth") == 0) {
opts->action = FAILLOCK_ACTION_PREAUTH;
}
else if (strcmp(argv[i], "authfail") == 0) {
@@ -163,226 +129,26 @@ args_parse(pam_handle_t *pamh, int argc,
if (flags & PAM_SILENT)
opts->flags |= FAILLOCK_FLAG_SILENT;
@ -616,14 +665,10 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m");
- opts->fatal_error = 1;
- }
-}
-
if (opts->fatal_error)
return PAM_BUF_ERR;
return PAM_SUCCESS;
}
-/* parse a single configuration file */
-static int
-int
-read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile)
-{
- FILE *f;
@ -632,9 +677,9 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- f = fopen(cfgfile, "r");
- if (f == NULL) {
- /* ignore non-existent default config file */
- if (errno == ENOENT && cfgfile == default_faillock_conf)
- return PAM_SUCCESS;
- return PAM_SERVICE_ERR;
- if (errno == ENOENT && strcmp(cfgfile, FAILLOCK_DEFAULT_CONF) == 0)
- return 0;
- return FAILLOCK_ERROR_CONF_OPEN;
- }
-
- while (fgets(linebuf, sizeof(linebuf), f) != NULL) {
@ -647,7 +692,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- /* len cannot be 0 unless there is a bug in fgets */
- if (len && linebuf[len - 1] != '\n' && !feof(f)) {
- (void) fclose(f);
- return PAM_SERVICE_ERR;
- return FAILLOCK_ERROR_CONF_MALFORMED;
- }
-
- if ((ptr=strchr(linebuf, '#')) != NULL) {
@ -700,11 +745,12 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- }
-
- (void)fclose(f);
- return PAM_SUCCESS;
-}
-
-static void
-set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value)
+ if (opts->fatal_error)
+ return PAM_BUF_ERR;
return PAM_SUCCESS;
}
-void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value)
-{
- if (strcmp(name, "dir") == 0) {
- if (value[0] != '/') {
@ -783,18 +829,83 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
- else if (strcmp(name, "local_users_only") == 0) {
- opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY;
- }
- else if (strcmp(name, "nodelay") == 0) {
- opts->flags |= FAILLOCK_FLAG_NO_DELAY;
- }
- else {
- pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name);
- }
-}
-
static int
check_local_user (pam_handle_t *pamh, const char *user)
-static int check_local_user (pam_handle_t *pamh, const char *user)
+static int
+check_local_user (pam_handle_t *pamh, const char *user)
{
- struct passwd pw, *pwp;
- char buf[4096];
- int found = 0;
- FILE *fp;
- int errn;
-
- fp = fopen(PATH_PASSWD, "r");
- if (fp == NULL) {
- pam_syslog(pamh, LOG_ERR, "unable to open %s: %m",
- PATH_PASSWD);
- return -1;
- }
-
- for (;;) {
- errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp);
- if (errn == ERANGE) {
- pam_syslog(pamh, LOG_WARNING, "%s contains very long lines; corrupted?",
- PATH_PASSWD);
- /* we can continue here as next call will read further */
- continue;
- }
- if (errn != 0)
- break;
- if (strcmp(pwp->pw_name, user) == 0) {
- found = 1;
- break;
- }
- }
-
- fclose (fp);
-
- if (errn != 0 && errn != ENOENT) {
- pam_syslog(pamh, LOG_ERR, "unable to enumerate local accounts: %m");
- return -1;
- } else {
- return found;
- }
+ return pam_modutil_check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS;
}
-static int get_pam_user(pam_handle_t *pamh, struct options *opts)
+static int
+get_pam_user(pam_handle_t *pamh, struct options *opts)
{
@@ -406,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct o
const char *user;
int rv;
struct passwd *pwd;
if ((rv=pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) {
- return rv;
+ return rv == PAM_CONV_AGAIN ? PAM_INCOMPLETE : rv;
}
if (*user == '\0') {
@@ -391,10 +157,10 @@ static int get_pam_user(pam_handle_t *pa
if ((pwd=pam_modutil_getpwnam(pamh, user)) == NULL) {
if (opts->flags & FAILLOCK_FLAG_AUDIT) {
- pam_syslog(pamh, LOG_ERR, "User unknown: %s", user);
+ pam_syslog(pamh, LOG_NOTICE, "User unknown: %s", user);
}
else {
- pam_syslog(pamh, LOG_ERR, "User unknown");
+ pam_syslog(pamh, LOG_NOTICE, "User unknown");
}
return PAM_IGNORE;
}
@@ -421,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct o
unsigned int i;
uint64_t latest_time;
int failures;
@ -807,7 +918,25 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
*fd = tfd;
@@ -483,9 +265,10 @@ static void
@@ -446,7 +213,7 @@ check_tally(pam_handle_t *pamh, struct o
}
latest_time = 0;
- for(i = 0; i < tallies->count; i++) {
+ for (i = 0; i < tallies->count; i++) {
if ((tallies->records[i].status & TALLY_STATUS_VALID) &&
tallies->records[i].time > latest_time)
latest_time = tallies->records[i].time;
@@ -455,7 +222,7 @@ check_tally(pam_handle_t *pamh, struct o
opts->latest_time = latest_time;
failures = 0;
- for(i = 0; i < tallies->count; i++) {
+ for (i = 0; i < tallies->count; i++) {
if ((tallies->records[i].status & TALLY_STATUS_VALID) &&
latest_time - tallies->records[i].time < opts->fail_interval) {
++failures;
@@ -498,9 +265,10 @@ static void
reset_tally(pam_handle_t *pamh, struct options *opts, int *fd)
{
int rv;
@ -819,7 +948,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
}
else {
while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR);
@@ -504,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct o
@@ -519,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct o
unsigned int oldest;
uint64_t oldtime;
const void *source = NULL;
@ -831,6 +960,139 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/pam_faillock.c.faillock-load-conf-
}
if (*fd == -1) {
if (errno == EACCES) {
@@ -536,7 +305,7 @@ write_tally(pam_handle_t *pamh, struct o
failures = 0;
for (i = 0; i < tallies->count; ++i) {
- if (tallies->records[i].time < oldtime) {
+ if (oldtime == 0 || tallies->records[i].time < oldtime) {
oldtime = tallies->records[i].time;
oldest = i;
}
@@ -630,16 +399,26 @@ faillock_message(pam_handle_t *pamh, str
left = opts->latest_time + opts->unlock_time - opts->now;
}
+ pam_info(pamh, _("The account is locked due to %u failed logins."),
+ (unsigned int)opts->failures);
if (left > 0) {
left = (left + 59)/60; /* minutes */
- pam_info(pamh, _("Account temporarily locked due to %d failed logins"),
- opts->failures);
- pam_info(pamh, _("(%d minutes left to unlock)"), (int)left);
- }
- else {
- pam_info(pamh, _("Account locked due to %d failed logins"),
- opts->failures);
+#if defined HAVE_DNGETTEXT && defined ENABLE_NLS
+ pam_info(
+ pamh,
+ dngettext(PACKAGE,
+ "(%d minute left to unlock)",
+ "(%d minutes left to unlock)",
+ (int)left),
+ (int)left);
+#else
+ if (left == 1)
+ pam_info(pamh, _("(%d minute left to unlock)"), (int)left);
+ else
+ /* TRANSLATORS: only used if dngettext is not supported. */
+ pam_info(pamh, _("(%d minutes left to unlock)"), (int)left);
+#endif
}
}
}
@@ -663,7 +442,7 @@ opts_cleanup(struct options *opts)
/*---------------------------------------------------------------------*/
-PAM_EXTERN int
+int
pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
@@ -673,13 +452,13 @@ pam_sm_authenticate(pam_handle_t *pamh,
memset(&tallies, 0, sizeof(tallies));
- args_parse(pamh, argc, argv, flags, &opts);
- if (opts.fatal_error) {
- rv = PAM_BUF_ERR;
+ rv = args_parse(pamh, argc, argv, flags, &opts);
+ if (rv != PAM_SUCCESS)
goto err;
- }
- pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */
+ if (!(opts.flags & FAILLOCK_FLAG_NO_DELAY)) {
+ pam_fail_delay(pamh, 2000000); /* 2 sec delay on failure */
+ }
if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) {
goto err;
@@ -722,7 +501,7 @@ err:
/*---------------------------------------------------------------------*/
-PAM_EXTERN int
+int
pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
int argc UNUSED, const char **argv UNUSED)
{
@@ -731,7 +510,7 @@ pam_sm_setcred(pam_handle_t *pamh UNUSED
/*---------------------------------------------------------------------*/
-PAM_EXTERN int
+int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
@@ -741,12 +520,10 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int
memset(&tallies, 0, sizeof(tallies));
- args_parse(pamh, argc, argv, flags, &opts);
+ rv = args_parse(pamh, argc, argv, flags, &opts);
- if (opts.fatal_error) {
- rv = PAM_BUF_ERR;
+ if (rv != PAM_SUCCESS)
goto err;
- }
opts.action = FAILLOCK_ACTION_AUTHSUCC;
@@ -770,28 +547,3 @@ err:
/*-----------------------------------------------------------------------*/
-#ifdef PAM_STATIC
-
-/* static module data */
-
-struct pam_module _pam_faillock_modstruct = {
- MODULE_NAME,
-#ifdef PAM_SM_AUTH
- pam_sm_authenticate,
- pam_sm_setcred,
-#else
- NULL,
- NULL,
-#endif
-#ifdef PAM_SM_ACCOUNT
- pam_sm_acct_mgmt,
-#else
- NULL,
-#endif
- NULL,
- NULL,
- NULL,
-};
-
-#endif /* #ifdef PAM_STATIC */
-
diff --git a/modules/pam_faillock/faillock.h b/modules/pam_faillock/faillock.h
index b22a9dfb..0ea0ffba 100644
--- a/modules/pam_faillock/faillock.h
@ -846,3 +1108,105 @@ diff -up Linux-PAM-1.5.1/modules/pam_faillock/faillock.h.faillock-load-conf-from
int open_tally(const char *dir, const char *user, uid_t uid, int create);
int read_tally(int fd, struct tally_data *tallies);
diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
index ddbb90e7..f46fca99 100644
--- a/modules/pam_faillock/pam_faillock.c
+++ b/modules/pam_faillock/pam_faillock.c
@@ -134,10 +134,96 @@ args_parse(pam_handle_t *pamh, int argc, const char **argv,
return PAM_SUCCESS;
}
+static int
+check_user_in_passwd(pam_handle_t *pamh,
+ const char *user_name,
+ const char *file_name)
+{
+ int rc;
+ size_t user_len;
+ FILE *fp;
+ char line[BUFSIZ];
+
+ /* Validate the user name. */
+ if ((user_len = strlen(user_name)) == 0) {
+ pam_syslog(pamh, LOG_NOTICE, "user name is not valid");
+ return PAM_SERVICE_ERR;
+ }
+
+ if (user_len > sizeof(line) - sizeof(":")) {
+ pam_syslog(pamh, LOG_NOTICE, "user name is too long");
+ return PAM_SERVICE_ERR;
+ }
+
+ if (strchr(user_name, ':') != NULL) {
+ /*
+ * "root:x" is not a local user name even if the passwd file
+ * contains a line starting with "root:x:".
+ */
+ return PAM_PERM_DENIED;
+ }
+
+ /* Open the passwd file. */
+ if (file_name == NULL) {
+ file_name = "/etc/passwd";
+ }
+ if ((fp = fopen(file_name, "r")) == NULL) {
+ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", file_name);
+ return PAM_SERVICE_ERR;
+ }
+
+ /*
+ * Scan the file using fgets() instead of fgetpwent_r() because
+ * the latter is not flexible enough in handling long lines
+ * in passwd files.
+ */
+ rc = PAM_PERM_DENIED;
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ size_t line_len;
+ const char *str;
+
+ /*
+ * Does this line start with the user name
+ * followed by a colon?
+ */
+ if (strncmp(user_name, line, user_len) == 0 &&
+ line[user_len] == ':') {
+ rc = PAM_SUCCESS;
+ /*
+ * Continue reading the file to avoid timing attacks.
+ */
+ }
+ /* Has a newline been read? */
+ line_len = strlen(line);
+ if (line_len < sizeof(line) - 1 ||
+ line[line_len - 1] == '\n') {
+ /* Yes, continue with the next line. */
+ continue;
+ }
+
+ /* No, read till the end of this line first. */
+ while ((str = fgets(line, sizeof(line), fp)) != NULL) {
+ line_len = strlen(line);
+ if (line_len == 0 ||
+ line[line_len - 1] == '\n') {
+ break;
+ }
+ }
+ if (str == NULL) {
+ /* fgets returned NULL, we are done. */
+ break;
+ }
+ /* Continue with the next line. */
+ }
+
+ fclose(fp);
+ return rc;
+}
+
static int
check_local_user (pam_handle_t *pamh, const char *user)
{
- return pam_modutil_check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS;
+ return check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS;
}
static int

File diff suppressed because it is too large Load Diff

@ -0,0 +1,70 @@
diff -up Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c
--- Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing 2017-02-10 11:10:15.000000000 +0100
+++ Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c 2019-10-16 16:07:31.259021159 +0200
@@ -10,6 +10,7 @@
#include <fcntl.h>
#include <syslog.h>
#include <sys/resource.h>
+#include <dirent.h>
/*
* Creates a pipe, closes its write end, redirects fd to its read end.
@@ -116,27 +117,45 @@ redirect_out(pam_handle_t *pamh, enum pa
static void
close_fds(void)
{
+ DIR *dir = NULL;
+ struct dirent *dent;
+ int dfd = -1;
+ int fd;
+ struct rlimit rlim;
+
/*
* An arbitrary upper limit for the maximum file descriptor number
* returned by RLIMIT_NOFILE.
*/
- const int MAX_FD_NO = 65535;
+ const unsigned int MAX_FD_NO = 65535;
/* The lower limit is the same as for _POSIX_OPEN_MAX. */
- const int MIN_FD_NO = 20;
+ const unsigned int MIN_FD_NO = 20;
- int fd;
- struct rlimit rlim;
-
- if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
- fd = MAX_FD_NO;
- else if (rlim.rlim_max < MIN_FD_NO)
- fd = MIN_FD_NO;
- else
- fd = rlim.rlim_max - 1;
+ /* If /proc is mounted, we can optimize which fd can be closed. */
+ if ((dir = opendir("/proc/self/fd")) != NULL) {
+ if ((dfd = dirfd(dir)) >= 0) {
+ while ((dent = readdir(dir)) != NULL) {
+ fd = atoi(dent->d_name);
+ if (fd > STDERR_FILENO && fd != dfd)
+ close(fd);
+ }
+ }
+ closedir(dir);
+ }
+
+ /* If /proc isn't available, fallback to the previous behavior. */
+ if (dfd < 0) {
+ if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
+ fd = MAX_FD_NO;
+ else if (rlim.rlim_max < MIN_FD_NO)
+ fd = MIN_FD_NO;
+ else
+ fd = rlim.rlim_max - 1;
- for (; fd > STDERR_FILENO; --fd)
- close(fd);
+ for (; fd > STDERR_FILENO; --fd)
+ close(fd);
+ }
}
int

@ -0,0 +1,105 @@
diff -up Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.inline Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h
--- Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.inline 2022-05-26 10:44:31.702623614 +0200
+++ Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h 2022-05-26 10:44:31.703623621 +0200
@@ -44,4 +44,17 @@
# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */
#endif
+/*
+ * Evaluates to
+ * 1, if the given two types are known to be the same
+ * 0, otherwise.
+ */
+#if PAM_GNUC_PREREQ(3, 0)
+# define PAM_IS_SAME_TYPE(x_, y_) \
+ __builtin_types_compatible_p(__typeof__(x_), __typeof__(y_))
+#else
+/* Cannot tell whether these types are the same. */
+# define PAM_IS_SAME_TYPE(x_, y_) 0
+#endif
+
#endif /* PAM_CC_COMPAT_H */
diff -up Linux-PAM-1.3.1/libpam/include/pam_inline.h.inline Linux-PAM-1.3.1/libpam/include/pam_inline.h
--- Linux-PAM-1.3.1/libpam/include/pam_inline.h.inline 2022-05-26 10:44:31.703623621 +0200
+++ Linux-PAM-1.3.1/libpam/include/pam_inline.h 2022-05-26 10:44:31.703623621 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020 Dmitry V. Levin <ldv@altlinux.org>
+ *
+ * Handy inline functions and macros providing some convenient functionality
+ * to libpam and its modules.
+ */
+
+#ifndef PAM_INLINE_H
+#define PAM_INLINE_H
+
+#include "pam_cc_compat.h"
+#include <string.h>
+
+/*
+ * Evaluates to
+ * - a syntax error if the argument is 0,
+ * 0, otherwise.
+ */
+#define PAM_FAIL_BUILD_ON_ZERO(e_) (sizeof(int[-1 + 2 * !!(e_)]) * 0)
+
+/*
+ * Evaluates to
+ * 1, if the given type is known to be a non-array type
+ * 0, otherwise.
+ */
+#define PAM_IS_NOT_ARRAY(a_) PAM_IS_SAME_TYPE((a_), &(a_)[0])
+
+/*
+ * Evaluates to
+ * - a syntax error if the argument is not an array,
+ * 0, otherwise.
+ */
+#define PAM_MUST_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(!PAM_IS_NOT_ARRAY(a_))
+
+/* Evaluates to the number of elements in the specified array. */
+#define PAM_ARRAY_SIZE(a_) (sizeof(a_) / sizeof((a_)[0]) + PAM_MUST_BE_ARRAY(a_))
+
+/*
+ * Returns NULL if STR does not start with PREFIX,
+ * or a pointer to the first char in STR after PREFIX.
+ * The length of PREFIX is specified by PREFIX_LEN.
+ */
+static inline const char *
+pam_str_skip_prefix_len(const char *str, const char *prefix, size_t prefix_len)
+{
+ return strncmp(str, prefix, prefix_len) ? NULL : str + prefix_len;
+}
+
+#define pam_str_skip_prefix(str_, prefix_) \
+ pam_str_skip_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_))
+
+/*
+ * Returns NULL if STR does not start with PREFIX
+ * (ignoring the case of the characters),
+ * or a pointer to the first char in STR after PREFIX.
+ * The length of PREFIX is specified by PREFIX_LEN.
+ */
+static inline const char *
+pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix_len)
+{
+ return strncasecmp(str, prefix, prefix_len) ? NULL : str + prefix_len;
+}
+
+#define pam_str_skip_icase_prefix(str_, prefix_) \
+ pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_))
+
+#endif /* PAM_INLINE_H */
diff -up Linux-PAM-1.3.1/libpam/Makefile.am.inline Linux-PAM-1.3.1/libpam/Makefile.am
--- Linux-PAM-1.3.1/libpam/Makefile.am.inline 2022-05-26 10:44:31.702623614 +0200
+++ Linux-PAM-1.3.1/libpam/Makefile.am 2022-05-26 10:45:21.146977780 +0200
@@ -18,7 +18,8 @@ include_HEADERS = include/security/_pam_
include/security/pam_ext.h include/security/pam_modutil.h
noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
- pam_modutil_private.h include/pam_cc_compat.h
+ pam_modutil_private.h include/pam_cc_compat.h \
+ include/pam_inline.h
libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84
libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@

@ -0,0 +1,82 @@
From c426914fa166ffb0482b6f6ad659ddf17d5dfaa1 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Wed, 9 Jan 2019 23:41:16 +0200
Subject: [PATCH] pam_lastlog: Improve silent option documentation
The silent option explicitly silents only the last login message and not
bad logins. Add a note to the manual to make this clear.
* modules/pam_lastlog/pam_lastlog.8.xml: Clearify "silent showfailed"
---
modules/pam_lastlog/pam_lastlog.8.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml
index c8f247e..bc2e1be 100644
--- a/modules/pam_lastlog/pam_lastlog.8.xml
+++ b/modules/pam_lastlog/pam_lastlog.8.xml
@@ -102,6 +102,7 @@
<para>
Don't inform the user about any previous login,
just update the <filename>/var/log/lastlog</filename> file.
+ This option does not affect display of bad login attempts.
</para>
</listitem>
</varlistentry>
--
2.20.1
From 7d036249a9772c546ede1f38ad68b3f1575216d6 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nsoffer@redhat.com>
Date: Sun, 6 Jan 2019 00:36:27 +0200
Subject: [PATCH] pam_lastlog: Respect PAM_SILENT flag
pam_lastlog module will not log info about failed login if the session
was opened with PAM_SILENT flag.
Example use case enabled by this change:
sudo --non-interactive program
If this command is run by another program expecting specific output from
the command run by sudo, the unexpected info about failed logins will
break this program.
* modules/pam_lastlog/pam_lastlog.c: Respect silent option.
(_pam_session_parse): Unset LASTLOG_BTMP if PAM_SILENT is set.
---
modules/pam_lastlog/pam_lastlog.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
index 18bf7be..e980c04 100644
--- a/modules/pam_lastlog/pam_lastlog.c
+++ b/modules/pam_lastlog/pam_lastlog.c
@@ -135,11 +135,6 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP|LASTLOG_UPDATE);
- /* does the appliction require quiet? */
- if (flags & PAM_SILENT) {
- ctrl |= LASTLOG_QUIET;
- }
-
/* step through arguments */
for (; argc-- > 0; ++argv) {
@@ -168,6 +163,12 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
}
}
+ /* does the appliction require quiet? */
+ if (flags & PAM_SILENT) {
+ ctrl |= LASTLOG_QUIET;
+ ctrl &= ~LASTLOG_BTMP;
+ }
+
D(("ctrl = %o", ctrl));
return ctrl;
}
--
2.20.1

@ -0,0 +1,227 @@
From 3a3e70739834cd5cbd17469907ef718c81ae40c0 Mon Sep 17 00:00:00 2001
From: Carlos Santos <casantos@redhat.com>
Date: Wed, 11 Sep 2019 11:50:28 -0300
Subject: [PATCH] pam_lastlog: document the 'unlimited' option
Signed-off-by: Carlos Santos <casantos@redhat.com>
---
modules/pam_lastlog/pam_lastlog.8.xml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml
index bc2e1be..f10e94a 100644
--- a/modules/pam_lastlog/pam_lastlog.8.xml
+++ b/modules/pam_lastlog/pam_lastlog.8.xml
@@ -48,6 +48,9 @@
<arg choice="opt">
inactive=&lt;days&gt;
</arg>
+ <arg choice="opt">
+ unlimited
+ </arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -196,6 +199,18 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>unlimited</option>
+ </term>
+ <listitem>
+ <para>
+ If the <emphasis>fsize</emphasis> limit is set, this option can be
+ used to override it, preventing failures on systems with large UID
+ values that lead lastlog to become a huge sparse file.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -300,6 +315,9 @@
<refsect1 id='pam_lastlog-see_also'>
<title>SEE ALSO</title>
<para>
+ <citerefentry>
+ <refentrytitle>limits.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
<citerefentry>
<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
--
2.20.1
From 9349333a9ae958205294cd25e97fd6b4805bd82b Mon Sep 17 00:00:00 2001
From: Carlos Santos <casantos@redhat.com>
Date: Tue, 10 Sep 2019 23:08:30 -0300
Subject: [PATCH] pam_lastlog: prevent crash due to reduced 'fsize' limit
It a reduced fsize limit is set in /etc/security/limits.conf and
pam_limits is in use pam_lastlog may cause a crash, e.g.
----- begin /etc/pam.d/su ----
auth sufficient pam_rootok.so
auth required pam_wheel.so use_uid
auth required pam_env.so
auth required pam_unix.so nullok
account required pam_unix.so
password required pam_unix.so nullok
session required pam_limits.so
session required pam_env.so
session required pam_unix.so
session optional pam_lastlog.so
----- end /etc/pam.d/su -----
----- begin /etc/security/limits.d/fsize.conf -----
* soft fsize 1710
* hard fsize 1710
----- end /etc/security/limits.d/fsize.conf -----
# id user1
uid=1000(user1) gid=1000(user1) groups=1000(user1)
# su - user1
Last login: Wed Sep 11 01:52:44 UTC 2019 on console
$ exit
# id user2
uid=60000(user2) gid=60000(user2) groups=60000(user2)
# su - user2
File size limit exceeded
This happens because pam_limits sets RLIMIT_FSIZE before pam_lastlog
attempts to write /var/log/lastlog, leading to a SIGXFSZ signal.
In order to fix this, and an 'unlimited' option, which leads to saving
the 'fsize' limit and set it to unlimited before writing lastlog. After
that, restore the saved value. If 'fsize' is already unlimited nothing
is done.
Failing to set the 'fsize' limit is not a fatal error. With luck the
configured limit will suffice, so we try to write lastlog anyway, even
under the risk of dying due to a SIGXFSZ.
Failing to restore the 'fsize' limit is a fatal error, since we don't
want to keep it unlimited.
Signed-off-by: Carlos Santos <casantos@redhat.com>
---
modules/pam_lastlog/pam_lastlog.c | 66 ++++++++++++++++++++++++++-----
1 file changed, 57 insertions(+), 9 deletions(-)
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c
index e980c04..a135c9f 100644
--- a/modules/pam_lastlog/pam_lastlog.c
+++ b/modules/pam_lastlog/pam_lastlog.c
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <syslog.h>
#include <unistd.h>
@@ -82,15 +84,16 @@ struct lastlog {
/* argument parsing */
-#define LASTLOG_DATE 01 /* display the date of the last login */
-#define LASTLOG_HOST 02 /* display the last host used (if set) */
-#define LASTLOG_LINE 04 /* display the last terminal used */
-#define LASTLOG_NEVER 010 /* display a welcome message for first login */
-#define LASTLOG_DEBUG 020 /* send info to syslog(3) */
-#define LASTLOG_QUIET 040 /* keep quiet about things */
-#define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */
-#define LASTLOG_BTMP 0200 /* display failed login info from btmp */
-#define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */
+#define LASTLOG_DATE 01 /* display the date of the last login */
+#define LASTLOG_HOST 02 /* display the last host used (if set) */
+#define LASTLOG_LINE 04 /* display the last terminal used */
+#define LASTLOG_NEVER 010 /* display a welcome message for first login */
+#define LASTLOG_DEBUG 020 /* send info to syslog(3) */
+#define LASTLOG_QUIET 040 /* keep quiet about things */
+#define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */
+#define LASTLOG_BTMP 0200 /* display failed login info from btmp */
+#define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */
+#define LASTLOG_UNLIMITED 01000 /* unlimited file size (ignore 'fsize' limit) */
static int
_pam_auth_parse(pam_handle_t *pamh, int flags, int argc, const char **argv,
@@ -158,6 +161,8 @@ _pam_session_parse(pam_handle_t *pamh, int flags, int argc, const char **argv)
ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE);
} else if (!strcmp(*argv,"showfailed")) {
ctrl |= LASTLOG_BTMP;
+ } else if (!strcmp(*argv,"unlimited")) {
+ ctrl |= LASTLOG_UNLIMITED;
} else {
pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
}
@@ -373,6 +378,12 @@ static int
last_login_write(pam_handle_t *pamh, int announce, int last_fd,
uid_t uid, const char *user)
{
+ static struct rlimit no_limit = {
+ RLIM_INFINITY,
+ RLIM_INFINITY
+ };
+ struct rlimit old_limit;
+ int setrlimit_res;
struct flock last_lock;
struct lastlog last_login;
time_t ll_time;
@@ -427,6 +438,31 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
sleep(LASTLOG_IGNORE_LOCK_TIME);
}
+ /*
+ * Failing to set the 'fsize' limit is not a fatal error. We try to write
+ * lastlog anyway, under the risk of dying due to a SIGXFSZ.
+ */
+ D(("setting limit for 'fsize'"));
+
+ if ((announce & LASTLOG_UNLIMITED) == 0) { /* don't set to unlimted */
+ setrlimit_res = -1;
+ } else if (getrlimit(RLIMIT_FSIZE, &old_limit) == 0) {
+ if (old_limit.rlim_cur == RLIM_INFINITY) { /* already unlimited */
+ setrlimit_res = -1;
+ } else {
+ setrlimit_res = setrlimit(RLIMIT_FSIZE, &no_limit);
+ if (setrlimit_res != 0)
+ pam_syslog(pamh, LOG_WARNING, "Could not set limit for 'fsize': %m");
+ }
+ } else {
+ setrlimit_res = -1;
+ if (errno == EINVAL) {
+ pam_syslog(pamh, LOG_INFO, "Limit for 'fsize' not supported: %m");
+ } else {
+ pam_syslog(pamh, LOG_WARNING, "Could not get limit for 'fsize': %m");
+ }
+ }
+
D(("writing to the lastlog file"));
if (pam_modutil_write (last_fd, (char *) &last_login,
sizeof (last_login)) != sizeof(last_login)) {
@@ -434,6 +470,18 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd,
retval = PAM_SERVICE_ERR;
}
+ /*
+ * Failing to restore the 'fsize' limit is a fatal error.
+ */
+ D(("restoring limit for 'fsize'"));
+ if (setrlimit_res == 0) {
+ setrlimit_res = setrlimit(RLIMIT_FSIZE, &old_limit);
+ if (setrlimit_res != 0) {
+ pam_syslog(pamh, LOG_ERR, "Could not restore limit for 'fsize': %m");
+ retval = PAM_SERVICE_ERR;
+ }
+ }
+
last_lock.l_type = F_UNLCK;
(void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
D(("unlocked"));
--
2.20.1

@ -0,0 +1,25 @@
diff -up Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-manpage Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml
--- Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml.motd-manpage 2018-05-18 11:50:46.000000000 +0200
+++ Linux-PAM-1.3.1/modules/pam_motd/pam_motd.8.xml 2019-12-19 10:29:36.243558251 +0100
@@ -31,10 +31,19 @@
<para>
pam_motd is a PAM module that can be used to display
arbitrary motd (message of the day) files after a successful
- login. By default the <filename>/etc/motd</filename> file is
+ 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.
</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:
+ </para>
+ <para>
+ <command>ln -sfn /dev/null /etc/motd.d/my_motd</command>
+ </para>
</refsect1>
<refsect1 id="pam_motd-options">

@ -0,0 +1,68 @@
From 491e5500b6b3913f531574208274358a2df88659 Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Mon, 5 Oct 2020 10:41:29 +0200
Subject: [PATCH] pam_namespace: polyinstantiation refer to gdm doc
modules/pam_namespace/pam_namespace.8.xml: delete obsolete information
about polyinstantiation and refer to gdm's documentation.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1861841
---
modules/pam_namespace/pam_namespace.8.xml | 41 ++---------------------
1 file changed, 2 insertions(+), 39 deletions(-)
diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml
index f0f80d33..57c44c4b 100644
--- a/modules/pam_namespace/pam_namespace.8.xml
+++ b/modules/pam_namespace/pam_namespace.8.xml
@@ -343,45 +343,8 @@
</para>
<para>
- To use polyinstantiation with graphical display manager gdm, insert the
- following line, before exit 0, in /etc/gdm/PostSession/Default:
- </para>
-
- <para>
- /usr/sbin/gdm-safe-restart
- </para>
-
- <para>
- This allows gdm to restart after each session and appropriately adjust
- namespaces of display manager and the X server. If polyinstantiation
- of /tmp is desired along with the graphical environment, then additional
- configuration changes are needed to address the interaction of X server
- and font server namespaces with their use of /tmp to create
- communication sockets. Please use the initialization script
- <filename>/etc/security/namespace.init</filename> to ensure that
- the X server and its clients can appropriately access the
- communication socket X0. Please refer to the sample instructions
- provided in the comment section of the instance initialization script
- <filename>/etc/security/namespace.init</filename>. In addition,
- perform the following changes to use graphical environment with
- polyinstantiation of /tmp:
- </para>
-
- <para>
- <literallayout>
- 1. Disable the use of font server by commenting out "FontPath"
- line in /etc/X11/xorg.conf. If you do want to use the font server
- then you will have to augment the instance initialization
- script to appropriately provide /tmp/.font-unix from the
- polyinstantiated /tmp.
- 2. Ensure that the gdm service is setup to use pam_namespace,
- as described above, by modifying /etc/pam.d/gdm.
- 3. Ensure that the display manager is configured to restart X server
- with each new session. This default setup can be verified by
- making sure that /usr/share/gdm/defaults.conf contains
- "AlwaysRestartServer=true", and it is not overridden by
- /etc/gdm/custom.conf.
- </literallayout>
+ To use polyinstantiation with graphical display manager gdm, please refer
+ to gdm's documentation.
</para>
</refsect1>
--
2.26.2

@ -0,0 +1,131 @@
diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml
index c7698cb..a94b49e 100644
--- a/modules/pam_namespace/namespace.conf.5.xml
+++ b/modules/pam_namespace/namespace.conf.5.xml
@@ -122,9 +122,14 @@
<para><emphasis>mntopts</emphasis>=<replaceable>value</replaceable>
- value of this flag is passed to the mount call when the tmpfs mount is
done. It allows for example the specification of the maximum size of the
- tmpfs instance that is created by the mount call. See <citerefentry>
- <refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum>
- </citerefentry> for details.
+ tmpfs instance that is created by the mount call. In addition to
+ options specified in the <citerefentry>
+ <refentrytitle>tmpfs</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry> manual the <emphasis>nosuid</emphasis>,
+ <emphasis>noexec</emphasis>, and <emphasis>nodev</emphasis> flags
+ can be used to respectively disable setuid bit effect, disable running
+ executables, and disable devices to be interpreted on the mounted
+ tmpfs filesystem.
</para>
<para>
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
index f541f89..660c7a1 100644
--- a/modules/pam_namespace/pam_namespace.c
+++ b/modules/pam_namespace/pam_namespace.c
@@ -230,6 +230,73 @@ static int parse_iscript_params(char *params, struct polydir_s *poly)
return 0;
}
+struct mntflag {
+ const char *name;
+ size_t len;
+ unsigned long flag;
+};
+
+#define LITERAL_AND_LEN(x) x, sizeof(x) - 1
+
+static const struct mntflag mntflags[] = {
+ { LITERAL_AND_LEN("noexec"), MS_NOEXEC },
+ { LITERAL_AND_LEN("nosuid"), MS_NOSUID },
+ { LITERAL_AND_LEN("nodev"), MS_NODEV }
+ };
+
+static int filter_mntopts(const char *opts, char **filtered,
+ unsigned long *mountflags)
+{
+ size_t origlen = strlen(opts);
+ const char *end;
+ char *dest;
+
+ dest = *filtered = NULL;
+ *mountflags = 0;
+
+ if (origlen == 0)
+ return 0;
+
+ do {
+ size_t len;
+ int i;
+
+ end = strchr(opts, ',');
+ if (end == NULL) {
+ len = strlen(opts);
+ } else {
+ len = end - opts;
+ }
+
+ for (i = 0; i < (int)(sizeof(mntflags)/sizeof(mntflags[0])); i++) {
+ if (mntflags[i].len != len)
+ continue;
+ if (memcmp(mntflags[i].name, opts, len) == 0) {
+ *mountflags |= mntflags[i].flag;
+ opts = end;
+ break;
+ }
+ }
+
+ if (opts != end) {
+ if (dest != NULL) {
+ *dest = ',';
+ ++dest;
+ } else {
+ dest = *filtered = calloc(1, origlen + 1);
+ if (dest == NULL)
+ return -1;
+ }
+ memcpy(dest, opts, len);
+ dest += len;
+ }
+
+ opts = end + 1;
+ } while (end != NULL);
+
+ return 0;
+}
+
static int parse_method(char *method, struct polydir_s *poly,
struct instance_data *idata)
{
@@ -289,7 +356,8 @@ static int parse_method(char *method, struct polydir_s *poly,
break;
}
free(poly->mount_opts); /* if duplicate mntopts specified */
- if ((poly->mount_opts = strdup(flag+namelen+1)) == NULL) {
+ poly->mount_opts = NULL;
+ if (filter_mntopts(flag+namelen+1, &poly->mount_opts, &poly->mount_flags) != 0) {
pam_syslog(idata->pamh, LOG_CRIT, "Memory allocation error");
return -1;
}
@@ -1484,7 +1552,7 @@ static int ns_setup(struct polydir_s *polyptr,
}
if (polyptr->method == TMPFS) {
- if (mount("tmpfs", polyptr->dir, "tmpfs", 0, polyptr->mount_opts) < 0) {
+ if (mount("tmpfs", polyptr->dir, "tmpfs", polyptr->mount_flags, polyptr->mount_opts) < 0) {
pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m",
polyptr->dir);
return PAM_SESSION_ERR;
diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
index 47ebcc3..1522386 100644
--- a/modules/pam_namespace/pam_namespace.h
+++ b/modules/pam_namespace/pam_namespace.h
@@ -166,6 +166,7 @@ struct polydir_s {
unsigned int flags; /* polydir flags */
char *init_script; /* path to init script */
char *mount_opts; /* mount options for tmpfs mount */
+ unsigned long mount_flags; /* mount flags for tmpfs mount */
uid_t owner; /* user which should own the polydir */
gid_t group; /* group which should own the polydir */
mode_t mode; /* mode of the polydir */

@ -0,0 +1,24 @@
diff -up Linux-PAM-1.3.1/doc/Makefile.am.noflex Linux-PAM-1.3.1/doc/Makefile.am
--- Linux-PAM-1.3.1/doc/Makefile.am.noflex 2017-02-10 11:10:15.000000000 +0100
+++ Linux-PAM-1.3.1/doc/Makefile.am 2018-05-18 14:53:50.300997606 +0200
@@ -2,7 +2,7 @@
# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
#
-SUBDIRS = man specs sag adg mwg
+SUBDIRS = man sag adg mwg
CLEANFILES = *~
diff -up Linux-PAM-1.3.1/Makefile.am.noflex Linux-PAM-1.3.1/Makefile.am
--- Linux-PAM-1.3.1/Makefile.am.noflex 2018-05-18 14:53:50.301997629 +0200
+++ Linux-PAM-1.3.1/Makefile.am 2018-05-18 14:55:31.576353800 +0200
@@ -4,7 +4,7 @@
AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 dist-xz check-news
-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests
+SUBDIRS = libpam tests libpamc libpam_misc modules po doc examples xtests
CLEANFILES = *~

@ -0,0 +1,63 @@
diff -up Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.pam-cc-compat Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h
--- Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h.pam-cc-compat 2022-05-26 10:43:50.436328027 +0200
+++ Linux-PAM-1.3.1/libpam/include/pam_cc_compat.h 2022-05-26 10:43:50.436328027 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 Dmitry V. Levin <ldv@altlinux.org>
+ */
+
+#ifndef PAM_CC_COMPAT_H
+#define PAM_CC_COMPAT_H
+
+#include "config.h"
+#include <security/_pam_types.h>
+
+#if defined __clang__ && defined __clang_major__ && defined __clang_minor__
+# define PAM_CLANG_PREREQ(maj, min) \
+ ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
+#else
+# define PAM_CLANG_PREREQ(maj, min) 0
+#endif
+
+#if PAM_GNUC_PREREQ(4, 6)
+# define DIAG_PUSH_IGNORE_CAST_QUAL \
+ _Pragma("GCC diagnostic push"); \
+ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+# define DIAG_POP_IGNORE_CAST_QUAL \
+ _Pragma("GCC diagnostic pop")
+# define DIAG_PUSH_IGNORE_CAST_ALIGN \
+ _Pragma("GCC diagnostic push"); \
+ _Pragma("GCC diagnostic ignored \"-Wcast-align\"")
+# define DIAG_POP_IGNORE_CAST_ALIGN \
+ _Pragma("GCC diagnostic pop")
+#elif PAM_CLANG_PREREQ(2, 6)
+# define DIAG_PUSH_IGNORE_CAST_QUAL \
+ _Pragma("clang diagnostic push"); \
+ _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
+# define DIAG_POP_IGNORE_CAST_QUAL \
+ _Pragma("clang diagnostic pop")
+# define DIAG_PUSH_IGNORE_CAST_ALIGN \
+ _Pragma("clang diagnostic push"); \
+ _Pragma("clang diagnostic ignored \"-Wcast-align\"")
+# define DIAG_POP_IGNORE_CAST_ALIGN \
+ _Pragma("clang diagnostic pop")
+#else
+# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */
+# define DIAG_POP_IGNORE_CAST_QUAL /* empty */
+# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */
+# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */
+#endif
+
+#endif /* PAM_CC_COMPAT_H */
diff -up Linux-PAM-1.3.1/libpam/Makefile.am.pam-cc-compat Linux-PAM-1.3.1/libpam/Makefile.am
--- Linux-PAM-1.3.1/libpam/Makefile.am.pam-cc-compat 2022-05-26 10:43:50.436328027 +0200
+++ Linux-PAM-1.3.1/libpam/Makefile.am 2022-05-26 10:44:00.865402730 +0200
@@ -18,7 +18,7 @@ include_HEADERS = include/security/_pam_
include/security/pam_ext.h include/security/pam_modutil.h
noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
- pam_modutil_private.h
+ pam_modutil_private.h include/pam_cc_compat.h
libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84
libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@

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

@ -1,37 +1,19 @@
From 3234488f2c52a021eec87df1990d256314c21bff Mon Sep 17 00:00:00 2001
From: Josef Moellers <jmoellers@suse.de>
Date: Wed, 14 Apr 2021 16:39:28 +0200
Subject: [PATCH] pam_limits: "Unlimited" is not a valid value for
RLIMIT_NOFILE.
Replace it with a value obtained from /proc/sys/fs/nr_open
* modules/pam_limits/limits.conf.5.xml: Document the replacement.
* modules/pam_limits/pam_limits.c: Replace unlimited RLIMIT_NOFILE
value with a value obtained from /proc/sys/fs/nr_open
---
modules/pam_limits/limits.conf.5.xml | 2 ++
modules/pam_limits/pam_limits.c | 49 ++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml
index cd64ac90..c5bd6768 100644
--- a/modules/pam_limits/limits.conf.5.xml
+++ b/modules/pam_limits/limits.conf.5.xml
@@ -283,6 +283,8 @@
diff -up Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml.pam-limits-unlimited-value Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml
--- Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml.pam-limits-unlimited-value 2022-01-28 09:45:41.431606850 +0100
+++ Linux-PAM-1.3.1/modules/pam_limits/limits.conf.5.xml 2022-01-28 09:47:31.732430391 +0100
@@ -275,6 +275,8 @@
All items support the values <emphasis>-1</emphasis>,
<emphasis>unlimited</emphasis> or <emphasis>infinity</emphasis> indicating no limit,
except for <emphasis remap='B'>priority</emphasis>, <emphasis remap='B'>nice</emphasis>,
and <emphasis remap='B'>nonewprivs</emphasis>.
except for <emphasis remap='B'>priority</emphasis> and <emphasis remap='B'>nice</emphasis>.
+ If <emphasis remap='B'>nofile</emphasis> is to be set to one of these values,
+ it will be set to the contents of /proc/sys/fs/nr_open instead (see setrlimit(3)).
</para>
<para>
If a hard limit or soft limit of a resource is set to a valid value,
diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
index 10049973..7cc45d77 100644
--- a/modules/pam_limits/pam_limits.c
+++ b/modules/pam_limits/pam_limits.c
@@ -487,6 +487,41 @@ static int init_limits(pam_handle_t *pamh, struct pam_limit_s *pl, int ctrl)
diff -up Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c.pam-limits-unlimited-value Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c
--- Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c.pam-limits-unlimited-value 2022-01-28 09:45:41.415606731 +0100
+++ Linux-PAM-1.3.1/modules/pam_limits/pam_limits.c 2022-01-28 09:45:41.431606850 +0100
@@ -487,6 +487,41 @@ static int init_limits(pam_handle_t *pam
return retval;
}
@ -73,7 +55,7 @@ index 10049973..7cc45d77 100644
static void
process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
const char *lim_item, const char *lim_value,
@@ -666,6 +701,20 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type,
@@ -652,6 +687,20 @@ process_limit (const pam_handle_t *pamh,
rlimit_value = 20 - int_value;
break;
#endif
@ -94,6 +76,3 @@ index 10049973..7cc45d77 100644
}
if ( (limit_item != LIMIT_LOGIN)
--
2.33.1

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

@ -0,0 +1,74 @@
From b6f73810a2e7afd02a231e2dfa14b05752c83db7 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Levin" <ldv@altlinux.org>
Date: Wed, 26 Feb 2020 19:20:58 +0000
Subject: [PATCH] pam_modutil_sanitize_helper_fds: fix SIGPIPE effect of
PAM_MODUTIL_PIPE_FD
When pam_modutil_sanitize_helper_fds() is invoked with
PAM_MODUTIL_PIPE_FD to provide a dummy pipe descriptor for stdout
or stderr, it closes the read end of the newly created dummy pipe.
The negative side effect of this approach is that any write to such
descriptor triggers a SIGPIPE. Avoid this by closing the write end of
the dummy pipe and using its read end as a dummy pipe descriptor for
output. Any read from such descriptor returns 0, and any write just
fails with EBADF, which should work better with unprepared writers.
* libpam/pam_modutil_sanitize.c (redirect_out_pipe): Remove.
(redirect_out): Call redirect_in_pipe instead of redirect_out_pipe.
Fixes: b0ec5d1e ("Introduce pam_modutil_sanitize_helper_fds")
---
libpam/pam_modutil_sanitize.c | 30 +-----------------------------
1 file changed, 1 insertion(+), 29 deletions(-)
diff --git a/libpam/pam_modutil_sanitize.c b/libpam/pam_modutil_sanitize.c
index 605c859d..58b9537c 100644
--- a/libpam/pam_modutil_sanitize.c
+++ b/libpam/pam_modutil_sanitize.c
@@ -46,34 +46,6 @@ redirect_in_pipe(pam_handle_t *pamh, int fd, const char *name)
return fd;
}
-/*
- * Creates a pipe, closes its read end, redirects fd to its write end.
- * Returns fd on success, -1 otherwise.
- */
-static int
-redirect_out_pipe(pam_handle_t *pamh, int fd, const char *name)
-{
- int out[2];
-
- if (pipe(out) < 0) {
- pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m");
- return -1;
- }
-
- close(out[0]);
-
- if (out[1] == fd)
- return fd;
-
- if (dup2(out[1], fd) != fd) {
- pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", name);
- fd = -1;
- }
-
- close(out[1]);
- return fd;
-}
-
/*
* Opens /dev/null for writing, redirects fd there.
* Returns fd on success, -1 otherwise.
@@ -106,7 +78,7 @@ redirect_out(pam_handle_t *pamh, enum pam_modutil_redirect_fd mode,
{
switch (mode) {
case PAM_MODUTIL_PIPE_FD:
- if (redirect_out_pipe(pamh, fd, name) < 0)
+ if (redirect_in_pipe(pamh, fd, name) < 0)
return -1;
break;
case PAM_MODUTIL_NULL_FD:
--
2.25.3

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

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

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

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

@ -1,20 +1,20 @@
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am
--- Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am 2022-08-22 09:08:48.916487811 +0200
@@ -9,9 +9,10 @@ MAINTAINERCLEANFILES = $(MANS) README
EXTRA_DIST = $(XMLS)
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
if HAVE_DOC
-dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8
+dist_man_MANS = pam_pwhistory.8 pwhistory_helper.8 pwhistory.conf.5
endif
-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
dist_check_SCRIPTS = tst-pam_pwhistory
TESTS = $(dist_check_SCRIPTS)
@@ -26,12 +27,14 @@ if HAVE_VERSIONING
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
@@ -25,12 +26,14 @@ if HAVE_VERSIONING
pam_pwhistory_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
@ -30,10 +30,10 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/Makefile.am.pam-pwhistory-load-co
+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\" @EXE_CFLAGS@
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml 2022-08-22 09:13:08.715628372 +0200
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>
@ -90,15 +90,18 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.8.xml.pam-pwhistory
<refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum>
</citerefentry>,
<citerefentry>
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-load-conf-from-file 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c 2022-08-22 09:11:34.949855242 +0200
@@ -63,14 +63,8 @@
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 "pam_inline.h"
+#include "pwhistory_config.h"
#define DEFAULT_BUFLEN 2048
#define MAX_FD_NO 20000
-struct options_t {
- int debug;
- int enforce_for_root;
@ -106,10 +109,11 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-loa
- int tries;
-};
-typedef struct options_t options_t;
-
static void
@@ -299,6 +293,8 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
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;
@ -118,7 +122,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-loa
/* Parse parameters for module */
for ( ; argc-- > 0; argv++)
parse_option (pamh, *argv, &options);
@@ -306,7 +302,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
@@ -311,7 +306,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, in
if (options.debug)
pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok entered");
@ -126,9 +130,9 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pam_pwhistory.c.pam-pwhistory-loa
if (options.remember == 0)
return PAM_IGNORE;
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml 2022-08-22 09:08:48.916487811 +0200
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"
@ -285,10 +289,10 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.5.xml.pam-pwhistor
+ </refsect1>
+
+</refentry>
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c 2022-08-22 09:08:48.916487811 +0200
@@ -0,0 +1,115 @@
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>
+ *
@ -330,6 +334,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ctype.h>
+
+#include <security/pam_modutil.h>
+
@ -338,6 +343,85 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-
+
+#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)
@ -358,19 +442,19 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-
+ fname = PWHISTORY_DEFAULT_CONF;
+ }
+
+ val = pam_modutil_search_key (pamh, fname, "debug");
+ val = pwhistory_search_key (pamh, fname, "debug");
+ if (val != NULL) {
+ options->debug = 1;
+ free(val);
+ }
+
+ val = pam_modutil_search_key (pamh, fname, "enforce_for_root");
+ val = pwhistory_search_key (pamh, fname, "enforce_for_root");
+ if (val != NULL) {
+ options->enforce_for_root = 1;
+ free(val);
+ }
+
+ val = pam_modutil_search_key (pamh, fname, "remember");
+ val = pwhistory_search_key (pamh, fname, "remember");
+ if (val != NULL) {
+ unsigned int temp;
+ if (sscanf(val, "%u", &temp) != 1) {
@ -382,7 +466,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-
+ free(val);
+ }
+
+ val = pam_modutil_search_key (pamh, fname, "retry");
+ val = pwhistory_search_key (pamh, fname, "retry");
+ if (val != NULL) {
+ unsigned int temp;
+ if (sscanf(val, "%u", &temp) != 1) {
@ -394,7 +478,7 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-
+ free(val);
+ }
+
+ val = pam_modutil_search_key (pamh, fname, "file");
+ val = pwhistory_search_key (pamh, fname, "file");
+ if (val != NULL) {
+ if (*val != '/') {
+ pam_syslog (pamh, LOG_ERR,
@ -404,9 +488,9 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.c.pam-pwhistory-
+ }
+ }
+}
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h 2022-08-22 09:08:48.916487811 +0200
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>
@ -462,9 +546,9 @@ diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory_config.h.pam-pwhistory-
+ struct options_t *options);
+
+#endif /* _PWHISTORY_CONFIG_H */
diff -up Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf
--- Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf.pam-pwhistory-load-conf-from-file 2022-08-22 09:08:48.916487811 +0200
+++ Linux-PAM-1.5.1/modules/pam_pwhistory/pwhistory.conf 2022-08-22 09:08:48.916487811 +0200
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.
+#

@ -0,0 +1,111 @@
From a7453aeeb398d6cbb7a709c4e2a1d75905220fff Mon Sep 17 00:00:00 2001
From: Stanislav Zidek <szidek@redhat.com>
Date: Fri, 16 Apr 2021 19:14:18 +0200
Subject: [PATCH] pam_userdb: Prevent garbage characters from db
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1791965
---
modules/pam_userdb/pam_userdb.8.xml | 3 +-
modules/pam_userdb/pam_userdb.c | 56 +++++++++++++++++------------
2 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/modules/pam_userdb/pam_userdb.8.xml b/modules/pam_userdb/pam_userdb.8.xml
index fa628ada..bce92850 100644
--- a/modules/pam_userdb/pam_userdb.8.xml
+++ b/modules/pam_userdb/pam_userdb.8.xml
@@ -100,7 +100,8 @@
</term>
<listitem>
<para>
- Print debug information.
+ Print debug information. Note that password hashes, both from db
+ and computed, will be printed to syslog.
</para>
</listitem>
</varlistentry>
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
index dc2ca232..d59801bf 100644
--- a/modules/pam_userdb/pam_userdb.c
+++ b/modules/pam_userdb/pam_userdb.c
@@ -194,7 +194,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
}
if (data.dptr != NULL) {
- int compare = 0;
+ int compare = -2;
if (ctrl & PAM_KEY_ONLY_ARG)
{
@@ -209,36 +209,48 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
char *cryptpw = NULL;
if (data.dsize < 13) {
- compare = -2;
+ /* hash is too short */
+ pam_syslog(pamh, LOG_INFO, "password hash in database is too short");
} else if (ctrl & PAM_ICASE_ARG) {
- compare = -2;
+ pam_syslog(pamh, LOG_INFO,
+ "case-insensitive comparison only works with plaintext passwords");
} else {
+ /* libdb is not guaranteed to produce null terminated strings */
+ char *pwhash = strndup(data.dptr, data.dsize);
+
+ if (pwhash == NULL) {
+ pam_syslog(pamh, LOG_CRIT, "strndup failed: data.dptr");
+ } else {
#ifdef HAVE_CRYPT_R
- struct crypt_data *cdata = NULL;
- cdata = malloc(sizeof(*cdata));
- if (cdata != NULL) {
- cdata->initialized = 0;
- cryptpw = crypt_r(pass, data.dptr, cdata);
- }
+ struct crypt_data *cdata = NULL;
+ cdata = malloc(sizeof(*cdata));
+ if (cdata == NULL) {
+ pam_syslog(pamh, LOG_CRIT, "malloc failed: struct crypt_data");
+ } else {
+ cdata->initialized = 0;
+ cryptpw = crypt_r(pass, pwhash, cdata);
+ }
#else
- cryptpw = crypt (pass, data.dptr);
+ cryptpw = crypt (pass, pwhash);
#endif
- if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
- compare = memcmp(data.dptr, cryptpw, data.dsize);
- } else {
- compare = -2;
- if (ctrl & PAM_DEBUG_ARG) {
- if (cryptpw)
- pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
- else
- pam_syslog(pamh, LOG_INFO, "crypt() returned NULL");
+ if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
+ compare = memcmp(data.dptr, cryptpw, data.dsize);
+ } else {
+ if (ctrl & PAM_DEBUG_ARG) {
+ if (cryptpw) {
+ pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
+ pam_syslog(pamh, LOG_INFO, "computed hash: %s", cryptpw);
+ } else {
+ pam_syslog(pamh, LOG_ERR, "crypt() returned NULL");
+ }
+ }
}
- }
#ifdef HAVE_CRYPT_R
- free(cdata);
+ free(cdata);
#endif
+ }
+ free(pwhash);
}
-
} else {
/* Unknown password encryption method -
--
2.30.2

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

@ -0,0 +1,712 @@
diff -up Linux-PAM-1.3.1/configure.ac.pam-usertype Linux-PAM-1.3.1/configure.ac
--- Linux-PAM-1.3.1/configure.ac.pam-usertype 2020-05-15 10:03:27.247468160 +0200
+++ Linux-PAM-1.3.1/configure.ac 2020-05-15 10:03:27.270468089 +0200
@@ -606,6 +606,27 @@ AC_SUBST([HAVE_KEY_MANAGEMENT], $HAVE_KE
AM_CONDITIONAL([HAVE_KEY_MANAGEMENT], [test "$have_key_syscalls" = 1])
+dnl
+dnl Get values for default uid ranges in login.defs used in pam_usertype
+dnl
+AC_ARG_WITH([uidmin], AS_HELP_STRING([--with-uidmin=<number>],[default value for regular user min uid (1000)]), opt_uidmin=$withval)
+if test x"$opt_uidmin" == x; then
+ opt_uidmin=1000
+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
+fi
+AC_DEFINE_UNQUOTED(PAM_USERTYPE_OVERFLOW_UID, $opt_kerneloverflowuid, [Kernel overflow uid.])
+
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 \
@@ -636,6 +657,7 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
modules/pam_timestamp/Makefile modules/pam_tty_audit/Makefile \
modules/pam_umask/Makefile \
modules/pam_unix/Makefile modules/pam_userdb/Makefile \
+ modules/pam_usertype/Makefile \
modules/pam_warn/Makefile modules/pam_wheel/Makefile \
modules/pam_xauth/Makefile doc/Makefile doc/specs/Makefile \
doc/man/Makefile doc/sag/Makefile doc/adg/Makefile \
diff -up Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/Makefile.am
--- Linux-PAM-1.3.1/modules/Makefile.am.pam-usertype 2020-05-15 10:03:27.247468160 +0200
+++ Linux-PAM-1.3.1/modules/Makefile.am 2020-05-15 10:03:27.270468089 +0200
@@ -12,7 +12,7 @@ SUBDIRS = pam_access pam_cracklib pam_de
pam_selinux pam_sepermit pam_shells pam_stress \
pam_succeed_if pam_time pam_timestamp \
pam_tty_audit pam_umask \
- pam_unix pam_userdb pam_warn pam_wheel pam_xauth
+ pam_unix pam_userdb pam_usertype pam_warn pam_wheel pam_xauth
CLEANFILES = *~
diff -up Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am
--- Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am.pam-usertype 2020-05-15 10:03:27.270468089 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/Makefile.am 2020-05-15 10:03:27.270468089 +0200
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk <kukuk@suse.de>
+# Copyright (c) 2020 Red Hat, Inc.
+#
+
+CLEANFILES = *~
+MAINTAINERCLEANFILES = $(MANS) README
+
+EXTRA_DIST = README ${MANS} ${XMLS} tst-pam_usertype
+
+TESTS = tst-pam_usertype
+
+man_MANS = pam_usertype.8
+
+XMLS = README.xml pam_usertype.8.xml
+
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ $(WARN_CFLAGS)
+AM_LDFLAGS = -no-undefined -avoid-version -module
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+
+securelib_LTLIBRARIES = pam_usertype.la
+pam_usertype_la_LIBADD = $(top_builddir)/libpam/libpam.la
+
+if ENABLE_REGENERATE_MAN
+noinst_DATA = README
+README: pam_usertype.8.xml
+-include $(top_srcdir)/Make.xml.rules
+endif
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml.pam-usertype 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 2020-05-15 10:03:27.270468089 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.8.xml 2020-05-15 10:03:27.270468089 +0200
@@ -0,0 +1,170 @@
+<?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='pam_usertype'>
+ <refmeta>
+ <refentrytitle>pam_usertype</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='sectdesc'>Linux-PAM</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='pam_usertype-name'>
+ <refname>pam_usertype</refname>
+ <refpurpose>check if the authenticated user is a system or regular account</refpurpose>
+ </refnamediv>
+
+
+ <refsynopsisdiv>
+ <cmdsynopsis id='pam_usertype-cmdsynopsis'>
+ <command>pam_usertype.so</command>
+ <arg choice='opt' rep='repeat'><replaceable>flag</replaceable></arg>
+ <arg choice='req'><replaceable>condition</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1 id='pam_usertype-description'>
+ <title>DESCRIPTION</title>
+ <para>
+ 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>
+ settings in <emphasis>/etc/login.defs</emphasis>. One use is to select
+ whether to load other modules based on this test.
+ </para>
+
+ <para>
+ The module should be given only one condition as module argument.
+ Authentication will succeed only if the condition is met.
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_usertype-options">
+ <title>OPTIONS</title>
+ <para>
+ The following <emphasis>flag</emphasis>s are supported:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>use_uid</option></term>
+ <listitem>
+ <para>
+ Evaluate conditions using the account of the user whose UID
+ the application is running under instead of the user being
+ authenticated.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>audit</option></term>
+ <listitem>
+ <para>
+ Log unknown users to the system log.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Available <emphasis>condition</emphasis>s are:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>issystem</option></term>
+ <listitem>
+ <para>Succeed if the user is a system user.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>isregular</option></term>
+ <listitem>
+ <para>Succeed if the user is a regular user.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="pam_usertype-types">
+ <title>MODULE TYPES PROVIDED</title>
+ <para>
+ All module types (<option>account</option>, <option>auth</option>,
+ <option>password</option> and <option>session</option>) are provided.
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_usertype-return_values'>
+ <title>RETURN VALUES</title>
+ <variablelist>
+
+ <varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ The condition was true.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_AUTH_ERR</term>
+ <listitem>
+ <para>
+ The condition was false.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_SERVICE_ERR</term>
+ <listitem>
+ <para>
+ A service error occurred or the arguments can't be
+ parsed correctly.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PAM_USER_UNKNOWN</term>
+ <listitem>
+ <para>
+ User was not found.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+
+ <refsect1 id='pam_usertype-examples'>
+ <title>EXAMPLES</title>
+ <para>
+ Skip remaining modules if the user is a system user:
+ </para>
+ <programlisting>
+account sufficient pam_usertype.so issystem
+ </programlisting>
+ </refsect1>
+
+ <refsect1 id='pam_usertype-see_also'>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id='pam_usertype-author'>
+ <title>AUTHOR</title>
+ <para>Pavel Březina &lt;pbrezina@redhat.com&gt;</para>
+ </refsect1>
+</refentry>
diff -up Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c
--- Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c.pam-usertype 2020-05-15 10:03:27.270468089 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/pam_usertype.c 2020-05-15 10:16:08.053198025 +0200
@@ -0,0 +1,394 @@
+/******************************************************************************
+ * Check user type based on login.defs.
+ *
+ * Copyright (c) 2020 Red Hat, Inc.
+ * Written by Pavel Březina <pbrezina@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 <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
+#define PAM_SM_SESSION
+#define PAM_SM_PASSWORD
+
+#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
+
+#define LOGIN_DEFS "/etc/login.defs"
+
+enum pam_usertype_op {
+ OP_IS_SYSTEM,
+ OP_IS_REGULAR,
+
+ OP_SENTINEL
+};
+
+struct pam_usertype_opts {
+ enum pam_usertype_op op;
+ int use_uid;
+ int audit;
+};
+
+static int
+pam_usertype_parse_args(struct pam_usertype_opts *opts,
+ pam_handle_t *pamh,
+ int argc,
+ const char **argv)
+{
+ int i;
+
+ memset(opts, 0, sizeof(struct pam_usertype_opts));
+ opts->op = OP_SENTINEL;
+
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "use_uid") == 0) {
+ opts->use_uid = 1;
+ } else if (strcmp(argv[i], "audit") == 0) {
+ opts->audit = 1;
+ } else if (strcmp(argv[i], "issystem") == 0) {
+ opts->op = OP_IS_SYSTEM;
+ } else if (strcmp(argv[i], "isregular") == 0) {
+ opts->op = OP_IS_REGULAR;
+ } else {
+ pam_syslog(pamh, LOG_WARNING, "Unknown argument: %s", argv[i]);
+ /* Just continue. */
+ }
+ }
+
+ if (opts->op == OP_SENTINEL) {
+ pam_syslog(pamh, LOG_ERR, "Operation not specified");
+ return PAM_SERVICE_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int
+pam_usertype_get_uid(struct pam_usertype_opts *opts,
+ pam_handle_t *pamh,
+ uid_t *_uid)
+{
+ struct passwd *pwd;
+ const void *prompt;
+ const char *username;
+ int ret;
+
+ /* Get uid of user that runs the application. */
+ if (opts->use_uid) {
+ pwd = pam_modutil_getpwuid(pamh, getuid());
+ if (pwd == NULL) {
+ pam_syslog(pamh, LOG_ERR,
+ "error retrieving information about user %lu",
+ (unsigned long)getuid());
+ return PAM_USER_UNKNOWN;
+ }
+
+ *_uid = pwd->pw_uid;
+ return PAM_SUCCESS;
+ }
+
+ /* Get uid of user that is being authenticated. */
+ ret = pam_get_item(pamh, PAM_USER_PROMPT, &prompt);
+ if (ret != PAM_SUCCESS || prompt == NULL || strlen(prompt) == 0) {
+ prompt = "login: ";
+ }
+
+ ret = pam_get_user(pamh, &username, prompt);
+ if (ret != PAM_SUCCESS || username == NULL) {
+ pam_syslog(pamh, LOG_ERR, "error retrieving user name: %s",
+ pam_strerror(pamh, ret));
+ return ret;
+ }
+
+ pwd = pam_modutil_getpwnam(pamh, username);
+ if (pwd == NULL) {
+ if (opts->audit) {
+ pam_syslog(pamh, LOG_NOTICE,
+ "error retrieving information about user %s", username);
+ }
+
+ return PAM_USER_UNKNOWN;
+ }
+
+ *_uid = pwd->pw_uid;
+
+ return PAM_SUCCESS;
+}
+
+#define MAX_UID_VALUE 0xFFFFFFFFUL
+
+/* lookup a value for key in login.defs file or similar key value format */
+char *
+pam_usertype_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;
+
+ 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 = "";
+
+ if (strcasecmp(tmp, key) == 0) {
+ retval = strdup(cp);
+ break;
+ }
+ }
+ fclose(fp);
+
+ free(buf);
+
+ return retval;
+}
+
+static uid_t
+pam_usertype_get_id(pam_handle_t *pamh,
+ const char *key,
+ uid_t default_value)
+{
+ unsigned long ul;
+ char *value;
+ char *ep;
+ uid_t uid;
+
+ value = pam_usertype_search_key(pamh, LOGIN_DEFS, key);
+ if (value == NULL) {
+ return default_value;
+ }
+
+ /* taken from get_lastlog_uid_max() */
+ ep = value + strlen(value);
+ while (ep > value && isspace(*(--ep))) {
+ *ep = '\0';
+ }
+
+ errno = 0;
+ ul = strtoul(value, &ep, 10);
+ if (!(ul >= MAX_UID_VALUE
+ || (uid_t)ul >= MAX_UID_VALUE
+ || (errno != 0 && ul == 0)
+ || value == ep
+ || *ep != '\0')) {
+ uid = (uid_t)ul;
+ } else {
+ uid = default_value;
+ }
+
+ free(value);
+
+ return uid;
+}
+
+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) {
+ pam_syslog(pamh, LOG_WARNING, "invalid uid");
+ 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;
+}
+
+static int
+pam_usertype_is_regular(pam_handle_t *pamh, uid_t uid)
+{
+ int ret;
+
+ ret = pam_usertype_is_system(pamh, uid);
+ switch (ret) {
+ case PAM_SUCCESS:
+ return PAM_AUTH_ERR;
+ case PAM_USER_UNKNOWN:
+ return PAM_USER_UNKNOWN;
+ default:
+ return PAM_SUCCESS;
+ }
+}
+
+static int
+pam_usertype_evaluate(struct pam_usertype_opts *opts,
+ pam_handle_t *pamh,
+ uid_t uid)
+{
+ switch (opts->op) {
+ case OP_IS_SYSTEM:
+ return pam_usertype_is_system(pamh, uid);
+ case OP_IS_REGULAR:
+ return pam_usertype_is_regular(pamh, uid);
+ default:
+ pam_syslog(pamh, LOG_ERR, "Unknown operation: %d", opts->op);
+ return PAM_SERVICE_ERR;
+ }
+}
+
+/**
+ * Arguments:
+ * - issystem: uid in <SYS_UID_MIN, 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
+ */
+int
+pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
+ int argc, const char **argv)
+{
+ struct pam_usertype_opts opts;
+ uid_t uid;
+ int ret;
+
+ ret = pam_usertype_parse_args(&opts, pamh, argc, argv);
+ if (ret != PAM_SUCCESS) {
+ return ret;
+ }
+
+ ret = pam_usertype_get_uid(&opts, pamh, &uid);
+ if (ret != PAM_SUCCESS) {
+ return ret;
+ }
+
+ return pam_usertype_evaluate(&opts, pamh, uid);
+}
+
+int
+pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED,
+ int argc UNUSED, const char **argv UNUSED)
+{
+ return PAM_IGNORE;
+}
+
+int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+int
+pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+int
+pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+int
+pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
diff -up Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/README.xml
--- Linux-PAM-1.3.1/modules/pam_usertype/README.xml.pam-usertype 2020-05-15 10:03:27.270468089 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/README.xml 2020-05-15 10:03:27.270468089 +0200
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+"http://www.docbook.org/xml/4.3/docbookx.dtd"
+[
+<!--
+<!ENTITY pamaccess SYSTEM "pam_usertype.8.xml">
+-->
+]>
+
+<article>
+
+ <articleinfo>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_usertype-name"]/*)'/>
+ </title>
+
+ </articleinfo>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-description"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-options"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-examples"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_usertype.8.xml" xpointer='xpointer(//refsect1[@id = "pam_usertype-author"]/*)'/>
+ </section>
+
+</article>
diff -up Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype
--- Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype.pam-usertype 2020-05-15 10:03:27.270468089 +0200
+++ Linux-PAM-1.3.1/modules/pam_usertype/tst-pam_usertype 2020-05-15 10:03:27.270468089 +0200
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../tests/tst-dlopen .libs/pam_usertype.so

@ -0,0 +1,33 @@
From e31dd6c7d0faa7a06d3ebd50a0b6957b9f822d15 Mon Sep 17 00:00:00 2001
From: Tomas Mraz <tmraz@fedoraproject.org>
Date: Wed, 7 Aug 2019 18:13:57 +0200
Subject: [PATCH] pam_tty_audit: Manual page clarification about password
logging
* modules/pam_tty_audit/pam_tty_audit.8.xml: Explanation why passwords
can be sometimes logged even when the option is not set.
---
modules/pam_tty_audit/pam_tty_audit.8.xml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/modules/pam_tty_audit/pam_tty_audit.8.xml b/modules/pam_tty_audit/pam_tty_audit.8.xml
index 59a3406..e346c68 100644
--- a/modules/pam_tty_audit/pam_tty_audit.8.xml
+++ b/modules/pam_tty_audit/pam_tty_audit.8.xml
@@ -149,6 +149,13 @@
greater than or equal to <replaceable>min_uid</replaceable> will be
matched.
</para>
+ <para>
+ Please note that passwords in some circumstances may be logged by TTY auditing
+ even if the <option>log_passwd</option> is not used. For example, all input to
+ an ssh session will be logged - even if there is a password being typed into
+ some software running at the remote host because only the local TTY state
+ affects the local TTY auditing.
+ </para>
</refsect1>
<refsect1 id='pam_tty_audit-examples'>
--
2.20.1

@ -0,0 +1,12 @@
diff -up Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c.unix-default-rounds Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c
--- Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c.unix-default-rounds 2023-11-02 09:59:54.533238124 +0100
+++ Linux-PAM-1.3.1/modules/pam_unix/pam_unix_passwd.c 2023-11-02 10:40:58.017404936 +0100
@@ -607,7 +607,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int
unsigned int ctrl, lctrl;
int retval;
int remember = -1;
- int rounds = -1;
+ int rounds = 0;
int pass_min_len = 0;
/* <DO NOT free() THESE> */

@ -0,0 +1,174 @@
From f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Thu, 15 Nov 2018 15:01:57 +0100
Subject: [PATCH] pam_unix: Use bcrypt b-variant for computing new hashes.
Bcrypt hashes used the "$2a$" prefix since 1997.
However, in 2011 an implementation bug was discovered in bcrypt
affecting the handling of characters in passphrases with the 8th
bit set.
Besides fixing the bug, OpenBSD 5.5 introduced the "$2b$" prefix
for a behavior that exactly matches crypt_blowfish's "$2y$", and
the crypt_blowfish implementation supports it as well since v1.1.
That said new computed bcrypt hashes should use the "$2b$" prefix.
* modules/pam_unix/passverify.c: Use bcrypt b-variant.
---
modules/pam_unix/passverify.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 9c1771e2..1f433b3a 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -385,7 +385,7 @@ PAMH_ARG_DECL(char * create_password_hash,
/* algoid = "$1" */
return crypt_md5_wrapper(password);
} else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
- algoid = "$2a$";
+ algoid = "$2b$";
} else if (on(UNIX_SHA256_PASS, ctrl)) {
algoid = "$5$";
} else if (on(UNIX_SHA512_PASS, ctrl)) {
--
2.41.0
diff -up Linux-PAM-1.3.1/configure.ac.legacy-xcrypt Linux-PAM-1.3.1/configure.ac
--- Linux-PAM-1.3.1/configure.ac.legacy-xcrypt 2023-10-26 12:08:46.896437225 +0200
+++ Linux-PAM-1.3.1/configure.ac 2023-10-26 12:10:38.289654696 +0200
@@ -395,19 +395,32 @@ AC_SUBST(LIBAUDIT)
AM_CONDITIONAL([HAVE_AUDIT_TTY_STATUS],
[test "x$HAVE_AUDIT_TTY_STATUS" = xyes])
-AC_CHECK_HEADERS(xcrypt.h crypt.h)
-AS_IF([test "x$ac_cv_header_xcrypt_h" = "xyes"],
- [crypt_libs="xcrypt crypt"],
- [crypt_libs="crypt"])
+AC_CHECK_HEADERS(crypt.h)
BACKUP_LIBS=$LIBS
-AC_SEARCH_LIBS([crypt],[$crypt_libs], LIBCRYPT="${ac_lib:+-l$ac_lib}", LIBCRYPT="")
-AC_CHECK_FUNCS(crypt_r crypt_gensalt_r)
+LIBCRYPT=""
+PKG_CHECK_MODULES([CRYPT], [libcrypt], [
+ CFLAGS="$CFLAGS $CRYPT_CFLAGS"
+ CPPFLAGS="$CPPFLAGS $CRYPT_CFLAGS"
+ LIBS="$LIBS $CRYPT_LIBS"
+ LIBCRYPT="$CRYPT_LIBS"
+], [
+ AC_SEARCH_LIBS([crypt_gensalt_rn],[crypt])
+ case "$ac_cv_search_crypt_gensalt_rn" in
+ -l*) LIBCRYPT="$ac_cv_search_crypt_gensalt_rn" ;;
+ no) AC_SEARCH_LIBS([crypt_r],[crypt])
+ case "$ac_cv_search_crypt_r" in
+ -l*) LIBCRYPT="$ac_cv_search_crypt_r" ;;
+ no ) AC_SEARCH_LIBS([crypt],[crypt])
+ case "$ac_cv_search_crypt" in
+ -l*) LIBCRYPT="$ac_cv_search_crypt" ;;
+ esac ;;
+ esac ;;
+ esac
+])
+AC_CHECK_FUNCS([crypt_r])
LIBS=$BACKUP_LIBS
AC_SUBST(LIBCRYPT)
-if test "$LIBCRYPT" = "-lxcrypt" -a "$ac_cv_header_xcrypt_h" = "yes" ; then
- AC_DEFINE([HAVE_LIBXCRYPT], 1, [Define to 1 if xcrypt support should be compiled in.])
-fi
AC_ARG_WITH([randomdev], AS_HELP_STRING([--with-randomdev=(<path>|yes|no)],[use specified random device instead of /dev/urandom or 'no' to disable]), opt_randomdev=$withval)
if test "$opt_randomdev" = yes -o -z "$opt_randomdev"; then
diff -up Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c
--- Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c.legacy-xcrypt 2023-10-26 12:08:46.896437225 +0200
+++ Linux-PAM-1.3.1/modules/pam_pwhistory/opasswd.c 2023-10-26 12:11:14.437725259 +0200
@@ -52,9 +52,7 @@
#include <stdarg.h>
#include <sys/stat.h>
-#if defined (HAVE_XCRYPT_H)
-#include <xcrypt.h>
-#elif defined (HAVE_CRYPT_H)
+#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
diff -up Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c
--- Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c.legacy-xcrypt 2017-02-10 11:10:15.000000000 +0100
+++ Linux-PAM-1.3.1/modules/pam_unix/bigcrypt.c 2023-10-26 12:08:46.896437225 +0200
@@ -29,9 +29,7 @@
#include <string.h>
#include <stdlib.h>
#include <security/_pam_macros.h>
-#ifdef HAVE_LIBXCRYPT
-#include <xcrypt.h>
-#elif defined(HAVE_CRYPT_H)
+#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
diff -up Linux-PAM-1.3.1/modules/pam_unix/passverify.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_unix/passverify.c
--- Linux-PAM-1.3.1/modules/pam_unix/passverify.c.legacy-xcrypt 2023-10-26 12:08:46.895437223 +0200
+++ Linux-PAM-1.3.1/modules/pam_unix/passverify.c 2023-10-26 12:16:25.470320408 +0200
@@ -19,9 +19,7 @@
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
-#ifdef HAVE_LIBXCRYPT
-#include <xcrypt.h>
-#elif defined(HAVE_CRYPT_H)
+#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
@@ -406,23 +404,19 @@ PAMH_ARG_DECL(char * create_password_has
return crypted;
}
-#ifdef HAVE_CRYPT_GENSALT_R
- if (on(UNIX_BLOWFISH_PASS, ctrl)) {
- char entropy[17];
- crypt_make_salt(entropy, sizeof(entropy) - 1);
- sp = crypt_gensalt_r (algoid, rounds,
- entropy, sizeof(entropy),
- salt, sizeof(salt));
- } else {
-#endif
- sp = stpcpy(salt, algoid);
- if (on(UNIX_ALGO_ROUNDS, ctrl)) {
- sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds);
- }
- crypt_make_salt(sp, 16);
-#ifdef HAVE_CRYPT_GENSALT_R
+#if defined(CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY) && CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY
+ /*
+ * Any version of libcrypt supporting auto entropy is
+ * guaranteed to have crypt_gensalt_rn().
+ */
+ sp = crypt_gensalt_rn(algoid, rounds, NULL, 0, salt, sizeof(salt));
+#else
+ sp = stpcpy(salt, algoid);
+ if (on(UNIX_ALGO_ROUNDS, ctrl)) {
+ sp += snprintf(sp, sizeof(salt) - (16 + 1 + (sp - salt)), "rounds=%u$", rounds);
}
-#endif
+ crypt_make_salt(sp, 16);
+#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */
#ifdef HAVE_CRYPT_R
sp = NULL;
cdata = malloc(sizeof(*cdata));
diff -up Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c.legacy-xcrypt Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c
--- Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c.legacy-xcrypt 2023-10-26 12:08:46.880437194 +0200
+++ Linux-PAM-1.3.1/modules/pam_userdb/pam_userdb.c 2023-10-26 12:08:46.896437225 +0200
@@ -17,9 +17,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
-#ifdef HAVE_LIBXCRYPT
-#include <xcrypt.h>
-#elif defined(HAVE_CRYPT_H)
+#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif

@ -0,0 +1,57 @@
From a6845905869ccabb5eb802be37241eabec085dc7 Mon Sep 17 00:00:00 2001
From: Tomas Mraz <tmraz@fedoraproject.org>
Date: Mon, 14 Oct 2019 16:52:46 +0200
Subject: [PATCH] pam_unix: Add logging useful for debugging problems
Two messages added about obtaining the username are guarded
by the debug option as these should not be normally
logged - they can be useful for debugging but they do not
indicate any special condition.
The message about authenticating user with blank password is
still just LOG_DEBUG priority but it is logged unconditionally
because it is somewhat extraordinary condition to have an user
with blank password.
* modules/pam_unix/pam_unix_auth.c (pam_sm_authenticate): Replace
D() macro calls which are not enabled on production builds with
regular pam_syslog() calls.
---
modules/pam_unix/pam_unix_auth.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c
index 681e49d..3fca945 100644
--- a/modules/pam_unix/pam_unix_auth.c
+++ b/modules/pam_unix/pam_unix_auth.c
@@ -130,15 +130,16 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
AUTH_RETURN;
}
if (on(UNIX_DEBUG, ctrl))
- D(("username [%s] obtained", name));
+ pam_syslog(pamh, LOG_DEBUG, "username [%s] obtained", name);
} else {
- D(("trouble reading username"));
if (retval == PAM_CONV_AGAIN) {
D(("pam_get_user/conv() function is not ready yet"));
/* it is safe to resume this function so we translate this
* retval to the value that indicates we're happy to resume.
*/
retval = PAM_INCOMPLETE;
+ } else if (on(UNIX_DEBUG, ctrl)) {
+ pam_syslog(pamh, LOG_DEBUG, "could not obtain username");
}
AUTH_RETURN;
}
@@ -146,7 +147,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
/* if this user does not have a password... */
if (_unix_blankpasswd(pamh, ctrl, name)) {
- D(("user '%s' has blank passwd", name));
+ pam_syslog(pamh, LOG_DEBUG, "user [%s] has blank password; authenticated without it", name);
name = NULL;
retval = PAM_SUCCESS;
AUTH_RETURN;
--
2.20.1

@ -0,0 +1,134 @@
From 6bf9b454eb971083f0cce49faa2aa1cde329ff5d Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Wed, 26 Aug 2020 14:44:23 +0200
Subject: [PATCH 1/3] pam_wheel: improve coding style
modules/pam_wheel/pam_wheel.c: improve indentation and explicitly state
condition statements
---
modules/pam_wheel/pam_wheel.c | 36 ++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c
index a025ebaf..94cb7d89 100644
--- a/modules/pam_wheel/pam_wheel.c
+++ b/modules/pam_wheel/pam_wheel.c
@@ -130,25 +130,27 @@ perform_check (pam_handle_t *pamh, int ctrl, const char *use_group)
}
if (ctrl & PAM_USE_UID_ARG) {
- tpwd = pam_modutil_getpwuid (pamh, getuid());
- if (!tpwd) {
- if (ctrl & PAM_DEBUG_ARG) {
+ tpwd = pam_modutil_getpwuid (pamh, getuid());
+ if (tpwd == NULL) {
+ if (ctrl & PAM_DEBUG_ARG) {
pam_syslog(pamh, LOG_NOTICE, "who is running me ?!");
- }
- return PAM_SERVICE_ERR;
- }
- fromsu = tpwd->pw_name;
+ }
+ return PAM_SERVICE_ERR;
+ }
+ fromsu = tpwd->pw_name;
} else {
- fromsu = pam_modutil_getlogin(pamh);
- if (fromsu) {
- tpwd = pam_modutil_getpwnam (pamh, fromsu);
- }
- if (!fromsu || !tpwd) {
- if (ctrl & PAM_DEBUG_ARG) {
- pam_syslog(pamh, LOG_NOTICE, "who is running me ?!");
- }
- return PAM_SERVICE_ERR;
- }
+ fromsu = pam_modutil_getlogin(pamh);
+
+ if (fromsu != NULL) {
+ tpwd = pam_modutil_getpwnam (pamh, fromsu);
+ }
+
+ if (fromsu == NULL || tpwd == NULL) {
+ if (ctrl & PAM_DEBUG_ARG) {
+ pam_syslog(pamh, LOG_NOTICE, "who is running me ?!");
+ }
+ return PAM_SERVICE_ERR;
+ }
}
/*
--
2.26.2
From 9091ea1d81e85f49a221b0325d27b22ce69e444a Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Thu, 27 Aug 2020 09:16:15 +0200
Subject: [PATCH 2/3] pam_wheel: if getlogin fails fallback to PAM_RUSER
modules/pam_wheel/pam_wheel.c: if getlogin fails to obtain the real user
ID, then try with PAM_RUSER.
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1866866
---
modules/pam_wheel/pam_wheel.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c
index 94cb7d89..7fa3cfa9 100644
--- a/modules/pam_wheel/pam_wheel.c
+++ b/modules/pam_wheel/pam_wheel.c
@@ -141,6 +141,16 @@ perform_check (pam_handle_t *pamh, int ctrl, const char *use_group)
} else {
fromsu = pam_modutil_getlogin(pamh);
+ /* if getlogin fails try a fallback to PAM_RUSER */
+ if (fromsu == NULL) {
+ const char *rhostname;
+
+ retval = pam_get_item(pamh, PAM_RHOST, (const void **)&rhostname);
+ if (retval != PAM_SUCCESS || rhostname == NULL) {
+ retval = pam_get_item(pamh, PAM_RUSER, (const void **)&fromsu);
+ }
+ }
+
if (fromsu != NULL) {
tpwd = pam_modutil_getpwnam (pamh, fromsu);
}
--
2.26.2
From a3a5cbf86083c43026b558e2023f597530626267 Mon Sep 17 00:00:00 2001
From: ikerexxe <ipedrosa@redhat.com>
Date: Wed, 9 Sep 2020 10:32:03 +0200
Subject: [PATCH 3/3] pam_wheel: clarify use_uid option in man page
modules/pam_wheel/pam_wheel.8.xml: indicate that use_uid option uses the
real uid of the calling process.
---
modules/pam_wheel/pam_wheel.8.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/modules/pam_wheel/pam_wheel.8.xml b/modules/pam_wheel/pam_wheel.8.xml
index b32f5e2b..ee8c7d26 100644
--- a/modules/pam_wheel/pam_wheel.8.xml
+++ b/modules/pam_wheel/pam_wheel.8.xml
@@ -122,9 +122,9 @@
</term>
<listitem>
<para>
- The check for wheel membership will be done against
- the current uid instead of the original one (useful when
- jumping with su from one account to another for example).
+ The check will be done against the real uid of the calling process,
+ instead of trying to obtain the user from the login session
+ associated with the terminal in use.
</para>
</listitem>
</varlistentry>
--
2.26.2

@ -1,24 +0,0 @@
diff -up Linux-PAM-1.5.0/doc/Makefile.am.noflex Linux-PAM-1.5.0/doc/Makefile.am
--- Linux-PAM-1.5.0/doc/Makefile.am.noflex 2020-11-10 16:46:13.000000000 +0100
+++ Linux-PAM-1.5.0/doc/Makefile.am 2020-11-11 11:39:00.980421433 +0100
@@ -2,7 +2,7 @@
# Copyright (c) 2005, 2006 Thorsten Kukuk <kukuk@suse.de>
#
-SUBDIRS = man specs sag adg mwg
+SUBDIRS = man sag adg mwg
CLEANFILES = *~
diff -up Linux-PAM-1.5.0/Makefile.am.noflex Linux-PAM-1.5.0/Makefile.am
--- Linux-PAM-1.5.0/Makefile.am.noflex 2020-11-11 11:39:00.980421433 +0100
+++ Linux-PAM-1.5.0/Makefile.am 2020-11-11 11:39:15.887625418 +0100
@@ -4,7 +4,7 @@
AUTOMAKE_OPTIONS = 1.9 gnu dist-xz no-dist-gzip check-news
-SUBDIRS = libpam tests libpamc libpam_misc modules po conf examples xtests
+SUBDIRS = libpam tests libpamc libpam_misc modules po doc examples xtests
if HAVE_DOC
SUBDIRS += doc

@ -1,25 +0,0 @@
diff -up Linux-PAM-1.5.0/configure.ac.redhat-modules Linux-PAM-1.5.0/configure.ac
--- Linux-PAM-1.5.0/configure.ac.redhat-modules 2020-11-11 11:21:21.947857371 +0100
+++ Linux-PAM-1.5.0/configure.ac 2020-11-11 11:22:58.638193747 +0100
@@ -639,6 +639,8 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
po/Makefile.in \
Make.xml.rules \
modules/Makefile \
+ modules/pam_chroot/Makefile modules/pam_console/Makefile \
+ modules/pam_postgresok/Makefile \
modules/pam_access/Makefile \
modules/pam_debug/Makefile modules/pam_deny/Makefile \
modules/pam_echo/Makefile modules/pam_env/Makefile \
diff -up Linux-PAM-1.5.0/modules/Makefile.am.redhat-modules Linux-PAM-1.5.0/modules/Makefile.am
--- Linux-PAM-1.5.0/modules/Makefile.am.redhat-modules 2020-11-10 16:46:13.000000000 +0100
+++ Linux-PAM-1.5.0/modules/Makefile.am 2020-11-11 11:21:21.947857371 +0100
@@ -47,6 +47,9 @@ SUBDIRS := \
pam_debug \
pam_deny \
pam_echo \
+ pam_chroot \
+ pam_console \
+ pam_postgresok \
pam_env \
pam_exec \
pam_faildelay \

@ -1,72 +0,0 @@
From c85513220c1bd3150e39c6277422d29cfa44acc7 Mon Sep 17 00:00:00 2001
From: Steve Grubb <sgrubb@redhat.com>
Date: Thu, 27 Jul 2023 13:14:42 -0400
Subject: [PATCH 1/2] pam_faillock: fix formatting of audit messages
pam_faillock uses audit_log_user_message to write to the audit system.
It does not take an op argument, so you have to add one yourself. Otherwise
the pam_faillock part of the message is lost because it's not in key=value
format.
Also, we can't use uid in that event because the kernel already adds that
field. What we normally do is use 'suid' (meaning sender uid) as the
field name.
---
modules/pam_faillock/pam_faillock.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c
index ca1c7035..a89909ab 100644
--- a/modules/pam_faillock/pam_faillock.c
+++ b/modules/pam_faillock/pam_faillock.c
@@ -248,7 +248,7 @@ check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
(void)pam_get_item(pamh, PAM_TTY, &tty);
(void)pam_get_item(pamh, PAM_RHOST, &rhost);
- snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid);
+ snprintf(buf, sizeof(buf), "op=pam_faillock suid=%u ", opts->uid);
audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf,
rhost, NULL, tty, 1);
}
@@ -364,7 +364,7 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies
errno == EAFNOSUPPORT))
return PAM_SYSTEM_ERR;
- snprintf(buf, sizeof(buf), "pam_faillock uid=%u ", opts->uid);
+ snprintf(buf, sizeof(buf), "op=pam_faillock suid=%u ", opts->uid);
audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf,
NULL, NULL, NULL, 1);
--
2.41.0
From 1648734a69c31e9ce834da70144ac9a453296807 Mon Sep 17 00:00:00 2001
From: Steve Grubb <sgrubb@redhat.com>
Date: Fri, 4 Aug 2023 17:45:45 -0400
Subject: [PATCH 2/2] pam_selinux: fix formatting of audit messages
pam_selinux uses audit_log_user_message to write to the audit system.
It does not take an op argument, so you have to add one yourself. Otherwise
the pam_selinux part of the message is lost because it's not in key=value
format.
---
modules/pam_selinux/pam_selinux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c
index e52e0fc4..713b3f73 100644
--- a/modules/pam_selinux/pam_selinux.c
+++ b/modules/pam_selinux/pam_selinux.c
@@ -97,7 +97,7 @@ send_audit_message(const pam_handle_t *pamh, int success, const char *default_co
pam_syslog(pamh, LOG_ERR, "Error translating selected context '%s'.", selected_context);
selected_raw = NULL;
}
- if (asprintf(&msg, "pam: default-context=%s selected-context=%s",
+ if (asprintf(&msg, "op=pam_selinux default-context=%s selected-context=%s",
default_raw ? default_raw : (default_context ? default_context : "?"),
selected_raw ? selected_raw : (selected_context ? selected_context : "?")) < 0) {
msg = NULL; /* asprintf leaves msg in undefined state on failure */
--
2.41.0

@ -1,36 +0,0 @@
From d54870f993e97fe75e2cd0470a3701d5af22877c Mon Sep 17 00:00:00 2001
From: Changqing Li <changqing.li@windriver.com>
Date: Tue, 12 Jan 2021 14:45:34 +0800
Subject: [PATCH] faillock: create tallydir before creating tallyfile
The default tallydir is "/var/run/faillock", and this default
tallydir may not exist.
Function open may fail as tallydir does not exist when creating
the tallyfile. Therefore, faillock will not work well.
Fix this problem by creating tallydir before creating tallyfile
when the tallydir does not exist.
Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
modules/pam_faillock/faillock.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/modules/pam_faillock/faillock.c b/modules/pam_faillock/faillock.c
index 4ea94cbe..091f253a 100644
--- a/modules/pam_faillock/faillock.c
+++ b/modules/pam_faillock/faillock.c
@@ -74,6 +74,9 @@ open_tally (const char *dir, const char *user, uid_t uid, int create)
if (create) {
flags |= O_CREAT;
+ if (access(dir, F_OK) != 0) {
+ mkdir(dir, 0755);
+ }
}
fd = open(path, flags, 0660);
--
2.43.0

@ -1,55 +0,0 @@
diff -up Linux-PAM-1.5.1/configure.ac.libpam-close-range Linux-PAM-1.5.1/configure.ac
--- Linux-PAM-1.5.1/configure.ac.libpam-close-range 2023-11-10 10:35:00.142833269 +0100
+++ Linux-PAM-1.5.1/configure.ac 2023-11-10 10:36:29.158987392 +0100
@@ -552,6 +552,7 @@ AC_CHECK_FUNCS(inet_ntop inet_pton innet
AC_CHECK_FUNCS(quotactl)
AC_CHECK_FUNCS(unshare)
AC_CHECK_FUNCS([ruserok_af ruserok], [break])
+AC_CHECK_FUNCS(close_range)
BACKUP_LIBS=$LIBS
LIBS="$LIBS -lutil"
AC_CHECK_FUNCS([logwtmp])
diff -up Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c.libpam-close-range Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c
--- Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c.libpam-close-range 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/libpam/pam_modutil_sanitize.c 2023-11-10 10:35:00.142833269 +0100
@@ -11,6 +11,10 @@
#include <syslog.h>
#include <sys/resource.h>
+#ifndef CLOSE_RANGE_UNSHARE
+#define CLOSE_RANGE_UNSHARE (1U << 1)
+#endif /* CLOSE_RANGE_UNSHARE */
+
/*
* Creates a pipe, closes its write end, redirects fd to its read end.
* Returns fd on success, -1 otherwise.
@@ -84,9 +88,8 @@ redirect_out(pam_handle_t *pamh, enum pa
return fd;
}
-/* Closes all descriptors after stderr. */
static void
-close_fds(void)
+close_fds_iteratively(void)
{
/*
* An arbitrary upper limit for the maximum file descriptor number
@@ -111,6 +114,18 @@ close_fds(void)
close(fd);
}
+/* Closes all descriptors after stderr. */
+static void
+close_fds(void)
+{
+#ifdef HAVE_CLOSE_RANGE
+ if (close_range(STDERR_FILENO+1, -1U, CLOSE_RANGE_UNSHARE) == 0)
+ return;
+#endif /* HAVE_CLOSE_RANGE */
+
+ close_fds_iteratively();
+}
+
int
pam_modutil_sanitize_helper_fds(pam_handle_t *pamh,
enum pam_modutil_redirect_fd stdin_mode,

@ -1,654 +0,0 @@
diff -up Linux-PAM-1.5.1/libpam/pam_handlers.c.libpam-support-long-lines Linux-PAM-1.5.1/libpam/pam_handlers.c
--- Linux-PAM-1.5.1/libpam/pam_handlers.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/libpam/pam_handlers.c 2024-06-18 10:07:12.434785557 +0200
@@ -17,21 +17,30 @@
#include <fcntl.h>
#include <unistd.h>
-#define BUF_SIZE 1024
#define MODULE_CHUNK 4
#define UNKNOWN_MODULE "<*unknown module*>"
#ifndef _PAM_ISA
#define _PAM_ISA "."
#endif
-static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
+struct line_buffer {
+ char *assembled;
+ char *chunk;
+ size_t chunk_size;
+ size_t len;
+ size_t size;
+};
+
+static void _pam_buffer_init(struct line_buffer *buffer);
+
+static int _pam_assemble_line(FILE *f, struct line_buffer *buf);
static void _pam_free_handlers_aux(struct handler **hp);
static int _pam_add_handler(pam_handle_t *pamh
, int must_fail, int other, int stack_level, int type
, int *actions, const char *mod_path
- , int argc, char **argv, int argvlen);
+ , int argc, char **argv, size_t argvlen);
/* Values for module type */
@@ -59,12 +68,15 @@ static int _pam_parse_conf_file(pam_hand
#endif /* PAM_READ_BOTH_CONFS */
)
{
- char buf[BUF_SIZE];
+ struct line_buffer buffer;
int x; /* read a line from the FILE *f ? */
+
+ _pam_buffer_init(&buffer);
/*
* read a line from the configuration (FILE *) f
*/
- while ((x = _pam_assemble_line(f, buf, BUF_SIZE)) > 0) {
+ while ((x = _pam_assemble_line(f, &buffer)) > 0) {
+ char *buf = buffer.assembled;
char *tok, *nexttok=NULL;
const char *this_service;
const char *mod_path;
@@ -74,7 +86,7 @@ static int _pam_parse_conf_file(pam_hand
int handler_type = PAM_HT_MODULE; /* regular handler from a module */
int argc;
char **argv;
- int argvlen;
+ size_t argvlen;
D(("_pam_init_handler: LINE: %s", buf));
if (known_service != NULL) {
@@ -233,10 +245,11 @@ static int _pam_parse_conf_file(pam_hand
if (nexttok != NULL) {
D(("list: %s",nexttok));
argvlen = _pam_mkargv(nexttok, &argv, &argc);
- D(("argvlen = %d",argvlen));
+ D(("argvlen = %zu",argvlen));
} else { /* there are no arguments so fix by hand */
D(("_pam_init_handlers: empty argument list"));
- argvlen = argc = 0;
+ argvlen = 0;
+ argc = 0;
argv = NULL;
}
@@ -557,88 +570,243 @@ int _pam_init_handlers(pam_handle_t *pam
return PAM_SUCCESS;
}
+static int _pam_buffer_add(struct line_buffer *buffer, char *start, char *end)
+{
+ size_t len = end - start;
+
+ D(("assembled: [%zu/%zu] '%s', adding [%zu] '%s'",
+ buffer->len, buffer->size,
+ buffer->assembled == NULL ? "" : buffer->assembled, len, start));
+
+ if (start == end)
+ return 0;
+
+ if (buffer->assembled == NULL && buffer->chunk == start) {
+ /* no extra allocation needed, just move chunk to assembled */
+ buffer->assembled = buffer->chunk;
+ buffer->len = len;
+ buffer->size = buffer->chunk_size;
+
+ buffer->chunk = NULL;
+ buffer->chunk_size = 0;
+
+ D(("exiting with quick exchange"));
+ return 0;
+ }
+
+ if (buffer->len + len + 1 > buffer->size) {
+ size_t size;
+ char *p;
+
+ size = buffer->len + len + 1;
+ if ((p = realloc(buffer->assembled, size)) == NULL)
+ return -1;
+
+ buffer->assembled = p;
+ buffer->size = size;
+ }
+
+ memcpy(buffer->assembled + buffer->len, start, len);
+ buffer->len += len;
+ buffer->assembled[buffer->len] = '\0';
+
+ D(("exiting"));
+ return 0;
+}
+
+static inline int _pam_buffer_add_eol(struct line_buffer *buffer,
+ char *start, char *end)
+{
+ if (buffer->assembled != NULL || (*start != '\0' && *start != '\n'))
+ return _pam_buffer_add(buffer, start, end);
+ return 0;
+}
+
+static void _pam_buffer_clear(struct line_buffer *buffer)
+{
+ _pam_drop(buffer->assembled);
+ _pam_drop(buffer->chunk);
+ buffer->chunk_size = 0;
+ buffer->len = 0;
+ buffer->size = 0;
+}
+
+static void _pam_buffer_init(struct line_buffer *buffer)
+{
+ buffer->assembled = NULL;
+ buffer->chunk = NULL;
+ _pam_buffer_clear(buffer);
+}
+
+static void _pam_buffer_purge(struct line_buffer *buffer)
+{
+ _pam_drop(buffer->chunk);
+ buffer->chunk_size = 0;
+}
+
+static void _pam_buffer_shift(struct line_buffer *buffer)
+{
+ if (buffer->assembled == NULL)
+ return;
+
+ _pam_buffer_purge(buffer);
+ buffer->chunk = buffer->assembled;
+ buffer->chunk_size = buffer->size;
+
+ buffer->assembled = NULL;
+ buffer->size = 0;
+ buffer->len = 0;
+}
+
+static inline int _pam_buffer_valid(struct line_buffer *buffer)
+{
+ return buffer->assembled != NULL && *buffer->assembled != '\0';
+}
+
+/*
+ * Trim string to relevant parts of a configuration line.
+ *
+ * Preceding whitespaces are skipped and comment (#) marks the end of
+ * configuration line.
+ *
+ * Returns start of configuration line.
+ */
+static inline char *_pam_str_trim(char *str)
+{
+ /* skip leading spaces */
+ str += strspn(str, " \t");
+ /*
+ * we are only interested in characters before the first '#'
+ * character
+ */
+ str[strcspn(str, "#")] = '\0';
+
+ return str;
+}
+
+/*
+ * Remove escaped newline from end of string.
+ *
+ * Configuration lines may span across multiple lines in a file
+ * by ending a line with a backslash (\).
+ *
+ * If an escaped newline is encountered, the backslash will be
+ * replaced with a blank ' ' and the newline itself removed.
+ * Then the variable "end" will point to the new end of line.
+ *
+ * Returns 0 if escaped newline was found and replaced, 1 otherwise.
+ */
+static inline int _pam_str_unescnl(char *start, char **end)
+{
+ int ret = 1;
+ char *p = *end;
+
+ /*
+ * Check for backslash by scanning back from the end of
+ * the entered line, the '\n' should be included since
+ * normally a line is terminated with this character.
+ */
+ while (p > start && ((*--p == ' ') || (*p == '\t') || (*p == '\n')))
+ ;
+ if (*p == '\\') {
+ *p++ = ' '; /* replace backslash with ' ' */
+ *p = '\0'; /* truncate the line here */
+ *end = p;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
+ * Prepare line from file for configuration line parsing.
+ *
+ * A configuration line may span across multiple lines in a file.
+ * Remove comments and skip preceding whitespaces.
+ *
+ * Returns 0 if line spans across multiple lines, 1 if
+ * end of line is encountered.
+ */
+static inline int _pam_str_prepare(char *line, ssize_t len,
+ char **start, char **end)
+{
+ int ret;
+
+ *start = line;
+ *end = line + len;
+
+ ret = _pam_str_unescnl(*start, end) || strchr(*start, '#') != NULL;
+
+ *start = _pam_str_trim(*start);
+
+ return ret;
+}
+
/*
* This is where we read a line of the PAM config file. The line may be
* preceded by lines of comments and also extended with "\\\n"
+ *
+ * Returns 0 on EOF, 1 on successful line parsing, or -1 on error.
*/
-static int _pam_assemble_line(FILE *f, char *buffer, int buf_len)
+static int _pam_assemble_line(FILE *f, struct line_buffer *buffer)
{
- char *p = buffer;
- char *endp = buffer + buf_len;
- char *s, *os;
- int used = 0;
+ int ret = 0;
/* loop broken with a 'break' when a non-'\\n' ended line is read */
D(("called."));
+
+ _pam_buffer_shift(buffer);
+
for (;;) {
- if (p >= endp) {
- /* Overflow */
- D(("_pam_assemble_line: overflow"));
- return -1;
- }
- if (fgets(p, endp - p, f) == NULL) {
- if (used) {
+ char *start, *end;
+ ssize_t n;
+ int eol;
+
+ if ((n = getline(&buffer->chunk, &buffer->chunk_size, f)) == -1) {
+ if (ret) {
/* Incomplete read */
- return -1;
+ ret = -1;
} else {
/* EOF */
- return 0;
+ ret = 0;
}
+ break;
}
- /* skip leading spaces --- line may be blank */
-
- s = p + strspn(p, " \n\t");
- if (*s && (*s != '#')) {
- os = s;
-
- /*
- * we are only interested in characters before the first '#'
- * character
- */
-
- while (*s && *s != '#')
- ++s;
- if (*s == '#') {
- *s = '\0';
- used += strlen(os);
- break; /* the line has been read */
- }
-
- s = os;
-
- /*
- * Check for backslash by scanning back from the end of
- * the entered line, the '\n' has been included since
- * normally a line is terminated with this
- * character. fgets() should only return one though!
- */
-
- s += strlen(s);
- while (s > os && ((*--s == ' ') || (*s == '\t')
- || (*s == '\n')));
-
- /* check if it ends with a backslash */
- if (*s == '\\') {
- *s++ = ' '; /* replace backslash with ' ' */
- *s = '\0'; /* truncate the line here */
- used += strlen(os);
- p = s; /* there is more ... */
- } else {
- /* End of the line! */
- used += strlen(os);
- break; /* this is the complete line */
- }
+ eol = _pam_str_prepare(buffer->chunk, n, &start, &end);
+ if (eol) {
+ if (_pam_buffer_add_eol(buffer, start, end)) {
+ ret = -1;
+ break;
+ }
+ if (_pam_buffer_valid(buffer)) {
+ /* Successfully parsed a line */
+ ret = 1;
+ break;
+ }
+ /* Start parsing next line */
+ _pam_buffer_shift(buffer);
+ ret = 0;
} else {
- /* Nothing in this line */
- /* Don't move p */
+ /* Configuration line spans across multiple lines in file */
+ if (_pam_buffer_add(buffer, start, end)) {
+ ret = -1;
+ break;
+ }
+ /* Keep parsing line */
+ ret = 1;
}
}
- return used;
+ if (ret == 1)
+ _pam_buffer_purge(buffer);
+ else
+ _pam_buffer_clear(buffer);
+
+ return ret;
}
static char *
@@ -777,7 +945,7 @@ _pam_load_module(pam_handle_t *pamh, con
int _pam_add_handler(pam_handle_t *pamh
, int handler_type, int other, int stack_level, int type
, int *actions, const char *mod_path
- , int argc, char **argv, int argvlen)
+ , int argc, char **argv, size_t argvlen)
{
struct loaded_module *mod = NULL;
struct handler **handler_p;
diff -up Linux-PAM-1.5.1/libpam/pam_misc.c.libpam-support-long-lines Linux-PAM-1.5.1/libpam/pam_misc.c
--- Linux-PAM-1.5.1/libpam/pam_misc.c.libpam-support-long-lines 2024-06-18 09:52:38.726482849 +0200
+++ Linux-PAM-1.5.1/libpam/pam_misc.c 2024-06-18 10:02:13.132973447 +0200
@@ -39,6 +39,8 @@
#include <stdarg.h>
#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
@@ -163,60 +164,55 @@ char *_pam_memdup(const char *x, int len
/* Generate argv, argc from s */
/* caller must free(argv) */
-int _pam_mkargv(const char *s, char ***argv, int *argc)
+size_t _pam_mkargv(const char *s, char ***argv, int *argc)
{
- int l;
- int argvlen = 0;
- char *sbuf, *sbuf_start;
+ size_t l;
+ size_t argvlen = 0;
char **our_argv = NULL;
- char **argvbuf;
- char *argvbufp;
-#ifdef PAM_DEBUG
- int count=0;
-#endif
- D(("_pam_mkargv called: %s",s));
+ D(("called: %s",s));
*argc = 0;
l = strlen(s);
- if (l) {
- if ((sbuf = sbuf_start = _pam_strdup(s)) == NULL) {
- pam_syslog(NULL, LOG_CRIT,
- "pam_mkargv: null returned by _pam_strdup");
- D(("arg NULL"));
+ if (l && l < SIZE_MAX / (sizeof(char) + sizeof(char *))) {
+ char **argvbuf;
+ /* Overkill on the malloc, but not large */
+ argvlen = (l + 1) * (sizeof(char) + sizeof(char *));
+ if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
+ pam_syslog(NULL, LOG_CRIT, "pam_mkargv: null returned by malloc");
+ argvlen = 0;
} else {
- /* Overkill on the malloc, but not large */
- argvlen = (l + 1) * ((sizeof(char)) + sizeof(char *));
- if ((our_argv = argvbuf = malloc(argvlen)) == NULL) {
- pam_syslog(NULL, LOG_CRIT,
- "pam_mkargv: null returned by malloc");
- } else {
- char *tmp=NULL;
-
- argvbufp = (char *) argvbuf + (l * sizeof(char *));
- D(("[%s]",sbuf));
- while ((sbuf = _pam_StrTok(sbuf, " \n\t", &tmp))) {
- D(("arg #%d",++count));
- D(("->[%s]",sbuf));
- strcpy(argvbufp, sbuf);
- D(("copied token"));
- *argvbuf = argvbufp;
- argvbufp += strlen(argvbufp) + 1;
- D(("stepped in argvbufp"));
- (*argc)++;
- argvbuf++;
- sbuf = NULL;
- D(("loop again?"));
+ char *argvbufp;
+ char *tmp=NULL;
+ char *tok;
+#ifdef PAM_DEBUG
+ unsigned count=0;
+#endif
+ argvbufp = (char *) argvbuf + (l * sizeof(char *));
+ strcpy(argvbufp, s);
+ D(("[%s]",argvbufp));
+ while ((tok = _pam_StrTok(argvbufp, " \n\t", &tmp))) {
+ D(("arg #%u",++count));
+ D(("->[%s]",tok));
+ *argvbuf++ = tok;
+ if (*argc == INT_MAX) {
+ pam_syslog(NULL, LOG_CRIT,
+ "pam_mkargv: too many arguments");
+ argvlen = 0;
+ _pam_drop(our_argv);
+ break;
}
+ (*argc)++;
+ argvbufp = NULL;
+ D(("loop again?"));
}
- _pam_drop(sbuf_start);
}
}
*argv = our_argv;
- D(("_pam_mkargv returned"));
+ D(("exiting"));
return(argvlen);
}
diff -up Linux-PAM-1.5.1/libpam/pam_private.h.libpam-support-long-lines Linux-PAM-1.5.1/libpam/pam_private.h
--- Linux-PAM-1.5.1/libpam/pam_private.h.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/libpam/pam_private.h 2024-06-18 09:52:38.726482849 +0200
@@ -16,6 +16,7 @@
#include "config.h"
+#include <stddef.h>
#include <syslog.h>
#include <security/pam_appl.h>
@@ -272,7 +273,7 @@ char *_pam_strdup(const char *s);
char *_pam_memdup(const char *s, int len);
-int _pam_mkargv(const char *s, char ***argv, int *argc);
+size_t _pam_mkargv(const char *s, char ***argv, int *argc);
void _pam_sanitize(pam_handle_t *pamh);
diff -up Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c
--- Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_exec/pam_exec.c 2024-06-18 09:52:38.725482846 +0200
@@ -407,7 +407,7 @@ call_exec (const char *pam_type, pam_han
_exit (err);
}
- arggv = calloc (argc + 4, sizeof (char *));
+ arggv = calloc ((size_t) argc + 1, sizeof (char *));
if (arggv == NULL)
_exit (ENOMEM);
diff -up Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c
--- Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c.libpam-support-long-lines 2024-06-18 09:52:38.725482846 +0200
+++ Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c 2024-06-18 09:54:17.102732759 +0200
@@ -96,7 +96,8 @@ static int process_args(pam_handle_t *pa
char **levp;
const char *user = NULL;
const void *tmp;
- int i,size, retval;
+ int i, retval;
+ size_t size;
*filtername = *++argv;
if (ctrl & FILTER_DEBUG) {
diff -up Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c
--- Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_motd/pam_motd.c 2024-06-18 09:55:44.530954883 +0200
@@ -71,14 +71,14 @@ static void try_to_display_fd(pam_handle
* 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, unsigned int *out_num_strs)
+ char ***out_arg_split, size_t *out_num_strs)
{
char *arg_extracted = NULL;
const char *arg_ptr = arg;
char **arg_split = NULL;
char delim_str[2];
- unsigned int i = 0;
- unsigned int num_strs = 0;
+ size_t i = 0;
+ size_t num_strs = 0;
int retval = 0;
delim_str[0] = delim;
@@ -172,13 +172,13 @@ static int filter_dirents(const struct d
}
static void try_to_display_directories_with_overrides(pam_handle_t *pamh,
- char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing)
+ char **motd_dir_path_split, size_t num_motd_dirs, int report_missing)
{
struct dirent ***dirscans = NULL;
unsigned int *dirscans_sizes = NULL;
unsigned int dirscans_size_total = 0;
char **dirnames_all = NULL;
- unsigned int i;
+ size_t i;
int i_dirnames = 0;
if (pamh == NULL || motd_dir_path_split == NULL) {
@@ -304,9 +304,8 @@ static int drop_privileges(pam_handle_t
}
static int try_to_display(pam_handle_t *pamh, char **motd_path_split,
- unsigned int num_motd_paths,
- char **motd_dir_path_split,
- unsigned int num_motd_dir_paths, int report_missing)
+ size_t num_motd_paths, char **motd_dir_path_split,
+ size_t num_motd_dir_paths, int report_missing)
{
PAM_MODUTIL_DEF_PRIVS(privs);
@@ -316,7 +315,7 @@ static int try_to_display(pam_handle_t *
}
if (motd_path_split != NULL) {
- unsigned int i;
+ size_t i;
for (i = 0; i < num_motd_paths; i++) {
int fd = open(motd_path_split[i], O_RDONLY, 0);
@@ -354,11 +353,11 @@ int pam_sm_open_session(pam_handle_t *pa
int retval = PAM_IGNORE;
const char *motd_path = NULL;
char *motd_path_copy = NULL;
- unsigned int num_motd_paths = 0;
+ size_t num_motd_paths = 0;
char **motd_path_split = NULL;
const char *motd_dir_path = NULL;
char *motd_dir_path_copy = NULL;
- unsigned int num_motd_dir_paths = 0;
+ size_t num_motd_dir_paths = 0;
char **motd_dir_path_split = NULL;
int report_missing;
diff -up Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c.libpam-support-long-lines Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c
--- Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c.libpam-support-long-lines 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_permit/tst-pam_permit-retval.c 2024-06-18 09:52:38.726482849 +0200
@@ -52,6 +52,35 @@ main(void)
ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
pamh = NULL;
+ /* Perform a test dedicated to configuration file parsing. */
+ ASSERT_NE(NULL, fp = fopen(service_file, "w"));
+ ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n"
+ "# ignore escaped newlines in comments \\\n"
+ "auth required \\\n"
+ " %s/.libs/%s.so\n"
+ "# allow unneeded whitespaces\n"
+ " account required %s/.libs/%s.so%c\\\n"
+ "line after NUL byte continues up to here\n"
+ "password required %s/.libs/%s.so # eol comment\n"
+ "session required %s/.libs/%s.so",
+ cwd, MODULE_NAME,
+ cwd, MODULE_NAME, '\0',
+ cwd, MODULE_NAME,
+ cwd, MODULE_NAME));
+ ASSERT_EQ(0, fclose(fp));
+
+ ASSERT_EQ(PAM_SUCCESS,
+ pam_start_confdir(service_file, user_name, &conv, ".", &pamh));
+ ASSERT_NE(NULL, pamh);
+ ASSERT_EQ(PAM_SUCCESS, pam_authenticate(pamh, 0));
+ ASSERT_EQ(PAM_SUCCESS, pam_setcred(pamh, 0));
+ ASSERT_EQ(PAM_SUCCESS, pam_acct_mgmt(pamh, 0));
+ ASSERT_EQ(PAM_SUCCESS, pam_chauthtok(pamh, 0));
+ ASSERT_EQ(PAM_SUCCESS, pam_open_session(pamh, 0));
+ ASSERT_EQ(PAM_SUCCESS, pam_close_session(pamh, 0));
+ ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0));
+ pamh = NULL;
+
ASSERT_EQ(0, unlink(service_file));
return 0;

@ -1,211 +0,0 @@
diff -up Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml
--- Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml.pam-access-resolve-ip 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_access/access.conf.5.xml 2024-11-21 10:04:58.553127026 +0100
@@ -226,6 +226,14 @@
item and the line will be most probably ignored. For this reason, it is not
recommended to put spaces around the ':' characters.
</para>
+ <para>
+ An IPv6 link local host address must contain the interface
+ identifier. IPv6 link local network/netmask is not supported.
+ </para>
+ <para>
+ Hostnames should be written as Fully-Qualified Host Name (FQHN) to avoid
+ confusion with device names or PAM service names.
+ </para>
</refsect1>
<refsect1 id="access.conf-see_also">
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml.pam-access-resolve-ip 2020-11-25 17:57:02.000000000 +0100
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.8.xml 2024-11-21 10:04:58.553127026 +0100
@@ -25,11 +25,14 @@
<arg choice="opt">
debug
</arg>
+ <arg choice="opt" rep="norepeat">
+ noaudit
+ </arg>
<arg choice="opt">
nodefgroup
</arg>
- <arg choice="opt">
- noaudit
+ <arg choice="opt" rep="norepeat">
+ nodns
</arg>
<arg choice="opt">
accessfile=<replaceable>file</replaceable>
@@ -114,7 +117,46 @@
<varlistentry>
<term>
- <option>fieldsep=<replaceable>separators</replaceable></option>
+ nodefgroup
+ </term>
+ <listitem>
+ <para>
+ User tokens which are not enclosed in parentheses will not be
+ matched against the group database. The backwards compatible default is
+ to try the group database match even for tokens not enclosed
+ in parentheses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ nodns
+ </term>
+ <listitem>
+ <para>
+ Do not try to resolve tokens as hostnames, only IPv4 and IPv6
+ addresses will be resolved. Which means to allow login from a
+ remote host, the IP addresses need to be specified in <filename>access.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ quiet_log
+ </term>
+ <listitem>
+ <para>
+ Do not log denials with
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ fieldsep=separators
</term>
<listitem>
<para>
@@ -152,20 +194,6 @@
</para>
</listitem>
</varlistentry>
-
- <varlistentry>
- <term>
- <option>nodefgroup</option>
- </term>
- <listitem>
- <para>
- User tokens which are not enclosed in parentheses will not be
- matched against the group database. The backwards compatible default is
- to try the group database match even for tokens not enclosed
- in parentheses.
- </para>
- </listitem>
- </varlistentry>
</variablelist>
</refsect1>
diff -up Linux-PAM-1.5.1/modules/pam_access/pam_access.c.pam-access-resolve-ip Linux-PAM-1.5.1/modules/pam_access/pam_access.c
--- Linux-PAM-1.5.1/modules/pam_access/pam_access.c.pam-access-resolve-ip 2024-11-21 10:04:58.547127010 +0100
+++ Linux-PAM-1.5.1/modules/pam_access/pam_access.c 2024-11-21 10:04:58.553127026 +0100
@@ -92,6 +92,7 @@ struct login_info {
int debug; /* Print debugging messages. */
int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
int noaudit; /* Do not audit denials */
+ int nodns; /* Do not try to resolve tokens as hostnames */
const char *fs; /* field separator */
const char *sep; /* list-element separator */
int from_remote_host; /* If PAM_RHOST was used for from */
@@ -143,6 +144,8 @@ parse_args(pam_handle_t *pamh, struct lo
loginfo->only_new_group_syntax = YES;
} else if (strcmp (argv[i], "noaudit") == 0) {
loginfo->noaudit = YES;
+ } else if (strcmp (argv[i], "nodns") == 0) {
+ loginfo->nodns = YES;
} else {
pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
}
@@ -700,6 +703,39 @@ string_match (pam_handle_t *pamh, const
}
+static int
+is_device (pam_handle_t *pamh, const char *tok)
+{
+ struct stat st;
+ const char *dev = "/dev/";
+ char *devname;
+
+ devname = malloc (strlen(dev) + strlen (tok) + 1);
+ if (devname == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Cannot allocate memory for device name: %m");
+ /*
+ * We should return an error and abort, but pam_access has no good
+ * error handling.
+ */
+ return NO;
+ }
+
+ char *cp = stpcpy (devname, dev);
+ strcpy (cp, tok);
+
+ if (lstat(devname, &st) != 0)
+ {
+ free (devname);
+ return NO;
+ }
+ free (devname);
+
+ if (S_ISCHR(st.st_mode))
+ return YES;
+
+ return NO;
+}
+
/* network_netmask_match - match a string against one token
* where string is a hostname or ip (v4,v6) address and tok
* represents either a hostname, a single ip (v4,v6) address
@@ -761,10 +797,42 @@ network_netmask_match (pam_handle_t *pam
return NO;
}
}
+ else if (isipaddr(tok, NULL, NULL) == YES)
+ {
+ if (getaddrinfo (tok, NULL, NULL, &ai) != 0)
+ {
+ if (item->debug)
+ pam_syslog(pamh, LOG_DEBUG, "cannot resolve IP address \"%s\"", tok);
+
+ return NO;
+ }
+ netmask_ptr = NULL;
+ }
+ else if (item->nodns)
+ {
+ /* Only hostnames are left, which we would need to resolve via DNS */
+ return NO;
+ }
else
{
+ /* Bail out on X11 Display entries and ttys. */
+ if (tok[0] == ':')
+ {
+ if (item->debug)
+ pam_syslog (pamh, LOG_DEBUG,
+ "network_netmask_match: tok=%s is X11 display", tok);
+ return NO;
+ }
+ if (is_device (pamh, tok))
+ {
+ if (item->debug)
+ pam_syslog (pamh, LOG_DEBUG,
+ "network_netmask_match: tok=%s is a TTY", tok);
+ return NO;
+ }
+
/*
- * It is either an IP address or a hostname.
+ * It is most likely a hostname.
* Let getaddrinfo sort everything out
*/
if (getaddrinfo (tok, NULL, NULL, &ai) != 0)

@ -1,150 +0,0 @@
From a35e092e24ee7632346a0e1b4a203c04d4cd2c62 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Mon, 24 Jan 2022 15:43:23 +0100
Subject: [PATCH] pam_keyinit: thread-safe implementation
* modules/pam_keyinit/pam_keyinit.c: Bypass setre*id() C library calls
with kernel calls and change global variables definitions to be
thread-safe.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1997969
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
Co-Authored-By: Andreas Schneider <asn@samba.org>
---
modules/pam_keyinit/pam_keyinit.c | 60 ++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 16 deletions(-)
diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c
index 92e4953b..df9804b9 100644
--- a/modules/pam_keyinit/pam_keyinit.c
+++ b/modules/pam_keyinit/pam_keyinit.c
@@ -21,6 +21,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 */
@@ -31,12 +32,12 @@
#define KEYCTL_REVOKE 3 /* revoke a key */
#define KEYCTL_LINK 8 /* link a key into a keyring */
-static int my_session_keyring = 0;
-static int session_counter = 0;
-static int do_revoke = 0;
-static uid_t revoke_as_uid;
-static gid_t 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)));
@@ -64,6 +65,33 @@ static void error(pam_handle_t *pamh, const char *fmt, ...)
va_end(va);
}
+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
*/
@@ -140,14 +168,14 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret)
/* 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);
return error_ret;
}
- 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 && setregid(-1, old_gid) < 0)
+ if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
error(pamh, "Unable to change GID back to %d\n", old_gid);
return error_ret;
}
@@ -157,12 +185,12 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret)
}
/* return to the original 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);
ret = error_ret;
}
- 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);
ret = error_ret;
}
@@ -215,14 +243,14 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error
/* 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 error_ret;
}
- 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 error_ret;
}
@@ -230,12 +258,12 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error
ret = init_keyrings(pamh, force, error_ret);
/* return to the original UID and GID (probably root) */
- if (uid != old_uid && setreuid(old_uid, -1) < 0) {
+ if (uid != old_uid && pam_setreuid(old_uid, -1) < 0) {
error(pamh, "Unable to change UID back to %d\n", old_uid);
ret = error_ret;
}
- if (gid != old_gid && setregid(old_gid, -1) < 0) {
+ if (gid != old_gid && pam_setregid(old_gid, -1) < 0) {
error(pamh, "Unable to change GID back to %d\n", old_gid);
ret = error_ret;
}
--
2.35.1

@ -1,79 +0,0 @@
From 55f206447a1e4ee26e307e7a9c069236e823b1a5 Mon Sep 17 00:00:00 2001
From: Jeff Squyres <jsquyres@cisco.com>
Date: Fri, 30 Apr 2021 15:16:38 -0700
Subject: [PATCH 1/2] pam_misc: make length of misc_conv() configurable
Add --with-misc-conv-bufsize=<number> option to configure to allow
a longer buffer size for libpam_misc's misc_conv() function (it still
defaults to 512 bytes).
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
---
configure.ac | 7 +++++++
libpam_misc/misc_conv.c | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 9c92d0de..b283db1b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -648,6 +648,13 @@ case "$enable_unix" in
*) AC_MSG_ERROR([bad value $enable_unix for --enable-unix option]) ;;
esac
+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=512]),
+ [],
+ [with_misc_conv_bufsize=512])
+AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.])
+
AM_CONDITIONAL([COND_BUILD_PAM_KEYINIT], [test "$have_key_syscalls" = 1])
AM_CONDITIONAL([COND_BUILD_PAM_LASTLOG], [test "$ac_cv_func_logwtmp" = yes])
AM_CONDITIONAL([COND_BUILD_PAM_NAMESPACE], [test "$ac_cv_func_unshare" = yes])
diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c
index f28b1093..908ee890 100644
--- a/libpam_misc/misc_conv.c
+++ b/libpam_misc/misc_conv.c
@@ -18,7 +18,7 @@
#include <security/pam_appl.h>
#include <security/pam_misc.h>
-#define INPUTSIZE PAM_MAX_RESP_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
--
2.41.0
From 80bfda5962e5be3daa70e0fc8c75fc97d1c55121 Mon Sep 17 00:00:00 2001
From: Jeff Squyres <jsquyres@cisco.com>
Date: Fri, 30 Apr 2021 15:28:33 -0700
Subject: [PATCH 2/2] pam_misc: set default length of misc_conv() buffer to
4096
---
configure.ac | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index b283db1b..8e5d0ff7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -650,9 +650,9 @@ esac
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=512]),
+ [Size of input buffer for libpam_misc's misc_conv() conversation function, default=4096]),
[],
- [with_misc_conv_bufsize=512])
+ [with_misc_conv_bufsize=4096])
AC_DEFINE_UNQUOTED(PAM_MISC_CONV_BUFSIZE, $with_misc_conv_bufsize, [libpam_misc misc_conv() buffer size.])
AM_CONDITIONAL([COND_BUILD_PAM_KEYINIT], [test "$have_key_syscalls" = 1])
--
2.41.0

@ -1,114 +0,0 @@
diff -up Linux-PAM-1.5.1/modules/pam_unix/passverify.c.fail1 Linux-PAM-1.5.1/modules/pam_unix/passverify.c
--- Linux-PAM-1.5.1/modules/pam_unix/passverify.c.fail1 2024-11-04 11:42:51.962791265 +0100
+++ Linux-PAM-1.5.1/modules/pam_unix/passverify.c 2024-11-04 11:45:18.246218579 +0100
@@ -239,17 +239,21 @@ PAMH_ARG_DECL(int get_account_info,
return PAM_UNIX_RUN_HELPER;
#endif
} else if (is_pwd_shadowed(*pwd)) {
+#ifdef HELPER_COMPILE
/*
- * ...and shadow password file entry for this user,
+ * shadow password file entry for this user,
* if shadowing is enabled
*/
-#ifndef HELPER_COMPILE
- if (geteuid() || SELINUX_ENABLED)
- return PAM_UNIX_RUN_HELPER;
-#endif
- *spwdent = pam_modutil_getspnam(pamh, name);
+ *spwdent = getspnam(name);
if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL)
return PAM_AUTHINFO_UNAVAIL;
+#else
+ /*
+ * The helper has to be invoked to deal with
+ * the shadow password file entry.
+ */
+ return PAM_UNIX_RUN_HELPER;
+#endif
}
} else {
return PAM_USER_UNKNOWN;
From 8d0c575336ad301cd14e16ad2fdec6fe621764b8 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <slyich@gmail.com>
Date: Thu, 28 Mar 2024 21:58:35 +0000
Subject: [PATCH] pam_unix: allow empty passwords with non-empty hashes
Before the change pam_unix has different behaviours for a user with
empty password for these two `/etc/shadow` entries:
nulloktest:$6$Yy4ty2jJ$bsVQWo8qlXC6UHq1/qTC3UR60ZJKmKApJ3Wj7DreAy8FxlVKtlDnplFQ7jMLVlDqordE7e4t49GvTb.aI59TP0:1::::::
nulloktest::1::::::
The entry with a hash was rejected and the entry without was accepted.
The rejection happened because 9e74e90147c "pam_unix: avoid determining
if user exists" introduced the following rejection check (slightly
simplified):
...
} else if (p[0] == '\0' && nullok) {
if (hash[0] != '\0') {
retval = PAM_AUTH_ERR;
}
We should not reject the user with a hash assuming it's non-empty.
The change does that by pushing empty password check into
`verify_pwd_hash()`.
`NixOS` generates such hashed entries for empty passwords as if they
were non-empty using the following perl code:
sub hashPassword {
my ($password) = @_;
my $salt = "";
my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
$salt .= $chars[rand 64] for (1..8);
return crypt($password, '$6$' . $salt . '$');
}
Resolves: https://github.com/linux-pam/linux-pam/issues/758
Fixes: 9e74e90147c "pam_unix: avoid determining if user exists"
Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
---
modules/pam_unix/passverify.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 30045333..1c83f1aa 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -76,9 +76,13 @@ PAMH_ARG_DECL(int verify_pwd_hash,
strip_hpux_aging(hash);
hash_len = strlen(hash);
- if (!hash_len) {
+
+ if (p && p[0] == '\0' && !nullok) {
+ /* The passed password is empty */
+ retval = PAM_AUTH_ERR;
+ } else if (!hash_len) {
/* the stored password is NULL */
- if (nullok) { /* this means we've succeeded */
+ if (p && p[0] == '\0' && nullok) { /* this means we've succeeded */
D(("user has empty password - access granted"));
retval = PAM_SUCCESS;
} else {
@@ -1109,12 +1113,6 @@ helper_verify_password(const char *name, const char *p, int nullok)
if (pwd == NULL || hash == NULL) {
helper_log_err(LOG_NOTICE, "check pass; user unknown");
retval = PAM_USER_UNKNOWN;
- } else if (p[0] == '\0' && nullok) {
- if (hash[0] == '\0') {
- retval = PAM_SUCCESS;
- } else {
- retval = PAM_AUTH_ERR;
- }
} else {
retval = verify_pwd_hash(p, hash, nullok);
}
--
2.47.0

@ -1,100 +0,0 @@
From 370064ef6f99581b08d473a42bb3417d5dda3e4e Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Thu, 17 Feb 2022 10:24:03 +0100
Subject: [PATCH] pam_usertype: only use SYS_UID_MAX for system users
* modules/pam_usertype/pam_usertype.c (pam_usertype_is_system): Stop
using SYS_UID_MIN to check if it is a system account, because all
accounts below the SYS_UID_MAX are system users.
* modules/pam_usertype/pam_usertype.8.xml: Remove reference to SYS_UID_MIN
as it is no longer used to calculate the system accounts.
* configure.ac: Remove PAM_USERTYPE_SYSUIDMIN.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1949137
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
---
configure.ac | 5 -----
modules/pam_usertype/pam_usertype.8.xml | 2 +-
modules/pam_usertype/pam_usertype.c | 15 ++++++---------
3 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/configure.ac b/configure.ac
index 639fc1ad..79113ad1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -632,11 +632,6 @@ test -n "$opt_uidmin" ||
opt_uidmin=1000
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)
-test -n "$opt_sysuidmin" ||
- opt_sysuidmin=101
-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.])
-
AC_ARG_WITH([kernel-overflow-uid], AS_HELP_STRING([--with-kernel-overflow-uid=<number>],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval)
test -n "$opt_kerneloverflowuid" ||
opt_kerneloverflowuid=65534
diff --git a/modules/pam_usertype/pam_usertype.8.xml b/modules/pam_usertype/pam_usertype.8.xml
index 7651da6e..d9307ba3 100644
--- a/modules/pam_usertype/pam_usertype.8.xml
+++ b/modules/pam_usertype/pam_usertype.8.xml
@@ -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 --git a/modules/pam_usertype/pam_usertype.c b/modules/pam_usertype/pam_usertype.c
index d03b73b5..cfd9c8bb 100644
--- a/modules/pam_usertype/pam_usertype.c
+++ b/modules/pam_usertype/pam_usertype.c
@@ -194,7 +194,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) {
@@ -202,21 +201,19 @@ pam_usertype_is_system(pam_handle_t *pamh, uid_t uid)
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
@@ -253,7 +250,7 @@ pam_usertype_evaluate(struct pam_usertype_opts *opts,
/**
* 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
--
2.36.1

@ -1,42 +0,0 @@
From ec0e724fe53188c5c762c34ca9db6681c0de01b8 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Thu, 1 Jul 2021 12:14:29 +0200
Subject: [PATCH] pam_filter: Close file after controlling tty
Failing to check the descriptor value meant that there was a bug in the
attempt to close the controlling tty. Moreover, this would lead to a
file descriptor leak as pointed out by the static analyzer tool:
Error: RESOURCE_LEAK (CWE-772): [#def26]
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:356: open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.]
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:356: var_assign: Assigning: "t" = handle returned from "open("/dev/tty", 2)".
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:357: off_by_one: Testing whether handle "t" is strictly greater than zero is suspicious. "t" leaks when it is zero.
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:357: remediation: Did you intend to include equality with zero?
Linux-PAM-1.5.1/modules/pam_filter/pam_filter.c:367: leaked_handle: Handle variable "t" going out of scope leaks the handle.
365| pam_syslog(pamh, LOG_ERR,
366| "child cannot become new session: %m");
367|-> return PAM_ABORT;
368| }
369|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
---
modules/pam_filter/pam_filter.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/pam_filter/pam_filter.c b/modules/pam_filter/pam_filter.c
index 2f0af4fb..6e6def37 100644
--- a/modules/pam_filter/pam_filter.c
+++ b/modules/pam_filter/pam_filter.c
@@ -354,7 +354,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl,
int t = open("/dev/tty", O_RDWR|O_NOCTTY);
#else
int t = open("/dev/tty",O_RDWR);
- if (t > 0) {
+ if (t >= 0) {
(void) ioctl(t, TIOCNOTTY, NULL);
close(t);
}
--
2.31.1

@ -1,738 +0,0 @@
From b3bb13e18a74e9ece825b7de1b81db97ebb107a0 Mon Sep 17 00:00:00 2001
From: Iker Pedrosa <ipedrosa@redhat.com>
Date: Thu, 25 Mar 2021 09:43:30 +0100
Subject: [PATCH] pam_timestamp: replace hmac implementation
sha1 is no longer recommended as a cryptographic algorithm for
authentication. Thus, the idea of this change is to replace the
implementation provided by hmacsha1 included in pam_timestamp module by
the one in the openssl library. This way, there's no need to maintain
the cryptographic algorithm implementation and it can be easily changed
with a single configuration change.
modules/pam_timestamp/hmac_openssl_wrapper.c: implement wrapper
functions around openssl's hmac implementation. Moreover, manage the key
generation and its read and write in a file. Include an option to
configure the cryptographic algorithm in login.defs file.
modules/pam_timestamp/hmac_openssl_wrapper.h: likewise.
modules/pam_timestamp/pam_timestamp.c: replace calls to functions
provided by hmacsha1 by functions provided by openssl's wrapper.
configure.ac: include openssl dependecy if it is enabled.
modules/pam_timestamp/Makefile.am: include new files and openssl library
to compilation.
ci/install-dependencies.sh: include openssl library to dependencies.
NEWS: add new item to next release.
Make.xml.rules.in: add stringparam profiling for hmac
doc/custom-man.xsl: change import docbook to one with profiling
modules/pam_timestamp/pam_timestamp.8.xml: add conditional paragraph to
indicate the value in /etc/login.defs that holds the value for the
encryption algorithm
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1947294
---
Make.xml.rules.in | 2 +-
NEWS | 5 +
configure.ac | 16 +
doc/custom-man.xsl | 2 +-
modules/pam_timestamp/Makefile.am | 15 +-
modules/pam_timestamp/hmac_openssl_wrapper.c | 381 +++++++++++++++++++
modules/pam_timestamp/hmac_openssl_wrapper.h | 57 +++
modules/pam_timestamp/pam_timestamp.8.xml | 5 +
modules/pam_timestamp/pam_timestamp.c | 53 ++-
10 files changed, 524 insertions(+), 13 deletions(-)
create mode 100644 modules/pam_timestamp/hmac_openssl_wrapper.c
create mode 100644 modules/pam_timestamp/hmac_openssl_wrapper.h
diff --git a/Make.xml.rules.in b/Make.xml.rules.in
index daa1b97b..27bb510e 100644
--- a/Make.xml.rules.in
+++ b/Make.xml.rules.in
@@ -21,6 +21,6 @@ README: README.xml
%.8: %.8.xml
$(XMLLINT) --nonet --xinclude --postvalid --noout $<
- $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude @STRINGPARAM_VENDORDIR@ --nonet $(top_srcdir)/doc/custom-man.xsl $<
+ $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) --xinclude @STRINGPARAM_VENDORDIR@ @STRINGPARAM_HMAC@ --nonet $(top_srcdir)/doc/custom-man.xsl $<
#CLEANFILES += $(man_MANS) README
diff --git a/NEWS b/NEWS
index 2d49ec39..f4d11303 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,10 @@
Linux-PAM NEWS -- history of user-visible changes.
+Release next
+* pam_timestamp: change hmac algorithm to call openssl instead of the bundled
+ sha1 implementation if selected. Add option to select the hash
+ algorithm to use with HMAC.
+
Release 1.5.1
* pam_unix: fixed CVE-2020-27780 - authentication bypass when a user
doesn't exist and root password is blank
diff --git a/configure.ac b/configure.ac
index bd806473..9c92d0de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -504,6 +504,22 @@ else
fi
AC_SUBST([STRINGPARAM_VENDORDIR])
+AC_ARG_ENABLE([openssl],
+ AS_HELP_STRING([--enable-openssl],[use OpenSSL crypto libraries]),
+ [OPENSSL_ENABLED=$enableval], OPENSSL_ENABLED=no)
+if test "$OPENSSL_ENABLED" = "yes" ; then
+ AC_CHECK_LIB([crypto], [EVP_MAC_CTX_new],
+ [CRYPTO_LIBS="-lcrypto"
+ use_openssl=yes
+ AC_DEFINE([WITH_OPENSSL], 1, [OpenSSL provides crypto algorithm for hmac])
+ STRINGPARAM_HMAC="--stringparam profile.condition 'openssl_hmac'"],
+ [CRYPTO_LIBS=""
+ STRINGPARAM_HMAC="--stringparam profile.condition 'no_openssl_hmac'"])
+fi
+AC_SUBST([CRYPTO_LIBS])
+AC_SUBST([STRINGPARAM_HMAC])
+AM_CONDITIONAL([COND_USE_OPENSSL], [test "x$use_openssl" = "xyes"])
+
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
diff --git a/doc/custom-man.xsl b/doc/custom-man.xsl
index 4c35e839..a3408e6c 100644
--- a/doc/custom-man.xsl
+++ b/doc/custom-man.xsl
@@ -1,6 +1,6 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ss="http://docbook.sf.net/xmlns/string.subst/1.0" version="1.0">
- <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"/>
+ <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/manpages/profile-docbook.xsl"/>
<xsl:param name="vendordir"/>
<xsl:param name="man.string.subst.map.local.pre">
diff --git a/modules/pam_timestamp/Makefile.am b/modules/pam_timestamp/Makefile.am
index 1faa324a..d290b85f 100644
--- a/modules/pam_timestamp/Makefile.am
+++ b/modules/pam_timestamp/Makefile.am
@@ -18,12 +18,12 @@ TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS)
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
-noinst_HEADERS = hmacsha1.h sha1.h
+noinst_HEADERS = hmacsha1.h sha1.h hmac_openssl_wrapper.h
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
$(WARN_CFLAGS)
-pam_timestamp_la_LDFLAGS = -no-undefined -avoid-version -module $(AM_LDFLAGS)
+pam_timestamp_la_LDFLAGS = -no-undefined -avoid-version -module $(AM_LDFLAGS) $(CRYPTO_LIBS)
pam_timestamp_la_LIBADD = $(top_builddir)/libpam/libpam.la
if HAVE_VERSIONING
pam_timestamp_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
@@ -32,7 +32,12 @@ endif
securelib_LTLIBRARIES = pam_timestamp.la
sbin_PROGRAMS = pam_timestamp_check
-pam_timestamp_la_SOURCES = pam_timestamp.c hmacsha1.c sha1.c
+pam_timestamp_la_SOURCES = pam_timestamp.c
+if COND_USE_OPENSSL
+pam_timestamp_la_SOURCES += hmac_openssl_wrapper.c
+else
+pam_timestamp_la_SOURCES += hmacsha1.c sha1.c
+endif
pam_timestamp_la_CFLAGS = $(AM_CFLAGS)
pam_timestamp_check_SOURCES = pam_timestamp_check.c
@@ -40,7 +45,11 @@ pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@
pam_timestamp_check_LDADD = $(top_builddir)/libpam/libpam.la
pam_timestamp_check_LDFLAGS = @EXE_LDFLAGS@
+if COND_USE_OPENSSL
+hmacfile_SOURCES = hmac_openssl_wrapper.c
+else
hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c
+endif
hmacfile_LDADD = $(top_builddir)/libpam/libpam.la
check_PROGRAMS = hmacfile
diff --git a/modules/pam_timestamp/hmac_openssl_wrapper.c b/modules/pam_timestamp/hmac_openssl_wrapper.c
new file mode 100644
index 00000000..926c2fb9
--- /dev/null
+++ b/modules/pam_timestamp/hmac_openssl_wrapper.c
@@ -0,0 +1,381 @@
+/* Wrapper for hmac openssl implementation.
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ * Written by 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"
+
+#ifdef WITH_OPENSSL
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
+
+#include <security/pam_ext.h>
+#include <security/pam_modutil.h>
+
+#include "hmac_openssl_wrapper.h"
+
+#define LOGIN_DEFS "/etc/login.defs"
+#define CRYPTO_KEY "HMAC_CRYPTO_ALGO"
+#define DEFAULT_ALGORITHM "SHA512"
+#define MAX_HMAC_LENGTH 512
+#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
+
+static char *
+get_crypto_algorithm(pam_handle_t *pamh, int debug){
+ char *config_value = NULL;
+
+ config_value = pam_modutil_search_key(pamh, LOGIN_DEFS, CRYPTO_KEY);
+
+ if (config_value == NULL) {
+ config_value = strdup(DEFAULT_ALGORITHM);
+ if (debug) {
+ pam_syslog(pamh, LOG_DEBUG,
+ "Key [%s] not found, falling back to default algorithm [%s]\n",
+ CRYPTO_KEY, DEFAULT_ALGORITHM);
+ }
+ }
+
+ return config_value;
+}
+
+static int
+generate_key(pam_handle_t *pamh, char **key, size_t key_size)
+{
+ int fd = 0;
+ size_t bytes_read = 0;
+ char * tmp = NULL;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1) {
+ pam_syslog(pamh, LOG_ERR, "Cannot open /dev/urandom: %m");
+ return PAM_AUTH_ERR;
+ }
+
+ tmp = malloc(key_size);
+ if (!tmp) {
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
+ close(fd);
+ return PAM_AUTH_ERR;
+ }
+
+ bytes_read = pam_modutil_read(fd, tmp, key_size);
+ close(fd);
+
+ if (bytes_read < key_size) {
+ pam_syslog(pamh, LOG_ERR, "Short read on random device");
+ free(tmp);
+ return PAM_AUTH_ERR;
+ }
+
+ *key = tmp;
+
+ return PAM_SUCCESS;
+}
+
+static int
+read_file(pam_handle_t *pamh, int fd, char **text, size_t *text_length)
+{
+ struct stat st;
+ size_t bytes_read = 0;
+ char *tmp = NULL;
+
+ if (fstat(fd, &st) == -1) {
+ pam_syslog(pamh, LOG_ERR, "Unable to stat file: %m");
+ close(fd);
+ return PAM_AUTH_ERR;
+ }
+
+ if (st.st_size == 0) {
+ pam_syslog(pamh, LOG_ERR, "Key file size cannot be 0");
+ close(fd);
+ return PAM_AUTH_ERR;
+ }
+
+ tmp = malloc(st.st_size);
+ if (!tmp) {
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
+ close(fd);
+ return PAM_AUTH_ERR;
+ }
+
+ bytes_read = pam_modutil_read(fd, tmp, st.st_size);
+ close(fd);
+
+ if (bytes_read < (size_t)st.st_size) {
+ pam_syslog(pamh, LOG_ERR, "Short read on key file");
+ memset(tmp, 0, st.st_size);
+ free(tmp);
+ return PAM_AUTH_ERR;
+ }
+
+ *text = tmp;
+ *text_length = st.st_size;
+
+ return PAM_SUCCESS;
+}
+
+static int
+write_file(pam_handle_t *pamh, const char *file_name, char *text,
+ size_t text_length, uid_t owner, gid_t group)
+{
+ int fd = 0;
+ size_t bytes_written = 0;
+
+ fd = open(file_name,
+ O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ pam_syslog(pamh, LOG_ERR, "Unable to open [%s]: %m", file_name);
+ memset(text, 0, text_length);
+ free(text);
+ return PAM_AUTH_ERR;
+ }
+
+ if (fchown(fd, owner, group) == -1) {
+ pam_syslog(pamh, LOG_ERR, "Unable to change ownership [%s]: %m", file_name);
+ memset(text, 0, text_length);
+ free(text);
+ close(fd);
+ return PAM_AUTH_ERR;
+ }
+
+ bytes_written = pam_modutil_write(fd, text, text_length);
+ close(fd);
+
+ if (bytes_written < text_length) {
+ pam_syslog(pamh, LOG_ERR, "Short write on %s", file_name);
+ free(text);
+ return PAM_AUTH_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int
+key_management(pam_handle_t *pamh, const char *file_name, char **text,
+ size_t text_length, uid_t owner, gid_t group)
+{
+ int fd = 0;
+
+ fd = open(file_name, O_RDONLY | O_NOFOLLOW);
+ if (fd == -1) {
+ if (errno == ENOENT) {
+ if (generate_key(pamh, text, text_length)) {
+ pam_syslog(pamh, LOG_ERR, "Unable to generate key");
+ return PAM_AUTH_ERR;
+ }
+
+ if (write_file(pamh, file_name, *text, text_length, owner, group)) {
+ pam_syslog(pamh, LOG_ERR, "Unable to write key");
+ return PAM_AUTH_ERR;
+ }
+ } else {
+ pam_syslog(pamh, LOG_ERR, "Unable to open %s: %m", file_name);
+ return PAM_AUTH_ERR;
+ }
+ } else {
+ if (read_file(pamh, fd, text, &text_length)) {
+ pam_syslog(pamh, LOG_ERR, "Error reading key file %s\n", file_name);
+ return PAM_AUTH_ERR;
+ }
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int
+hmac_management(pam_handle_t *pamh, int debug, void **out, size_t *out_length,
+ char *key, size_t key_length,
+ const void *text, size_t text_length)
+{
+ int ret = PAM_AUTH_ERR;
+ EVP_MAC *evp_mac = NULL;
+ EVP_MAC_CTX *ctx = NULL;
+ unsigned char *hmac_message = NULL;
+ size_t hmac_length;
+ char *algo = NULL;
+ OSSL_PARAM subalg_param[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ algo = get_crypto_algorithm(pamh, debug);
+
+ subalg_param[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ algo,
+ 0);
+
+ evp_mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ if (evp_mac == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac implementation");
+ goto done;
+ }
+
+ ctx = EVP_MAC_CTX_new(evp_mac);
+ if (ctx == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac context");
+ goto done;
+ }
+
+ ret = EVP_MAC_init(ctx, (const unsigned char *)key, key_length, subalg_param);
+ if (ret == 0) {
+ pam_syslog(pamh, LOG_ERR, "Unable to initialize hmac context");
+ goto done;
+ }
+
+ ret = EVP_MAC_update(ctx, (const unsigned char *)text, text_length);
+ if (ret == 0) {
+ pam_syslog(pamh, LOG_ERR, "Unable to update hmac context");
+ goto done;
+ }
+
+ hmac_message = (unsigned char*)malloc(sizeof(unsigned char) * MAX_HMAC_LENGTH);
+ if (!hmac_message) {
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
+ goto done;
+ }
+
+ ret = EVP_MAC_final(ctx, hmac_message, &hmac_length, MAX_HMAC_LENGTH);
+ if (ret == 0) {
+ pam_syslog(pamh, LOG_ERR, "Unable to calculate hmac message");
+ goto done;
+ }
+
+ *out_length = hmac_length;
+ *out = malloc(*out_length);
+ if (*out == NULL) {
+ pam_syslog(pamh, LOG_CRIT, "Not enough memory");
+ goto done;
+ }
+
+ memcpy(*out, hmac_message, *out_length);
+ ret = PAM_SUCCESS;
+
+done:
+ if (hmac_message != NULL) {
+ free(hmac_message);
+ }
+ if (key != NULL) {
+ memset(key, 0, key_length);
+ free(key);
+ }
+ if (ctx != NULL) {
+ EVP_MAC_CTX_free(ctx);
+ }
+ if (evp_mac != NULL) {
+ EVP_MAC_free(evp_mac);
+ }
+ free(algo);
+
+ return ret;
+}
+
+int
+hmac_size(pam_handle_t *pamh, int debug, size_t *hmac_length)
+{
+ int ret = PAM_AUTH_ERR;
+ EVP_MAC *evp_mac = NULL;
+ EVP_MAC_CTX *ctx = NULL;
+ const unsigned char key[] = "ThisIsJustAKey";
+ size_t key_length = MAX_KEY_LENGTH;
+ char *algo = NULL;
+ OSSL_PARAM subalg_param[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ algo = get_crypto_algorithm(pamh, debug);
+
+ subalg_param[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ algo,
+ 0);
+
+ evp_mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ if (evp_mac == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac implementation");
+ goto done;
+ }
+
+ ctx = EVP_MAC_CTX_new(evp_mac);
+ if (ctx == NULL) {
+ pam_syslog(pamh, LOG_ERR, "Unable to create hmac context");
+ goto done;
+ }
+
+ ret = EVP_MAC_init(ctx, key, key_length, subalg_param);
+ if (ret == 0) {
+ pam_syslog(pamh, LOG_ERR, "Unable to initialize hmac context");
+ goto done;
+ }
+
+ *hmac_length = EVP_MAC_CTX_get_mac_size(ctx);
+ ret = PAM_SUCCESS;
+
+done:
+ if (ctx != NULL) {
+ EVP_MAC_CTX_free(ctx);
+ }
+ if (evp_mac != NULL) {
+ EVP_MAC_free(evp_mac);
+ }
+ free(algo);
+
+ return ret;
+}
+
+int
+hmac_generate(pam_handle_t *pamh, int debug, void **mac, size_t *mac_length,
+ const char *key_file, uid_t owner, gid_t group,
+ const void *text, size_t text_length)
+{
+ char *key = NULL;
+ size_t key_length = MAX_KEY_LENGTH;
+
+ if (key_management(pamh, key_file, &key, key_length, owner, group)) {
+ return PAM_AUTH_ERR;
+ }
+
+ if (hmac_management(pamh, debug, mac, mac_length, key, key_length,
+ text, text_length)) {
+ return PAM_AUTH_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+#endif /* WITH_OPENSSL */
diff --git a/modules/pam_timestamp/hmac_openssl_wrapper.h b/modules/pam_timestamp/hmac_openssl_wrapper.h
new file mode 100644
index 00000000..cc27c811
--- /dev/null
+++ b/modules/pam_timestamp/hmac_openssl_wrapper.h
@@ -0,0 +1,57 @@
+/* Wrapper for hmac openssl implementation.
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ * Written by 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 PAM_TIMESTAMP_HMAC_OPENSSL_WRAPPER_H
+#define PAM_TIMESTAMP_HMAC_OPENSSL_WRAPPER_H
+
+#include "config.h"
+
+#ifdef WITH_OPENSSL
+
+#include <openssl/hmac.h>
+#include <security/pam_modules.h>
+
+int
+hmac_size(pam_handle_t *pamh, int debug, size_t *hmac_length);
+
+int
+hmac_generate(pam_handle_t *pamh, int debug, void **mac, size_t *mac_length,
+ const char *key_file, uid_t owner, gid_t group,
+ const void *text, size_t text_length);
+
+#endif /* WITH_OPENSSL */
+#endif /* PAM_TIMESTAMP_HMAC_OPENSSL_WRAPPER_H */
diff --git a/modules/pam_timestamp/pam_timestamp.8.xml b/modules/pam_timestamp/pam_timestamp.8.xml
index e19a0bcf..83e5aea8 100644
--- a/modules/pam_timestamp/pam_timestamp.8.xml
+++ b/modules/pam_timestamp/pam_timestamp.8.xml
@@ -50,6 +50,11 @@ for the user. When an application attempts to authenticate the user, a
<emphasis>pam_timestamp</emphasis> will treat a sufficiently recent timestamp
file as grounds for succeeding.
</para>
+ <para condition="openssl_hmac">
+ The default encryption hash is taken from the
+ <emphasis remap='B'>HMAC_CRYPTO_ALGO</emphasis> variable from
+ <emphasis>/etc/login.defs</emphasis>.
+ </para>
</refsect1>
<refsect1 id="pam_timestamp-options">
diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c
index 30be883c..01dd1385 100644
--- a/modules/pam_timestamp/pam_timestamp.c
+++ b/modules/pam_timestamp/pam_timestamp.c
@@ -56,7 +56,11 @@
#include <utmp.h>
#include <syslog.h>
#include <paths.h>
+#ifdef WITH_OPENSSL
+#include "hmac_openssl_wrapper.h"
+#else
#include "hmacsha1.h"
+#endif /* WITH_OPENSSL */
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
@@ -79,6 +83,9 @@
#define BUFLEN PATH_MAX
#endif
+#define ROOT_USER 0
+#define ROOT_GROUP 0
+
/* Return PAM_SUCCESS if the given directory looks "safe". */
static int
check_dir_perms(pam_handle_t *pamh, const char *tdir)
@@ -449,6 +456,13 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_AUTH_ERR;
}
+#ifdef WITH_OPENSSL
+ if (hmac_size(pamh, debug, &maclen)) {
+ return PAM_AUTH_ERR;
+ }
+#else
+ maclen = hmac_sha1_size();
+#endif /* WITH_OPENSSL */
/* Check that the file is the expected size. */
if (st.st_size == 0) {
/* Invalid, but may have been created by sudo. */
@@ -456,7 +470,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_AUTH_ERR;
}
if (st.st_size !=
- (off_t)(strlen(path) + 1 + sizeof(then) + hmac_sha1_size())) {
+ (off_t)(strlen(path) + 1 + sizeof(then) + maclen)) {
pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' "
"appears to be corrupted", path);
close(fd);
@@ -487,8 +501,17 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
message_end = message + strlen(path) + 1 + sizeof(then);
/* Regenerate the MAC. */
- hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY, 0, 0,
- message, message_end - message);
+#ifdef WITH_OPENSSL
+ if (hmac_generate(pamh, debug, &mac, &maclen, TIMESTAMPKEY,
+ ROOT_USER, ROOT_GROUP, message, message_end - message)) {
+ close(fd);
+ free(message);
+ return PAM_AUTH_ERR;
+ }
+#else
+ hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY,
+ ROOT_USER, ROOT_GROUP, message, message_end - message);
+#endif /* WITH_OPENSSL */
if ((mac == NULL) ||
(memcmp(path, message, strlen(path)) != 0) ||
(memcmp(mac, message_end, maclen) != 0)) {
@@ -605,8 +628,16 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char *
}
}
+#ifdef WITH_OPENSSL
+ if (hmac_size(pamh, debug, &maclen)) {
+ return PAM_SESSION_ERR;
+ }
+#else
+ maclen = hmac_sha1_size();
+#endif /* WITH_OPENSSL */
+
/* Generate the message. */
- text = malloc(strlen(path) + 1 + sizeof(now) + hmac_sha1_size());
+ text = malloc(strlen(path) + 1 + sizeof(now) + maclen);
if (text == NULL) {
pam_syslog(pamh, LOG_CRIT, "unable to allocate memory: %m");
return PAM_SESSION_ERR;
@@ -621,15 +652,21 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char *
p += sizeof(now);
/* Generate the MAC and append it to the plaintext. */
- hmac_sha1_generate_file(pamh, &mac, &maclen,
- TIMESTAMPKEY,
- 0, 0,
- text, p - text);
+#ifdef WITH_OPENSSL
+ if (hmac_generate(pamh, debug, &mac, &maclen, TIMESTAMPKEY,
+ ROOT_USER, ROOT_GROUP, text, p - text)) {
+ free(text);
+ return PAM_SESSION_ERR;
+ }
+#else
+ hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY,
+ ROOT_USER, ROOT_GROUP, text, p - text);
if (mac == NULL) {
pam_syslog(pamh, LOG_ERR, "failure generating MAC: %m");
free(text);
return PAM_SESSION_ERR;
}
+#endif /* WITH_OPENSSL */
memmove(p, mac, maclen);
p += maclen;
free(mac);
--
2.31.1

@ -2,4 +2,3 @@ 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 -
f /var/log/tallylog 0600 root root -

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

@ -1,13 +1,14 @@
%global pam_redhat_version 1.1.4
%define pam_redhat_version 0.99.11
Summary: An extensible library which provides authentication for applications
Name: pam
Version: 1.5.1
Release: 22%{?dist}
Version: 1.3.1
Release: 33%{?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+.
License: BSD and GPLv2+
Group: System Environment/Base
Source0: https://github.com/linux-pam/linux-pam/releases/download/v%{version}/Linux-PAM-%{version}.tar.xz
Source1: https://github.com/linux-pam/linux-pam/releases/download/v%{version}/Linux-PAM-%{version}.tar.xz.asc
Source2: https://releases.pagure.org/pam-redhat/pam-redhat-%{pam_redhat_version}.tar.bz2
@ -24,77 +25,114 @@ Source15: pamtmp.conf
Source16: postlogin.pamd
Source17: postlogin.5
Source18: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
Patch1: pam-1.5.0-redhat-modules.patch
Patch2: pam-1.5.0-noflex.patch
Patch3: pam-1.3.0-unix-nomsg.patch
Patch4: pam-1.5.1-timestamp-openssl-hmac-authentication.patch
# https://github.com/linux-pam/linux-pam/commit/ec0e724fe53188c5c762c34ca9db6681c0de01b8
Patch5: pam-1.5.1-pam_filter_close_file_after_controlling_tty.patch
Patch1: pam-1.2.0-redhat-modules.patch
Patch4: pam-1.1.0-console-nochmod.patch
Patch5: pam-1.1.0-notally.patch
Patch7: pam-1.2.1-faillock.patch
Patch8: pam-1.2.1-faillock-admin-group.patch
Patch9: pam-1.3.1-noflex.patch
Patch10: pam-1.1.3-nouserenv.patch
Patch13: pam-1.1.6-limits-user.patch
Patch15: pam-1.1.8-full-relro.patch
# FIPS related - non upstreamable
Patch20: pam-1.2.0-unix-no-fallback.patch
Patch28: pam-1.1.1-console-errmsg.patch
# Upstreamed partially
Patch29: pam-1.3.0-pwhistory-helper.patch
Patch31: pam-1.1.8-audit-user-mgmt.patch
Patch32: pam-1.2.1-console-devname.patch
Patch33: pam-1.3.0-unix-nomsg.patch
Patch34: pam-1.3.1-coverity.patch
Patch35: pam-1.3.1-console-build.patch
Patch36: pam-1.3.1-faillock-update.patch
Patch37: pam-1.3.1-namespace-mntopts.patch
Patch38: pam-1.3.1-lastlog-no-showfailed.patch
Patch39: pam-1.3.1-lastlog-unlimited-fsize.patch
Patch40: pam-1.3.1-unix-improve-logging.patch
Patch41: pam-1.3.1-tty-audit-manfix.patch
Patch42: pam-1.3.1-fds-closing.patch
Patch43: pam-1.3.1-authtok-verify-fix.patch
Patch44: pam-1.3.1-motd-manpage.patch
# Upstreamed
Patch45: pam-1.3.1-pam-usertype.patch
# Upstreamed
Patch46: pam-1.3.1-audit-error.patch
# Upstreamed
Patch47: pam-1.3.1-pam-modutil-close-write.patch
# https://github.com/linux-pam/linux-pam/commit/6bf9b454eb971083f0cce49faa2aa1cde329ff5d
# https://github.com/linux-pam/linux-pam/commit/9091ea1d81e85f49a221b0325d27b22ce69e444a
# https://github.com/linux-pam/linux-pam/commit/a3a5cbf86083c43026b558e2023f597530626267
Patch48: pam-1.3.1-wheel-pam_ruser-fallback.patch
# https://github.com/linux-pam/linux-pam/commit/491e5500b6b3913f531574208274358a2df88659
Patch49: pam-1.3.1-namespace-gdm-doc.patch
# https://github.com/linux-pam/linux-pam/commit/a7453aeeb398d6cbb7a709c4e2a1d75905220fff
Patch50: pam-1.3.1-pam-userdb-prevent-garbage-characters-from-db.patch
# https://github.com/linux-pam/linux-pam/commit/3234488f2c52a021eec87df1990d256314c21bff
Patch6: pam-1.5.1-pam-limits-unlimited-value.patch
Patch51: pam-1.3.1-pam-limits-unlimited-value.patch
# https://github.com/linux-pam/linux-pam/commit/a35e092e24ee7632346a0e1b4a203c04d4cd2c62
Patch7: pam-1.5.1-pam-keyinit-thread-safe.patch
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
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
Patch8: pam-1.5.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
Patch9: pam-1.5.1-pam-usertype-SYS_UID_MAX.patch
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
Patch10: pam-1.5.1-pam-pwhistory-load-conf-from-file.patch
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
Patch11: pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch
Patch62: pam-1.5.1-pam-lastlog-check-localtime_r-return-value.patch
# https://github.com/linux-pam/linux-pam/commit/bcbf145ce925934214e48200c27c9ff736452549
Patch12: pam-1.5.1-pam-faillock-clarify-missing-user.patch
Patch63: pam-1.5.1-pam-faillock-clarify-missing-user.patch
# https://github.com/linux-pam/linux-pam/commit/10086bc69663fa819277af244eeb5b629a2403b8
Patch13: pam-1.5.1-pam-faillock-avoid-logging-erroneous.patch
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
Patch14: pam-1.5.1-pam-misc-configurable.patch
# https://github.com/linux-pam/linux-pam/commit/d6103b30050554d7b6ca6d55cb5b4ed3c9516663
Patch15: pam-1.5.1-libpam-close-range.patch
# https://github.com/linux-pam/linux-pam/commit/c85513220c1bd3150e39c6277422d29cfa44acc7
# https://github.com/linux-pam/linux-pam/commit/1648734a69c31e9ce834da70144ac9a453296807
Patch16: pam-1.5.1-audit-messages-formatting.patch
Patch65: pam-1.3.1-pam-misc-configurable.patch
# https://github.com/linux-pam/linux-pam/commit/530c9f9e2d746e1d168c6b17863debda7664ac7c
# https://github.com/linux-pam/linux-pam/commit/f7abb8c1ef3aa31e6c2564a8aaf69683a77c2016
Patch66: pam-1.3.1-unix-enable-bcrypt.patch
Patch67: pam-1.3.1-unix-default-rounds.patch
# https://github.com/linux-pam/linux-pam/commit/d54870f993e97fe75e2cd0470a3701d5af22877c
Patch17: pam-1.5.1-faillock-create-tallydir.patch
# https://github.com/linux-pam/linux-pam/commit/244b46908df930626535c0cd7c2867407fe8714a
# https://github.com/linux-pam/linux-pam/commit/f26d873435be9f35fa7953493cc07a9bc4e31876
Patch18: pam-1-5-1-libpam-getlogin.patch
Patch68: pam-1.3.1-faillock-create-tallydir.patch
# https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f
Patch19: pam-1.5.1-access-handle-hostnames.patch
Patch69: pam-1.3.1-access-handle-hostnames.patch
# https://github.com/linux-pam/linux-pam/commit/031bb5a5d0d950253b68138b498dc93be69a64cb
Patch20: pam-1.5.1-namespace-protect-dir.patch
# https://github.com/linux-pam/linux-pam/commit/ec1fb9ddc6c252d8c61379e9385ca19c036fcb96
Patch21: pam-1.5.1-libpam-support-long-lines.patch
# https://github.com/linux-pam/linux-pam/commit/b3020da7da384d769f27a8713257fbe1001878be
# https://github.com/linux-pam/linux-pam/commit/8d0c575336ad301cd14e16ad2fdec6fe621764b8
Patch22: pam-1.5.1-pam-unix-shadow-password.patch
# https://github.com/linux-pam/linux-pam/commit/940747f88c16e029b69a74e80a2e94f65cb3e628
Patch23: pam-1.5.1-pam-access-resolve-ip.patch
%global _pamlibdir %{_libdir}
%global _moduledir %{_libdir}/security
%global _secconfdir %{_sysconfdir}/security
%global _pamconfdir %{_sysconfdir}/pam.d
%global _pamvendordir %{_datadir}/pam.d
%global _systemdlibdir /usr/lib/systemd/system
Patch70: pam-1.3.1-namespace-protect-dir.patch
%define _pamlibdir %{_libdir}
%define _moduledir %{_libdir}/security
%define _secconfdir %{_sysconfdir}/security
%define _pamconfdir %{_sysconfdir}/pam.d
%if %{?WITH_SELINUX:0}%{!?WITH_SELINUX:1}
%global WITH_SELINUX 1
%define WITH_SELINUX 1
%endif
%if %{?WITH_AUDIT:0}%{!?WITH_AUDIT:1}
%global WITH_AUDIT 1
%define WITH_AUDIT 1
%endif
%global _performance_build 1
Recommends: cracklib-dicts >= 2.8
Requires: libpwquality >= 0.9.9
BuildRequires: make
Requires(post): coreutils, /sbin/ldconfig
BuildRequires: autoconf >= 2.60
BuildRequires: automake, libtool
BuildRequires: bison, flex, sed
BuildRequires: cracklib-devel
BuildRequires: perl-interpreter, pkgconfig, gettext-devel
BuildRequires: libtirpc-devel
BuildRequires: libtirpc-devel, libnsl2-devel
%if %{WITH_AUDIT}
BuildRequires: audit-libs-devel >= 1.0.8
Requires: audit-libs >= 1.0.8
@ -103,17 +141,11 @@ Requires: audit-libs >= 1.0.8
BuildRequires: libselinux-devel >= 1.33.2
Requires: libselinux >= 1.33.2
%endif
BuildRequires: libeconf-devel >= 0.3.5
Requires: libeconf >= 0.3.5
Requires: glibc >= 2.3.90-37
BuildRequires: libxcrypt-devel >= 4.3.3-2
BuildRequires: libdb-devel
# Following deps are necessary only to build the pam library documentation.
BuildRequires: linuxdoc-tools, elinks, libxslt
BuildRequires: docbook-style-xsl, docbook-dtds
BuildRequires: gcc
BuildRequires: openssl-devel >= 3.0.0
Requires: openssl >= 3.0.0
URL: http://www.linux-pam.org/
@ -123,6 +155,7 @@ allows system administrators to set authentication policy without
having to recompile programs that handle authentication.
%package devel
Group: Development/Libraries
Summary: Files needed for developing PAM-aware applications and modules for PAM
Requires: pam%{?_isa} = %{version}-%{release}
@ -133,17 +166,6 @@ having to recompile programs that handle authentication. This package
contains header files used for building both PAM-aware applications
and modules for use with the PAM system.
%package docs
Summary: Extra documentation for PAM.
Requires: pam%{?_isa} = %{version}-%{release}
%description docs
PAM (Pluggable Authentication Modules) is a system security tool that
allows system administrators to set authentication policy without
having to recompile programs that handle authentication. The pam-docs
contains extra documentation for PAM. Currently, this includes additional
documentation in txt and html format.
%prep
%setup -q -n Linux-PAM-%{version} -a 2
perl -pi -e "s/ppc64-\*/ppc64-\* \| ppc64p7-\*/" build-aux/config.sub
@ -155,28 +177,57 @@ mv pam-redhat-%{pam_redhat_version}/* modules
cp %{SOURCE18} .
%patch1 -p1 -b .redhat-modules
%patch2 -p1 -b .noflex
%patch3 -p1 -b .nomsg
%patch4 -p1 -b .timestamp-openssl-hmac-authentication
%patch5 -p1 -b .pam_filter_close_file_after_controlling_tty
%patch6 -p1 -b .pam-limits-unlimited-value
%patch7 -p1 -b .pam-keyinit-thread-safe
%patch8 -p1 -b .faillock-load-conf-from-file
%patch9 -p1 -b .pam-usertype-SYS_UID_MAX
%patch10 -p1 -b .pam-pwhistory-load-conf-from-file
%patch11 -p1 -b .pam-lastlog-check-localtime_r-return-value
%patch12 -p1 -b .pam-faillock-clarify-missing-user
%patch13 -p1 -b .pam-faillock-avoid-logging-erroneous
%patch14 -p1 -b .pam-misc-configurable
%patch15 -p1 -b .libpam-close-range
%patch16 -p1 -b .audit-messages-formatting
%patch17 -p1 -b .faillock-create-tallydir
%patch18 -p1 -b .libpam-getlogin
%patch19 -p1 -b .access-handle-hostnames
%patch20 -p1 -b .namespace-protect-dir
%patch21 -p1 -b .libpam-support-long-lines
%patch22 -p1 -b .pam-unix-shadow-password
%patch23 -p1 -b .pam-access-resolve-ip
%patch4 -p1 -b .nochmod
%patch5 -p1 -b .notally
%patch7 -p1 -b .faillock
%patch8 -p1 -b .admin-group
%patch9 -p1 -b .noflex
%patch10 -p1 -b .nouserenv
%patch13 -p1 -b .limits
%patch15 -p1 -b .relro
%patch20 -p1 -b .no-fallback
%patch28 -p1 -b .errmsg
%patch29 -p1 -b .pwhhelper
%patch31 -p1 -b .audit-user-mgmt
%patch32 -p1 -b .devname
%patch33 -p1 -b .nomsg
%patch34 -p1 -b .coverity
%patch35 -p1 -b .console-build
%patch36 -p1 -b .faillock-update
%patch37 -p1 -b .mntopts
%patch38 -p1 -b .no-showfailed
%patch39 -p1 -b .unlimited-fsize
%patch40 -p1 -b .improve-logging
%patch41 -p1 -b .tty-audit-manfix
%patch42 -p1 -b .fds-closing
%patch43 -p1 -b .authtok-verify-fix
%patch44 -p1 -b .motd-manpage
%patch45 -p1 -b .pam-usertype
%patch46 -p1 -b .audit-error
%patch47 -p1 -b .pam-modutil-close-write
%patch48 -p1 -b .wheel-pam_ruser-fallback
%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-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
%patch66 -p1 -b .unix-enable-bcrypt
%patch67 -p1 -b .unix-default-rounds
%patch68 -p1 -b .faillock-create-tallydir
%patch69 -p1 -b .access-handle-hostnames
%patch70 -p1 -b .namespace-protect-dir
autoreconf -i
@ -185,7 +236,6 @@ autoreconf -i
--disable-rpath \
--libdir=%{_pamlibdir} \
--includedir=%{_includedir}/security \
--enable-vendordir=%{_datadir} \
%if ! %{WITH_SELINUX}
--disable-selinux \
%endif
@ -193,9 +243,7 @@ autoreconf -i
--disable-audit \
%endif
--disable-static \
--disable-prelude \
--disable-nis \
--enable-openssl
--disable-prelude
make -C po update-gmo
make
# we do not use _smp_mflags because the build of sources in yacc/flex fails
@ -206,6 +254,9 @@ for readme in modules/pam_*/README ; do
cp -f ${readme} doc/txts/README.`dirname ${readme} | sed -e 's|^modules/||'`
done
rm -rf doc/txts/README.pam_tally*
rm -rf doc/sag/html/*pam_tally*
# Install the binaries, libraries, and modules.
make install DESTDIR=$RPM_BUILD_ROOT LDCONFIG=:
@ -221,7 +272,6 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/environment
# Install default configuration files.
install -d -m 755 $RPM_BUILD_ROOT%{_pamconfdir}
install -d -m 755 $RPM_BUILD_ROOT%{_pamvendordir}
install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_pamconfdir}/other
install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_pamconfdir}/system-auth
install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_pamconfdir}/password-auth
@ -283,6 +333,8 @@ if [ -d ${dir} ] ; then
%if ! %{WITH_AUDIT}
[ ${dir} = "modules/pam_tty_audit" ] && continue
%endif
[ ${dir} = "modules/pam_tally" ] && continue
[ ${dir} = "modules/pam_tally2" ] && continue
if ! ls -1 $RPM_BUILD_ROOT%{_moduledir}/`basename ${dir}`*.so ; then
echo ERROR `basename ${dir}` did not build a module.
exit 1
@ -301,11 +353,12 @@ for module in $RPM_BUILD_ROOT%{_moduledir}/pam*.so ; do
fi
done
%ldconfig_scriptlets
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files -f Linux-PAM.lang
%dir %{_pamconfdir}
%dir %{_pamvendordir}
%config(noreplace) %{_pamconfdir}/other
%config(noreplace) %{_pamconfdir}/system-auth
%config(noreplace) %{_pamconfdir}/password-auth
@ -316,11 +369,12 @@ done
%{!?_licensedir:%global license %%doc}
%license Copyright
%license gpl-2.0.txt
%doc doc/txts
%doc doc/sag/*.txt doc/sag/html
%{_pamlibdir}/libpam.so.*
%{_pamlibdir}/libpamc.so.*
%{_pamlibdir}/libpam_misc.so.*
%{_sbindir}/pam_console_apply
%{_sbindir}/pam_namespace_helper
%{_sbindir}/faillock
%attr(4755,root,root) %{_sbindir}/pam_timestamp_check
%attr(4755,root,root) %{_sbindir}/unix_chkpwd
@ -331,6 +385,7 @@ done
%{_moduledir}/pam_access.so
%{_moduledir}/pam_chroot.so
%{_moduledir}/pam_console.so
%{_moduledir}/pam_cracklib.so
%{_moduledir}/pam_debug.so
%{_moduledir}/pam_deny.so
%{_moduledir}/pam_echo.so
@ -364,7 +419,6 @@ done
%{_moduledir}/pam_sepermit.so
%endif
%{_moduledir}/pam_securetty.so
%{_moduledir}/pam_setquota.so
%{_moduledir}/pam_shells.so
%{_moduledir}/pam_stress.so
%{_moduledir}/pam_succeed_if.so
@ -385,7 +439,6 @@ done
%{_moduledir}/pam_wheel.so
%{_moduledir}/pam_xauth.so
%{_moduledir}/pam_filter
%{_systemdlibdir}/pam_namespace.service
%dir %{_secconfdir}
%config(noreplace) %{_secconfdir}/access.conf
%config(noreplace) %{_secconfdir}/chroot.conf
@ -427,149 +480,96 @@ done
%doc doc/adg/*.txt doc/adg/html
%doc doc/specs/rfc86.0.txt
%files docs
%doc doc/txts
%doc doc/sag/*.txt doc/sag/html
%changelog
* Thu Nov 21 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-22
- pam_access: rework resolving of tokens as hostname.
Resolves: CVE-2024-10963 and RHEL-66245
* Fri Mar 29 2024 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 1.3.1-33
- Rebuilt for MSVSphere 8.10 beta
* Wed Nov 6 2024 Diaa Sami <disami@redhat.com> - 1.5.1-21
- pam_unix: always run the helper to obtain shadow password file entries.
CVE-2024-10041. Resolves: RHEL-62880
* Tue Jun 18 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-20
- libpam: support long lines in service files. Resolves: RHEL-40705
* Mon Feb 12 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-19
* Mon Feb 12 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-33
- pam_namespace: protect_dir(): use O_DIRECTORY to prevent local DoS
situations. CVE-2024-22365. Resolves: RHEL-21244
* Fri Jan 26 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-18
- libpam: use getlogin() from libc and not utmp. Resolves: RHEL-16727
- pam_access: handle hostnames in access.conf. Resolves: RHEL-22300
* Mon Jan 8 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-17
- pam_faillock: create tallydir before creating tallyfile. Resolves: RHEL-20943
* Fri Nov 10 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-16
- libpam: use close_range() to close file descriptors. Resolves: RHEL-5099
- fix formatting of audit messages. Resolves: RHEL-5100
* Mon Jun 26 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-15
- pam_misc: make length of misc_conv() configurable and set to 4096. Resolves: #2215007
situations. CVE-2024-22365. Resolves: RHEL-21242
* Tue Nov 29 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-14
- pam_lastlog: check localtime_r() return value. Resolves: #2130124
- pam_faillock: clarify missing user faillock files after reboot. Resolves: #2126632
- pam_faillock: avoid logging an erroneous consecutive login failure message. Resolves: #2126648
* Fri Jan 26 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-32
- pam_access: handle hostnames in access.conf. Resolves: RHEL-3374
* Wed Sep 28 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-13
- pam_pwhistory: load configuration from file. Resolves: #2126640
* Mon Jan 8 2024 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-31
- pam_faillock: create tallydir before creating tallyfile. Resolves: RHEL-19810
* Thu Jun 23 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-12
- pam_usertype: only use SYS_UID_MAX for system users. Resolves: #2078421
* Thu Nov 2 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-30
- pam_unix: enable bcrypt. Resolves: RHEL-5057
* Wed May 25 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-11
- faillock: load configuration from file. Resolves: #2061698
* 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 17 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-10
- pam_keyinit: thread-safe implementation. Resolves: #2061696
* Tue May 16 2023 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-26
- smartcard-auth: modify the content to remove unnecessary modules. Resolves: #1983683
* Thu Dec 2 2021 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-9
- pam_limits: "Unlimited" is not a valid value for RLIMIT_NOFILE. Resolves: #1989900
* 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
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 1.5.1-8
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Thu Sep 29 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-24
- pam_pwhistory: load configuration from file. Resolves: #2068461
* Wed Jul 14 2021 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-7
- Fix issues detected by covscan tool
* Wed Jul 13 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-22
- Regenerate the /run/motd.d at each boot. Resolves: #2104878
* Fri Jul 2 2021 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-6
- pam_timestamp: openssl hmac authentication. Resolves: #1934975
* 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
* Mon Apr 19 2021 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-5
- Disable nis support. Resolves: #1942373
* Thu May 26 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-20
- faillock: load configuration from file. Resolves: #1978029
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 1.5.1-4
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.5.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Mon Nov 30 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-2
- Add BuildRequires: make (#1902520)
* Thu Nov 26 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.1-1
- Rebase to release 1.5.1
- fix CVE-2020-27780: authentication bypass when the user doesn't exist
and root password is blank (#1901173)
* Wed Nov 11 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.5.0-1
- Rebase to release 1.5.0
- Rebase to pam-redhat-1.1.4
- Remove pam_cracklib, pam_tally and pam_tally2
- spec file cleanup
* Fri Nov 6 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.4.0-7
- libpam: fix memory leak in pam_start (#1894630)
* 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
* Mon Oct 19 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.4.0-6
- pam_unix: fix missing initialization of daysleft (#1887077)
- pam_motd: change privilege message prompt to default (#1861640)
* Thu May 19 2022 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-18
- pam_motd: fix memory leak. Resolves: #2014458
* Wed Oct 14 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.4.0-5
- pam_motd: read motd files with target user credentials skipping unreadable ones (#1861640)
- Clarify upstreamed patches
* 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
* Tue Aug 04 2020 Tom Stellard <tstellar@redhat.com> - 1.4.0-4
- Add BuildRequires: gcc
- https://docs.fedoraproject.org/en-US/packaging-guidelines/C_and_C++/#_packaging
* 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
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.4.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon May 3 2021 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-15
- pam_userdb: Prevent garbage characters from db (#1791965)
* Thu Jul 2 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.4.0-2
- Enable layered configuration with distribution configs in /usr/share/pam.d
- Added new pam-redhat tarball to lookaside cache
* Thu Nov 5 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-14
- Revert 1.3.1-12
* Wed Jun 24 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.4.0-1
- Rebased to release 1.4.0
- Rebased to pam-redhat-1.1.3
- Removed pam_cracklib as it has been deprecated
* Fri Oct 30 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-13
- pam_wheel: if getlogin fails fallback to PAM_RUSER: fixed malformed patch (#1866866)
- pam_namespace: polyinstantiation refer to gdm doc (#1861841)
* Mon Jun 22 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-28
- pam_faillock: change /run/faillock/$USER permissions to 0660 (#1661822)
* Thu Jul 16 2020 Peter Robinson <pbrobinson@redhat.com> - 1.3.1-12
- Add the motd.d directories (empty) to silence warnings and to
provide proper ownership for them (#1847501)
* Wed Jun 17 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-27
- pam_unix and pam_usertype: avoid determining if user exists (#1629598)
* Fri May 15 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-11
- pam_usertype: fixed malformed patch
* Thu May 14 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-26
- pam_tty_audit: if kernel audit is disabled return PAM_IGNORE (#1775357)
* Tue Apr 21 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-10
- pam_modutil_sanitize_helper_fds: fix SIGPIPE effect of PAM_MODUTIL_PIPE_FD (#1791970)
* Thu Apr 23 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-25
- docs: splitted documentation in subpackage -docs
* Mon Mar 9 2020 Iker Pedrosa <ipedrosa@redhat.com> - 1.3.1-24
- pam_selinux: check unknown object classes or permissions in current policy
* Tue Feb 4 2020 Pavel Březina <pbrezina@redhat.com> - 1.3.1-23
- Add pam_usertype.so
* Fri Apr 17 2020 Iker Pedrosa <ipedrosa@redhat.com> 1.3.1-9
- pam_usertype: new module to tell if uid is in login.defs ranges (#1810474)
- pam_tty_audit: if kernel audit is disabled return PAM_IGNORE (#1775357)
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.3.1-22
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Dec 19 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-8
- pam_motd: Document how to properly silence unwanted motd messages
* Wed Dec 18 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-21
* Mon Dec 16 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-6
- pam_faillock: Fix regression in admin_group support
* Wed Oct 16 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-20
- pam_namespace: Support noexec, nosuid and nodev flags for tmpfs mounts
- Drop tallylog and pam_tally documentation
* Wed Oct 16 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-5
- pam_faillock: Support configuration file /etc/security/faillock.conf
- pam_faillock: Support local_users_only option
- pam_namespace: Support noexec, nosuid and nodev flags for tmpfs mounts
- Drop tallylog and pam_tally[2] documentation
- pam_lastlog: Do not display failed attempts with PAM_SILENT flag
- pam_lastlog: Support unlimited option to override fsize limit
- pam_unix: Log if user authenticated without password
@ -577,70 +577,13 @@ done
- Optimize closing fds when spawning helpers
- Fix duplicate password verification in pam_authtok_verify()
* Mon Sep 9 2019 Tomáš Mráz <tmraz@redhat.com> 1.3.1-19
- pam_faillock: Support configuration file /etc/security/faillock.conf
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.3.1-18
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Dec 7 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-4
- Drop pam_tally2 which was obsoleted and deprecated long time ago
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.3.1-17
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Mon Jan 14 2019 Björn Esser <besser82@fedoraproject.org> - 1.3.1-16
- Rebuilt for libcrypt.so.2 (#1666033)
* Thu Dec 20 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-15
- Add the motd.d directories (empty) to silence warnings and to
provide proper ownership for them (#1660935)
* Tue Dec 4 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-14
- Update Red Hat PAM modules to version 1.0.0 which includes pam_faillock
- Drop also pam_tally2 which was obsoleted and deprecated long time ago
* Sun Dec 02 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-13
- Backport upstream commit reporting disabled or invalid hashes to syslog
- Backport upstream commit fixing syslog for disabled or invalid hashes
* Wed Nov 28 2018 Robert Fairley <rfairley@redhat.com> 1.3.1-12
- Backport upstream commit pam_motd: Support multiple motd paths specified, with filename overrides (#69)
- Backport upstream commit pam_motd: Fix segmentation fault when no motd_dir specified (#76)
* Mon Nov 26 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-11
- Completely drop the check of invalid or disabled salt via crypt_checksalt
* Sun Nov 25 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-10
- Fix passphraseless sudo with crypt_checksalt (#1653023)
* Fri Nov 23 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-9
- Backport upstream commit removing an obsolete prototype
- Backport upstream commit preferring bcrypt_b ($2b$) for blowfish
- Backport upstream commit preferring gensalt with autoentropy
- Backport upstream commit using crypt_checksalt for password aging
- Backport upstream commit adding support for (gost-)yescrypt
- Update the no-MD5-fallback patch for alignment
* Fri Nov 16 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-8
- Use %%ldconfig_scriptlets
- Drop Requires(post), not needed anymore
- Prefer %%global over %%define
* Tue Nov 13 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-7
- when building against libxcrypt >= 4.3.3-2, we can avoid the explicit
dependency on libxcrypt >= 4.3.3-1
* Mon Nov 12 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-6
- add explicit (Build)Requires for libxcrypt >= 4.3.3-1
* Mon Nov 12 2018 Björn Esser <besser82@fedoraproject.org> - 1.3.1-5
- rebuilt against libxcrypt-4.3.3 to enable the use of crypt_gensalt_r
* Mon Sep 10 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-4
* Mon Sep 10 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-3
- add pam_umask to postlogin PAM configuration file
- fix some issues found by Coverity scan
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.3.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Fri Jun 8 2018 Tomáš Mráz <tmraz@redhat.com> 1.3.1-1
- use /run instead of /var/run in pamtmp.conf (#1588612)

Loading…
Cancel
Save