[packages/pam] up to 1.7.2
arekm
arekm at pld-linux.org
Tue Aug 18 13:44:03 CEST 2026
commit d5c25bb063e52293654b592956f25ad91186e7f3
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Tue Aug 18 13:22:52 2026 +0200
up to 1.7.2
Upstream switched to meson.
Backport CVE-2026-54411 fix (pam_userdb timing leak).
pam-memset_explicit-args.patch | 11 --
pam-mkhomedir-notfound.patch | 43 +++---
pam-pld-modules.patch | 263 +++++++++++++++++++++++++++++---
pam.spec | 138 +++++++----------
pam_access-rework-hostname-tokens.patch | 223 ---------------------------
pam_pwgen-pam_i18n.patch | 11 ++
pam_userdb-consttime-compare.patch | 157 +++++++++++++++++++
7 files changed, 480 insertions(+), 366 deletions(-)
---
diff --git a/pam.spec b/pam.spec
index bfb2817..31d9b7f 100644
--- a/pam.spec
+++ b/pam.spec
@@ -6,10 +6,8 @@
# Conditional build:
%bcond_without doc # documentation
%bcond_with econf # libeconf handled configuration
-%bcond_with prelude # Prelude IDS support (in libpam)
%bcond_without selinux # SELinux support
%bcond_without audit # Linux Auditing library support
-%bcond_without static_libs # static libraries
%bcond_without systemd # logind support
%define pam_pld_version 1.1.2-1
@@ -23,8 +21,8 @@ Summary(ru.UTF-8): Интструмент, обеспечивающий ауте
Summary(tr.UTF-8): Modüler, artımsal doğrulama birimleri
Summary(uk.UTF-8): Інструмент, що забезпечує аутентифікацію для програм
Name: pam
-Version: 1.6.0
-Release: 2
+Version: 1.7.2
+Release: 1
Epoch: 1
# The library is BSD licensed with option to relicense as GPLv2+
# - this option is redundant as the BSD license allows that anyway.
@@ -32,7 +30,7 @@ Epoch: 1
License: BSD and GPL v2+
Group: Base
Source0: https://github.com/linux-pam/linux-pam/releases/download/v%{version}/Linux-PAM-%{version}.tar.xz
-# Source0-md5: 41a10af5fc35a7be472ae9864338e64a
+# Source0-md5: 934c26eca3fada956356a30489e86291
Source2: ftp://ftp.pld-linux.org/software/pam/%{name}-pld-%{pam_pld_version}.tar.gz
# Source2-md5: f9ec6fcafcf1801bf318e60040244f2e
Source3: other.pamd
@@ -48,13 +46,12 @@ Patch1: %{name}_console-lex-static.patch
Patch3: %{name}-mkhomedir-notfound.patch
Patch5: %{name}-exec-failok.patch
Patch6: pam_console_pam_tty.patch
-Patch7: pam_access-rework-hostname-tokens.patch
-Patch8: pam-memset_explicit-args.patch
Patch9: pam_pwgen-const-argv.patch
+Patch10: pam_pwgen-pam_i18n.patch
+# CVE-2026-54411, fixed upstream after 1.7.2
+Patch11: pam_userdb-consttime-compare.patch
URL: http://www.linux-pam.org/
%{?with_audit:BuildRequires: audit-libs-devel >= 1.6.9}
-BuildRequires: autoconf >= 2.61
-BuildRequires: automake
BuildRequires: bison
BuildRequires: flex
# gdbm due to db pulling libpthread
@@ -63,14 +60,14 @@ BuildRequires: gettext-tools >= 0.18.3
BuildRequires: glibc-devel >= 6:2.10.1
%{?with_econf:BuildRequires: libeconf-devel >= 0.5.0}
BuildRequires: libnsl-devel
-%{?with_prelude:BuildRequires: libprelude-devel >= 0.9.0}
%{?with_selinux:BuildRequires: libselinux-devel >= 2.1.9}
BuildRequires: libtirpc-devel
-BuildRequires: libtool >= 2:2
BuildRequires: libxcrypt-devel
%{?with_audit:BuildRequires: linux-libc-headers >= 7:2.6.23.1}
+BuildRequires: meson >= 0.62.0
+BuildRequires: ninja >= 1.5
BuildRequires: pkgconfig
-BuildRequires: rpmbuild(macros) >= 1.527
+BuildRequires: rpmbuild(macros) >= 2.042
%{?with_systemd:BuildRequires: systemd-devel >= 1:254}
BuildRequires: tar >= 1:1.22
BuildRequires: xz
@@ -199,6 +196,7 @@ Group: Development/Libraries
Requires: %{name}-libs = %{epoch}:%{version}-%{release}
%{?with_audit:Requires: audit-libs-devel >= 1.0.8}
Requires: filesystem >= 3.0-11
+Obsoletes: %{name}-static < %{epoch}:1.7.2
%description devel
Header files for developing PAM based applications.
@@ -215,26 +213,6 @@ Bibliotecas e arquivos de inclusão para desenvolvimento com PAM
%description devel -l uk.UTF-8
Цей пакет містить хедери та бібліотеки програміста для PAM.
-%package static
-Summary: PAM static libraries
-Summary(pl.UTF-8): Biblioteki statyczne PAM
-Summary(ru.UTF-8): Статические библиотеки разработчика для PAM
-Summary(uk.UTF-8): Статичні бібліотеки програміста для PAM
-Group: Development/Libraries
-Requires: %{name}-devel = %{epoch}:%{version}-%{release}
-
-%description static
-PAM static libraries.
-
-%description static -l pl.UTF-8
-Biblioteki statyczne PAM.
-
-%description static -l ru.UTF-8
-Этот пакет содержит статические библиотеки разработчика для PAM.
-
-%description static -l uk.UTF-8
-Цей пакет містить статичні бібліотеки програміста для PAM.
-
%package pam_selinux
Summary: PAM module - SELinux support
Summary(pl.UTF-8): Moduł PAM pozwalający na zmianę kontekstów SELinuksa
@@ -269,60 +247,57 @@ danych GDBM.
%patch -P3 -p1
%patch -P5 -p1
%patch -P6 -p1
-%patch -P7 -p1
-%patch -P8 -p1
%patch -P9 -p1
+%patch -P10 -p1
+%patch -P11 -p1
%build
-%{__libtoolize}
-%{__aclocal} -I m4
-%{__autoconf}
-%{__autoheader}
-%{__automake}
-%configure \
- ac_cv_path_FO2PDF= \
- %{__enable_disable static_libs static} \
- --enable-shared \
+# -Dvendordir= : 1.7.2 turned vendordir on by default, which would move the
+# shipped configs out of /etc/security into /usr/share/pam/security
+%meson \
--libdir=/%{_lib} \
- --includedir=%{_includedir}/security \
- %{!?with_audit:--disable-audit} \
- --enable-db=gdbm \
- %{!?with_econf:--disable-econf} \
- %{!?with_doc:--disable-regenerate-docu} \
- --enable-isadir=../../%{_lib}/security \
- --enable-lastlog \
- %{__enable_disable systemd logind} \
- %{!?with_prelude:--disable-prelude} \
- %{!?with_selinux:--disable-selinux} \
- --with-systemdunitdir="%{systemdunitdir}"
-
-# we must explicitely update-gmo as we patch a po file
-%{__make} -C po update-gmo
-%{__make} \
- DEFS="-DHAVE_CONFIG_H -D_GNU_SOURCE"
+ -Daudit=%{__enabled_disabled audit} \
+ -Ddb=gdbm \
+ -Ddocs=%{__enabled_disabled doc} \
+ -Deconf=%{__enabled_disabled econf} \
+ -Delogind=disabled \
+ -Disadir=../../%{_lib}/security \
+ -Dlogind=%{__enabled_disabled systemd} \
+ -Dpam_lastlog=enabled \
+ -Dpwaccess=disabled \
+ -Dselinux=%{__enabled_disabled selinux} \
+ -Dsystemdunitdir=%{systemdunitdir} \
+ -Dvendordir=
+
+%meson_build
%install
rm -rf $RPM_BUILD_ROOT
install -d $RPM_BUILD_ROOT{%{_libdir},/etc/pam.d,/usr/lib/pam.d,/var/{log,run/sepermit}} \
$RPM_BUILD_ROOT%{systemdtmpfilesdir}
-%{__make} install \
- DESTDIR=$RPM_BUILD_ROOT \
- pkgconfigdir=%{_pkgconfigdir}
+%meson_install
+
+# meson installs these next to the libraries
+install -d $RPM_BUILD_ROOT%{_pkgconfigdir}
+%{__mv} $RPM_BUILD_ROOT/%{_lib}/pkgconfig/*.pc $RPM_BUILD_ROOT%{_pkgconfigdir}
+rmdir $RPM_BUILD_ROOT/%{_lib}/pkgconfig
%if %{with selinux}
-install -p modules/pam_selinux/.libs/pam_selinux_check $RPM_BUILD_ROOT%{_sbindir}
-cp -p modules/pam_selinux/pam_selinux_check.8 $RPM_BUILD_ROOT%{_mandir}/man8
+install -p %{_vpath_builddir}/modules/pam_selinux/pam_selinux_check $RPM_BUILD_ROOT%{_sbindir}
cp -p %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/pam_selinux_check
%endif
cp -p %{SOURCE9} $RPM_BUILD_ROOT%{systemdtmpfilesdir}/%{name}.conf
-install -d doc/txts
+%if %{with doc}
+install -d doc/txts doc/txts-userdb
+cp -p $RPM_BUILD_ROOT%{_docdir}/Linux-PAM/modules/*.txt doc/txts
for r in modules/pam_*/README; do
- cp -pf $r doc/txts/README.$(basename $(dirname $r))
+ cp -pf $r doc/txts/$(basename $(dirname $r)).txt
done
-%{__rm} doc/txts/README.pam_userdb
+%{__mv} doc/txts/pam_userdb.txt doc/txts-userdb
+%endif
install -d doc/html
cp -pf doc/index.html doc/html/
@@ -332,9 +307,6 @@ echo ".so PAM.8" > $RPM_BUILD_ROOT%{_mandir}/man8/pam.8
:> $RPM_BUILD_ROOT/etc/security/opasswd
:> $RPM_BUILD_ROOT/etc/security/blacklist
-%{?with_static_libs:%{__mv} $RPM_BUILD_ROOT/%{_lib}/lib*.a $RPM_BUILD_ROOT%{_libdir}}
-%{__rm} $RPM_BUILD_ROOT/%{_lib}/lib*.la
-
cd $RPM_BUILD_ROOT/%{_lib}
ln -sf /%{_lib}/$(echo libpam.so.*.*.*) $RPM_BUILD_ROOT%{_libdir}/libpam.so
ln -sf /%{_lib}/$(echo libpam_misc.so.*.*.*) $RPM_BUILD_ROOT%{_libdir}/libpam_misc.so
@@ -377,8 +349,6 @@ for module in $RPM_BUILD_ROOT/%{_lib}/security/pam*.so ; do
done
# useless - shut up check-files
-%{__rm} $RPM_BUILD_ROOT/%{_lib}/security/*.la
-%{?with_static_libs:%{__rm} $RPM_BUILD_ROOT/%{_lib}/security/*.a}
%{__rm} $RPM_BUILD_ROOT/%{_lib}/lib*.so
%{__rm} -r $RPM_BUILD_ROOT%{_docdir}/Linux-PAM
@@ -386,9 +356,9 @@ done
rm -rf rpm-doc
install -d rpm-doc
cp -a doc/html rpm-doc/html
-cp -a doc/sag/html rpm-doc/sag-html
-cp -a doc/adg/html rpm-doc/adg-html
-cp -a doc/mwg/html rpm-doc/mwg-html
+cp -a %{_vpath_builddir}/doc/sag/html rpm-doc/sag-html
+cp -a %{_vpath_builddir}/doc/adg/html rpm-doc/adg-html
+cp -a %{_vpath_builddir}/doc/mwg/html rpm-doc/mwg-html
%endif
%if %{without selinux}
@@ -457,9 +427,11 @@ fi
%files -f Linux-PAM.lang
%defattr(644,root,root,755)
-%doc AUTHORS CHANGELOG ChangeLog Copyright NEWS doc/txts/README*
+%doc AUTHORS Copyright NEWS
%if %{with doc}
-%doc doc/specs/*.txt doc/sag/Linux-PAM_*.txt rpm-doc/{html,sag-html}
+%doc doc/txts/*.txt
+%doc doc/specs/*.txt %{_vpath_builddir}/doc/specs/*.txt
+%doc %{_vpath_builddir}/doc/sag/Linux-PAM_*.txt rpm-doc/{html,sag-html}
%endif
%dir /etc/pam.d
%dir /etc/security/console.apps
@@ -600,7 +572,7 @@ fi
%files devel
%defattr(644,root,root,755)
%if %{with doc}
-%doc doc/{adg,mwg}/Linux-PAM_*.txt rpm-doc/{adg,mwg}-html
+%doc %{_vpath_builddir}/doc/{adg,mwg}/Linux-PAM_*.txt rpm-doc/{adg,mwg}-html
%endif
%attr(755,root,root) %{_libdir}/libpam.so
%attr(755,root,root) %{_libdir}/libpam_misc.so
@@ -613,14 +585,6 @@ fi
%{_mandir}/man3/misc_conv.3*
%{_mandir}/man3/pam*.3*
-%if %{with static_libs}
-%files static
-%defattr(644,root,root,755)
-%{_libdir}/libpam.a
-%{_libdir}/libpamc.a
-%{_libdir}/libpam_misc.a
-%endif
-
%if %{with selinux}
%files pam_selinux
%defattr(644,root,root,755)
@@ -637,6 +601,6 @@ fi
%files pam_userdb
%defattr(644,root,root,755)
-%doc modules/pam_userdb/README
+%{?with_doc:%doc doc/txts-userdb/pam_userdb.txt}
%attr(755,root,root) /%{_lib}/security/pam_userdb.so
%{_mandir}/man8/pam_userdb.8*
diff --git a/pam-memset_explicit-args.patch b/pam-memset_explicit-args.patch
deleted file mode 100644
index a084339..0000000
--- a/pam-memset_explicit-args.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- Linux-PAM-1.6.0.orig/libpam/include/pam_inline.h
-+++ Linux-PAM-1.6.0/libpam/include/pam_inline.h
-@@ -82,7 +82,7 @@ pam_str_skip_icase_prefix_len(const char
- static inline void pam_overwrite_n(void *ptr, size_t len)
- {
- if (ptr)
-- memset_explicit(ptr, len);
-+ memset_explicit(ptr, 0, len);
- }
- #elif defined HAVE_EXPLICIT_BZERO
- static inline void pam_overwrite_n(void *ptr, size_t len)
diff --git a/pam-mkhomedir-notfound.patch b/pam-mkhomedir-notfound.patch
index c60fc49..0c97a80 100644
--- a/pam-mkhomedir-notfound.patch
+++ b/pam-mkhomedir-notfound.patch
@@ -1,6 +1,6 @@
-diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8.xml
---- Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2006-05-30 15:03:09.000000000 +0200
-+++ Linux-PAM-0.99.7.1/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2007-02-03 22:09:37.942620000 +0100
+diff -urN Linux-PAM-1.7.2.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linux-PAM-1.7.2/modules/pam_mkhomedir/pam_mkhomedir.8.xml
+--- Linux-PAM-1.7.2.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2026-01-22 09:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_mkhomedir/pam_mkhomedir.8.xml 2026-08-18 12:12:05.673038517 +0200
@@ -29,6 +29,9 @@
umask=<replaceable>mode</replaceable>
</arg>
@@ -11,10 +11,13 @@ diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linu
skel=<replaceable>skeldir</replaceable>
</arg>
</cmdsynopsis>
-@@ -82,6 +94,20 @@
-
- <varlistentry>
- <term>
+@@ -106,6 +109,20 @@
+ </para>
+ </listitem>
+ </varlistentry>
++
++ <varlistentry>
++ <term>
+ <option>notfound=[<replaceable>create</replaceable>|<replaceable>deny</replaceable>|<replaceable>ignore</replaceable>]</option>
+ </term>
+ <listitem>
@@ -26,16 +29,14 @@ diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linu
+ </para>
+ </listitem>
+ </varlistentry>
-+
-+ <varlistentry>
-+ <term>
- skel=/path/to/skel/directory
- </term>
- <listitem>
---- Linux-PAM-1.4.0/modules/pam_mkhomedir/pam_mkhomedir.c.orig 2020-06-08 12:17:27.000000000 +0200
-+++ Linux-PAM-1.4.0/modules/pam_mkhomedir/pam_mkhomedir.c 2020-08-25 19:45:06.233402760 +0200
-@@ -53,8 +53,11 @@
- #include "pam_inline.h"
+
+ <varlistentry>
+ <term>
+diff -urN Linux-PAM-1.7.2.orig/modules/pam_mkhomedir/pam_mkhomedir.c Linux-PAM-1.7.2/modules/pam_mkhomedir/pam_mkhomedir.c
+--- Linux-PAM-1.7.2.orig/modules/pam_mkhomedir/pam_mkhomedir.c 2026-01-22 09:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_mkhomedir/pam_mkhomedir.c 2026-08-18 12:12:05.673356863 +0200
+@@ -54,8 +54,11 @@
+ #include "pam_i18n.h"
/* argument parsing */
-#define MKHOMEDIR_DEBUG 020 /* be verbose about things */
@@ -48,16 +49,16 @@ diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linu
#define LOGIN_DEFS "/etc/login.defs"
#define UMASK_DEFAULT "0022"
-@@ -67,7 +70,7 @@
+@@ -76,7 +79,7 @@
_pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv,
options_t *opt)
{
- opt->ctrl = 0;
+ opt->ctrl = HOMEDIR_CREATE;
opt->umask = NULL;
- opt->skeldir = "/etc/skel";
+ opt->skeldir = NULL;
-@@ -88,6 +91,15 @@
+@@ -97,6 +100,15 @@
opt->umask = str;
} else if ((str = pam_str_skip_prefix(*argv, "skel=")) != NULL) {
opt->skeldir = str;
@@ -73,7 +74,7 @@ diff -urN Linux-PAM-0.99.7.1.orig/modules/pam_mkhomedir/pam_mkhomedir.8.xml Linu
} else {
pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
}
-@@ -221,7 +233,12 @@
+@@ -261,7 +273,12 @@
return PAM_SUCCESS;
}
diff --git a/pam-pld-modules.patch b/pam-pld-modules.patch
index 0049144..e6fc381 100644
--- a/pam-pld-modules.patch
+++ b/pam-pld-modules.patch
@@ -1,24 +1,239 @@
---- Linux-PAM-1.6.0/configure.ac.orig 2024-03-22 18:58:45.064426280 +0100
-+++ Linux-PAM-1.6.0/configure.ac 2024-03-22 18:59:27.857527783 +0100
-@@ -774,6 +774,8 @@ AC_CONFIG_FILES([Makefile libpam/Makefil
- po/Makefile.in \
- Make.xml.rules \
- modules/Makefile \
-+ modules/pam_console/Makefile modules/pam_pwexport/Makefile \
-+ modules/pam_pwgen/Makefile modules/pam_rps/Makefile \
- modules/pam_access/Makefile \
- modules/pam_canonicalize_user/Makefile \
- modules/pam_debug/Makefile modules/pam_deny/Makefile \
---- Linux-PAM-1.4.0.org/modules/Makefile.am 2020-06-08 12:17:27.000000000 +0200
-+++ Linux-PAM-1.4.0/modules/Makefile.am 2021-03-21 13:19:44.089594925 +0100
-@@ -98,6 +98,10 @@ SUBDIRS := \
- pam_warn \
- pam_wheel \
- pam_xauth \
-+ pam_console \
-+ pam_pwexport \
-+ pam_pwgen \
-+ pam_rps \
- #
-
- CLEANFILES = *~
+--- Linux-PAM-1.7.2.orig/modules/meson.build 2026-01-22 09:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/meson.build 2026-08-18 12:15:36.703326906 +0200
+@@ -43,3 +43,9 @@
+ subdir('pam_warn')
+ subdir('pam_wheel')
+ subdir('pam_xauth')
++
++# PLD-specific modules, shipped in pam-pld-*.tar.gz
++subdir('pam_console')
++subdir('pam_pwexport')
++subdir('pam_pwgen')
++subdir('pam_rps')
+--- Linux-PAM-1.7.2.orig/modules/maps/modules-auth-password.map 1970-01-01 01:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/maps/modules-auth-password.map 1970-01-01 01:00:00.000000000 +0100
+@@ -0,0 +1,7 @@
++{
++ global:
++ pam_sm_authenticate;
++ pam_sm_chauthtok;
++ pam_sm_setcred;
++ local: *;
++};
+--- Linux-PAM-1.7.2.orig/modules/pam_console/meson.build 1970-01-01 01:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_console/meson.build 1970-01-01 01:00:00.000000000 +0100
+@@ -0,0 +1,87 @@
++# -*- mode: meson -*-
++# PLD-specific module, not part of upstream Linux-PAM.
++
++pam_console_lockdir = localstatedir / 'run' / 'console'
++pam_console_c_args = ['-DLOCKDIR="@0@"'.format(pam_console_lockdir)]
++
++pam_module_map_path = meson.current_source_dir() / '..' / 'maps' / 'modules-auth-session.map'
++
++shared_module(
++ 'pam_console',
++ name_prefix: '',
++ sources: ['pam_console.c', 'regerr.c', 'handlers.c'],
++ c_args: pam_console_c_args,
++ dependencies: [libpam_internal_dep, libpam_dep],
++ link_depends: [pam_module_map_path],
++ link_args: ['-Wl,--version-script=' + pam_module_map_path],
++ install: true,
++ install_dir: securedir,
++)
++
++configfile_gen = custom_target(
++ 'configfile-gen',
++ output: ['configfile.tab.c', 'configfile.tab.h', 'configfile.lex.c'],
++ command: [
++ find_program('sh'),
++ files('gen-configfile.sh'),
++ meson.current_source_dir(),
++ prog_yacc,
++ prog_flex,
++ '@OUTPUT0@',
++ '@OUTPUT2@',
++ ],
++)
++
++executable(
++ 'pam_console_apply',
++ sources: [
++ 'pam_console_apply.c',
++ 'chmod.c',
++ 'modechange.c',
++ 'regerr.c',
++ 'configfile.c',
++ 'hashtable.c',
++ # configfile.c #includes the generated sources; naming the header here is
++ # what orders the generator before this target is compiled
++ configfile_gen[1],
++ ],
++ c_args: pam_console_c_args,
++ link_args: exe_link_args,
++ dependencies: [libpam_internal_dep, libpam_dep],
++ install: true,
++ install_dir: sbindir,
++)
++
++install_data(
++ ['console.apps.5', 'console.handlers.5', 'console.perms.5'],
++ install_dir: mandir / 'man5',
++ install_tag: 'man',
++)
++
++install_data(
++ ['pam_console.8', 'pam_console_apply.8'],
++ install_dir: mandir / 'man8',
++ install_tag: 'man',
++)
++
++install_data(
++ ['console.handlers', 'console.perms'],
++ install_dir: sconfigdir,
++ install_tag: 'config',
++)
++
++install_data(
++ '50-default.perms',
++ install_dir: sconfigdir / 'console.perms.d',
++ install_tag: 'config',
++)
++
++install_emptydir(
++ sconfigdir / 'console.apps',
++ install_tag: 'config',
++)
++
++install_emptydir(
++ pam_console_lockdir,
++ install_tag: 'config',
++)
+--- Linux-PAM-1.7.2.orig/modules/pam_pwexport/meson.build 1970-01-01 01:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_pwexport/meson.build 1970-01-01 01:00:00.000000000 +0100
+@@ -0,0 +1,21 @@
++# -*- mode: meson -*-
++# PLD-specific module, not part of upstream Linux-PAM.
++
++pam_module_map_path = meson.current_source_dir() / '..' / 'maps' / 'modules-auth-password.map'
++
++shared_module(
++ 'pam_pwexport',
++ name_prefix: '',
++ sources: ['pam_pwexport.c'],
++ dependencies: [libpam_internal_dep, libpam_dep],
++ link_depends: [pam_module_map_path],
++ link_args: ['-Wl,--version-script=' + pam_module_map_path],
++ install: true,
++ install_dir: securedir,
++)
++
++install_data(
++ 'pam_pwexport.8',
++ install_dir: mandir / 'man8',
++ install_tag: 'man',
++)
+--- Linux-PAM-1.7.2.orig/modules/pam_pwgen/meson.build 1970-01-01 01:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_pwgen/meson.build 1970-01-01 01:00:00.000000000 +0100
+@@ -0,0 +1,56 @@
++# -*- mode: meson -*-
++# PLD-specific module, not part of upstream Linux-PAM.
++
++pam_module_map_path = meson.current_source_dir() / '..' / 'maps' / 'modules-password.map'
++
++shared_module(
++ 'pam_pwgen',
++ name_prefix: '',
++ sources: ['pam_pwgen.c'],
++ dependencies: [libpam_internal_dep, libpam_dep, libcrypt, libaudit],
++ link_depends: [pam_module_map_path],
++ link_args: ['-Wl,--version-script=' + pam_module_map_path],
++ install: true,
++ install_dir: securedir,
++)
++
++executable(
++ 'pam_pwgen',
++ sources: ['pam_pwgen_app.c'],
++ link_args: exe_link_args,
++ dependencies: [libpam_internal_dep, libpam_dep, libaudit],
++ install: true,
++ install_dir: prefixdir / get_option('bindir'),
++)
++
++executable(
++ 'pwgen_trigram',
++ sources: ['pwgen_trigram.c'],
++ link_args: exe_link_args,
++ dependencies: [libpam_internal_dep, libpam_dep, libaudit],
++ install: true,
++ install_dir: sbindir,
++)
++
++install_data(
++ [
++ 'trigram.de',
++ 'trigram.dk',
++ 'trigram.en',
++ 'trigram.es',
++ 'trigram.fi',
++ 'trigram.it',
++ 'trigram.ja',
++ 'trigram.no',
++ 'trigram.pl',
++ ],
++ install_dir: sconfigdir,
++ install_tag: 'config',
++)
++
++install_symlink(
++ 'trigram',
++ pointing_to: 'trigram.en',
++ install_dir: sconfigdir,
++ install_tag: 'config',
++)
+--- Linux-PAM-1.7.2.orig/modules/pam_rps/meson.build 1970-01-01 01:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_rps/meson.build 1970-01-01 01:00:00.000000000 +0100
+@@ -0,0 +1,21 @@
++# -*- mode: meson -*-
++# PLD-specific module, not part of upstream Linux-PAM.
++
++pam_module_map_path = meson.current_source_dir() / '..' / 'maps' / 'modules-auth.map'
++
++shared_module(
++ 'pam_rps',
++ name_prefix: '',
++ sources: ['pam_rps.c'],
++ dependencies: [libpam_internal_dep, libpam_dep],
++ link_depends: [pam_module_map_path],
++ link_args: ['-Wl,--version-script=' + pam_module_map_path],
++ install: true,
++ install_dir: securedir,
++)
++
++install_data(
++ 'pam_rps.8',
++ install_dir: mandir / 'man8',
++ install_tag: 'man',
++)
+--- Linux-PAM-1.7.2.orig/modules/pam_console/gen-configfile.sh 1970-01-01 01:00:00.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_console/gen-configfile.sh 1970-01-01 01:00:00.000000000 +0100
+@@ -0,0 +1,17 @@
++#!/bin/sh
++# configfile.c #includes the generated parser and lexer, so their internals
++# have to become static; sed-static does that rewriting.
++set -e
++
++srcdir=$1
++yacc=$2
++lex=$3
++tab_c=$4
++lex_c=$5
++
++# -d makes bison derive the header name from the -o argument
++"$yacc" -d -o "$tab_c" -p _pc_yy "$srcdir/configfile.y"
++sh "$srcdir/sed-static" "$tab_c"
++
++"$lex" -Cr -o"$lex_c" -P_pc_yy "$srcdir/configfile.l"
++sh "$srcdir/sed-static" "$lex_c"
diff --git a/pam_access-rework-hostname-tokens.patch b/pam_access-rework-hostname-tokens.patch
deleted file mode 100644
index f08cf0a..0000000
--- a/pam_access-rework-hostname-tokens.patch
+++ /dev/null
@@ -1,223 +0,0 @@
-From: Thorsten Kukuk <kukuk at suse.com>
-Date: Thu, 14 Nov 2024 10:27:28 +0100
-Subject: pam_access: rework resolving of tokens as hostname
-
-* modules/pam_access/pam_access.c: separate resolving of IP addresses
- from hostnames. Don't resolve TTYs or display variables as hostname
- (#834).
- Add "nodns" option to disallow resolving of tokens as hostname.
-* modules/pam_access/pam_access.8.xml: document nodns option
-* modules/pam_access/access.conf.5.xml: document that hostnames should
- be written as FQHN.
-
-(cherry picked from commit 940747f88c16e029b69a74e80a2e94f65cb3e628)
----
- modules/pam_access/access.conf.5.xml | 4 ++
- modules/pam_access/pam_access.8.xml | 46 +++++++++++++++--------
- modules/pam_access/pam_access.c | 72 +++++++++++++++++++++++++++++++++++-
- 3 files changed, 105 insertions(+), 17 deletions(-)
-
-diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml
-index 65c6b69..67e5354 100644
---- a/modules/pam_access/access.conf.5.xml
-+++ b/modules/pam_access/access.conf.5.xml
-@@ -233,6 +233,10 @@
- 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 xml:id="access.conf-see_also">
-diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml
-index dcc5039..d907b80 100644
---- a/modules/pam_access/pam_access.8.xml
-+++ b/modules/pam_access/pam_access.8.xml
-@@ -22,11 +22,14 @@
- <arg choice="opt" rep="norepeat">
- debug
- </arg>
-+ <arg choice="opt" rep="norepeat">
-+ noaudit
-+ </arg>
- <arg choice="opt" rep="norepeat">
- nodefgroup
- </arg>
- <arg choice="opt" rep="norepeat">
-- noaudit
-+ nodns
- </arg>
- <arg choice="opt" rep="norepeat">
- quiet_log
-@@ -132,6 +135,33 @@
- </listitem>
- </varlistentry>
-
-+ <varlistentry>
-+ <term>
-+ 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
-@@ -185,20 +215,6 @@
- </listitem>
- </varlistentry>
-
-- <varlistentry>
-- <term>
-- 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>
--
- </variablelist>
- </refsect1>
-
-diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
-index 11f6b92..15acbf9 100644
---- a/modules/pam_access/pam_access.c
-+++ b/modules/pam_access/pam_access.c
-@@ -100,6 +100,7 @@ struct login_info {
- int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */
- int noaudit; /* Do not audit denials */
- int quiet_log; /* Do not log 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 */
-@@ -154,6 +155,8 @@ parse_args(pam_handle_t *pamh, struct login_info *loginfo,
- loginfo->noaudit = YES;
- } else if (strcmp (argv[i], "quiet_log") == 0) {
- loginfo->quiet_log = YES;
-+ } else if (strcmp (argv[i], "nodns") == 0) {
-+ loginfo->nodns = YES;
- } else {
- pam_syslog(pamh, LOG_ERR, "unrecognized option [%s]", argv[i]);
- }
-@@ -820,7 +823,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item)
- if ((str_len = strlen(string)) > tok_len
- && strcasecmp(tok, string + str_len - tok_len) == 0)
- return YES;
-- } else if (tok[tok_len - 1] == '.') { /* internet network numbers (end with ".") */
-+ } else if (tok[tok_len - 1] == '.') { /* internet network numbers/subnet (end with ".") */
- struct addrinfo hint;
-
- memset (&hint, '\0', sizeof (hint));
-@@ -895,6 +898,39 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string,
- }
-
-
-+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
-@@ -956,10 +992,42 @@ network_netmask_match (pam_handle_t *pamh,
- 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)
diff --git a/pam_pwgen-pam_i18n.patch b/pam_pwgen-pam_i18n.patch
new file mode 100644
index 0000000..d8237dc
--- /dev/null
+++ b/pam_pwgen-pam_i18n.patch
@@ -0,0 +1,11 @@
+--- Linux-PAM-1.7.2.orig/modules/pam_pwgen/pam_pwgen.c 2007-02-05 15:50:40.000000000 +0100
++++ Linux-PAM-1.7.2/modules/pam_pwgen/pam_pwgen.c 2026-08-18 12:17:51.700819525 +0200
+@@ -63,6 +63,8 @@
+ #include <security/_pam_macros.h>
+ #include <security/pam_ext.h>
+
++#include "pam_i18n.h"
++
+ #ifndef LINUX_PAM
+ #include <security/pam_appl.h>
+ #endif /* LINUX_PAM */
diff --git a/pam_userdb-consttime-compare.patch b/pam_userdb-consttime-compare.patch
new file mode 100644
index 0000000..5be97d9
--- /dev/null
+++ b/pam_userdb-consttime-compare.patch
@@ -0,0 +1,157 @@
+From 30708d973b63891bf700299ce3ae0f1086398284 Mon Sep 17 00:00:00 2001
+From: vlefebvre <valentin.lefebvre at suse.com>
+Date: Tue, 16 Jun 2026 16:31:29 +0200
+Subject: [PATCH] pam_userdb: fix password comparison timing leak
+
+* libpam/include/pam_inline.h: Include <ctype.h>.
+(pam_consttime_strcaseeq): New function that implements a constant-time,
+case-insensitive string equality check.
+* modules/pam_userdb/pam_userdb.c (user_lookup): Use it along with
+pam_consttime_streq instead of strncmp and strncasecmp to fix
+timing side-channel that leaks password prefix bytes and length
+(CWE-208).
+
+Resolves: https://github.com/linux-pam/linux-pam/issues/992
+Co-authored-by: Dmitry V. Levin <ldv at strace.io>
+---
+ libpam/include/pam_inline.h | 20 +++++++++
+ modules/pam_userdb/pam_userdb.c | 75 +++++++++++++++++++--------------
+ 2 files changed, 64 insertions(+), 31 deletions(-)
+
+diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h
+index d79d6fdf2..86d131cf4 100644
+--- a/libpam/include/pam_inline.h
++++ b/libpam/include/pam_inline.h
+@@ -9,6 +9,7 @@
+ #define PAM_INLINE_H
+
+ #include "pam_cc_compat.h"
++#include <ctype.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -244,4 +245,23 @@ pam_consttime_streq(const char *userinput, const char *secret) {
+ return ret == 0;
+ }
+
++/*
++ * Constant-time, case-insensitive string equality check.
++ * Same contract as pam_consttime_streq but uses tolower() on each byte.
++ * Runs for exactly strlen(userinput)+1 iterations regardless of secret.
++ */
++static inline int
++pam_consttime_strcaseeq(const char *userinput, const char *secret) {
++ volatile const char *u = userinput, *s = secret;
++ volatile int ret = 0;
++
++ do {
++ ret |= tolower((unsigned char)*u) ^ tolower((unsigned char)*s);
++
++ s += !!*s;
++ } while (*u++ != '\0');
++
++ return ret == 0;
++}
++
+ #endif /* PAM_INLINE_H */
+diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
+index bdb8553cc..b37f096cd 100644
+--- a/modules/pam_userdb/pam_userdb.c
++++ b/modules/pam_userdb/pam_userdb.c
+@@ -321,15 +321,24 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
+ } else {
+
+ /* Unknown password encryption method -
+- * default to plaintext password storage
++ * default to plaintext password storage.
++ * Use constant-time comparison: strncmp/strncasecmp leak prefix bytes
++ * and the length pre-check leaks the password length (CWE-208).
+ */
+
+- if (strlen(pass) != (size_t)data.dsize) {
+- compare = 1; /* wrong password len -> wrong password */
+- } else if (ctrl & PAM_ICASE_ARG) {
+- compare = strncasecmp(data.dptr, pass, data.dsize);
++ /* libdb is not guaranteed to produce null-terminated strings */
++ char *stored = strndup(data.dptr, data.dsize);
++ if (stored == NULL) {
++ pam_syslog(pamh, LOG_CRIT, "strndup failed: data.dptr");
++ compare = -2;
+ } else {
+- compare = strncmp(data.dptr, pass, data.dsize);
++ if (ctrl & PAM_ICASE_ARG) {
++ compare = pam_consttime_strcaseeq(pass, stored) ? 0 : 1;
++ } else {
++ compare = pam_consttime_streq(pass, stored) ? 0 : 1;
++ }
++ pam_overwrite_string(stored);
++ free(stored);
+ }
+
+ if (cryptmode && pam_str_skip_icase_prefix(cryptmode, "none") == NULL
+@@ -361,36 +370,40 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
+ }
+
+ /* now handle the key_only case */
++ size_t ulen = strlen(user);
+ for (key = db_firstkey(dbm);
+ key.dptr != NULL;
+ key = db_nextkey(dbm, key)) {
+- int compare;
+- /* first compare the user portion (case sensitive) */
+- compare = strncmp(key.dptr, user, strlen(user));
+- if (compare == 0) {
+- /* assume failure */
+- compare = -1;
+- /* if we have the divider where we expect it to be... */
+- if (key.dptr[strlen(user)] == '-') {
+- saw_user = 1;
+- if ((size_t)key.dsize == strlen(user) + 1 + strlen(pass)) {
+- if (ctrl & PAM_ICASE_ARG) {
+- /* compare the password portion (case insensitive)*/
+- compare = strncasecmp(key.dptr + strlen(user) + 1,
+- pass,
+- strlen(pass));
+- } else {
+- /* compare the password portion (case sensitive) */
+- compare = strncmp(key.dptr + strlen(user) + 1,
+- pass,
+- strlen(pass));
+- }
+- }
+- }
+- if (compare == 0) {
++ /* assume failure */
++ int compare = -1;
++
++ /*
++ * First compare the user portion (case sensitive);
++ * user is caller-supplied, so this memcmp leaks nothing secret.
++ */
++ if ((size_t)key.dsize > ulen &&
++ key.dptr[ulen] == '-' &&
++ memcmp(key.dptr, user, ulen) == 0) {
++ saw_user = 1;
++ char *stored_pass = strndup(key.dptr + ulen + 1,
++ key.dsize - ulen - 1);
++ if (stored_pass == NULL) {
+ db_close(dbm);
+- return 0; /* match */
++ return -2;
+ }
++ /* compare the password portion (case (in)sensitive) */
++ if (ctrl & PAM_ICASE_ARG) {
++ compare = pam_consttime_strcaseeq(pass, stored_pass) ? 0 : 1;
++ } else {
++ compare = pam_consttime_streq(pass, stored_pass) ? 0 : 1;
++ }
++ pam_overwrite_string(stored_pass);
++ free(stored_pass);
++ }
++
++ if (compare == 0) {
++ db_close(dbm);
++ return 0; /* match */
+ }
+ }
+ db_close(dbm);
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/pam.git/commitdiff/d5c25bb063e52293654b592956f25ad91186e7f3
More information about the pld-cvs-commit
mailing list