summaryrefslogtreecommitdiff
path: root/modules/pam_unix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_unix')
-rw-r--r--modules/pam_unix/CHANGELOG18
-rw-r--r--modules/pam_unix/Makefile.am20
-rw-r--r--modules/pam_unix/Makefile.in300
-rw-r--r--modules/pam_unix/README34
-rw-r--r--modules/pam_unix/bigcrypt.c2
-rw-r--r--modules/pam_unix/md5.c7
-rw-r--r--modules/pam_unix/md5.h4
-rw-r--r--modules/pam_unix/md5_crypt.c5
-rw-r--r--modules/pam_unix/pam_unix.845
-rw-r--r--modules/pam_unix/pam_unix.8.xml69
-rw-r--r--modules/pam_unix/pam_unix_acct.c57
-rw-r--r--modules/pam_unix/pam_unix_auth.c26
-rw-r--r--modules/pam_unix/pam_unix_passwd.c62
-rw-r--r--modules/pam_unix/pam_unix_sess.c43
-rw-r--r--modules/pam_unix/passverify.c133
-rw-r--r--modules/pam_unix/passverify.h8
-rw-r--r--modules/pam_unix/support.c200
-rw-r--r--modules/pam_unix/support.h113
-rw-r--r--modules/pam_unix/unix_chkpwd.86
-rw-r--r--modules/pam_unix/unix_chkpwd.c11
-rw-r--r--modules/pam_unix/unix_update.86
21 files changed, 694 insertions, 475 deletions
diff --git a/modules/pam_unix/CHANGELOG b/modules/pam_unix/CHANGELOG
index c18acc27..f8f70f59 100644
--- a/modules/pam_unix/CHANGELOG
+++ b/modules/pam_unix/CHANGELOG
@@ -1,6 +1,6 @@
$Id$
-* Mon Aug 16 1999 Jan Rêkorajski <baggins@pld.org.pl>
+* Mon Aug 16 1999 Jan Rękorajski <baggins@pld.org.pl>
- fixed reentrancy problems
* Sun Jul 4 21:03:42 PDT 1999
@@ -15,7 +15,7 @@ $Id$
* Sun Jun 27 1999 Steve Langasek <vorlon@netexpress.net>
- fix to uid-handling code for NIS+
-* Sat Jun 26 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Sat Jun 26 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- merged MD5 fix and early failure syslog
by Andrey Vladimirovich Savochkin <saw@msu.ru>
- minor fixes
@@ -24,31 +24,31 @@ $Id$
* Fri Jun 25 1999 Stephen Langasek <vorlon@netexpress.net>
- reorganized the code to let it build as separate C files
-* Sun Jun 20 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Sun Jun 20 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- fixes in pam_unix_auth, it incorrectly saved and restored return
value when likeauth option was used
-* Tue Jun 15 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Tue Jun 15 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- added NIS+ support
-* Mon Jun 14 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Mon Jun 14 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- total rewrite based on pam_pwdb module, now there is ONE pam_unix.so
module, it accepts the same options as pam_pwdb - all of them correctly ;)
(pam_pwdb dosn't understand what DISALLOW_NULL_AUTHTOK means)
-* Tue Apr 20 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Tue Apr 20 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- Arghhh, pam_unix_passwd was not updating /etc/shadow when used with
pam_cracklib.
-* Mon Apr 19 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Mon Apr 19 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- added "remember=XXX" option that means 'remember XXX old passwords'
Old passwords are stored in /etc/security/opasswd, there can be
maximum of 400 passwords per user.
-* Sat Mar 27 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Sat Mar 27 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- added crypt16 to pam_unix_auth and pam_unix_passwd (check only, this algorithm
is too lame to use it in real life)
-* Sun Mar 21 1999 Jan Rêkorajski <baggins@mimuw.edu.pl>
+* Sun Mar 21 1999 Jan Rękorajski <baggins@mimuw.edu.pl>
- pam_unix_auth now correctly behave when user has NULL AUTHTOK
- pam_unix_auth returns PAM_PERM_DENIED when seteuid fails
diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am
index 56df1782..6463872a 100644
--- a/modules/pam_unix/Makefile.am
+++ b/modules/pam_unix/Makefile.am
@@ -5,13 +5,14 @@
CLEANFILES = *~
MAINTAINERCLEANFILES = $(MANS) README
-EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c $(MANS) CHANGELOG \
- tst-pam_unix $(XMLS)
+EXTRA_DIST = md5.c md5_crypt.c lckpwdf.-c $(XMLS) CHANGELOG
-man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8
+if HAVE_DOC
+dist_man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8
+endif
XMLS = README.xml pam_unix.8.xml unix_chkpwd.8.xml unix_update.8.xml
-
-TESTS = tst-pam_unix
+dist_check_SCRIPTS = tst-pam_unix
+TESTS = $(dist_check_SCRIPTS)
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
@@ -19,11 +20,7 @@ secureconfdir = $(SCONFIGDIR)
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
-DUPDATE_HELPER=\"$(sbindir)/unix_update\" \
- @TIRPC_CFLAGS@ @NSL_CFLAGS@
-
-if HAVE_LIBSELINUX
- AM_CFLAGS += -D"WITH_SELINUX"
-endif
+ @TIRPC_CFLAGS@ @NSL_CFLAGS@ $(WARN_CFLAGS)
pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
@@ -61,7 +58,6 @@ unix_update_LDFLAGS = @PIE_LDFLAGS@
unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
if ENABLE_REGENERATE_MAN
-noinst_DATA = README
-README: pam_unix.8.xml
+dist_noinst_DATA = README
-include $(top_srcdir)/Make.xml.rules
endif
diff --git a/modules/pam_unix/Makefile.in b/modules/pam_unix/Makefile.in
index 806f04c8..bfc1a252 100644
--- a/modules/pam_unix/Makefile.in
+++ b/modules/pam_unix/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -22,7 +22,17 @@
VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@@ -85,14 +95,10 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-@HAVE_LIBSELINUX_TRUE@am__append_1 = -D"WITH_SELINUX"
-@HAVE_VERSIONING_TRUE@am__append_2 = -Wl,--version-script=$(srcdir)/../modules.map
+@HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map
sbin_PROGRAMS = unix_chkpwd$(EXEEXT) unix_update$(EXEEXT)
noinst_PROGRAMS = bigcrypt$(EXEEXT)
subdir = modules/pam_unix
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS) \
- $(top_srcdir)/build-aux/test-driver README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
@@ -108,10 +114,16 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \
+ $(am__dist_noinst_DATA_DIST) $(noinst_HEADERS) \
+ $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(securelibdir)" \
+ "$(DESTDIR)$(man8dir)"
+PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -139,8 +151,6 @@ am__uninstall_files_from_dir = { \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
-am__installdirs = "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(sbindir)" \
- "$(DESTDIR)$(man8dir)"
LTLIBRARIES = $(securelib_LTLIBRARIES)
pam_unix_la_DEPENDENCIES = $(top_builddir)/libpam/libpam.la
am_pam_unix_la_OBJECTS = bigcrypt.lo pam_unix_acct.lo pam_unix_auth.lo \
@@ -154,7 +164,6 @@ am__v_lt_1 =
pam_unix_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(pam_unix_la_LDFLAGS) $(LDFLAGS) -o $@
-PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS)
am_bigcrypt_OBJECTS = bigcrypt-bigcrypt.$(OBJEXT) \
bigcrypt-bigcrypt_main.$(OBJEXT)
bigcrypt_OBJECTS = $(am_bigcrypt_OBJECTS)
@@ -196,7 +205,24 @@ am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/bigcrypt-bigcrypt.Po \
+ ./$(DEPDIR)/bigcrypt-bigcrypt_main.Po ./$(DEPDIR)/bigcrypt.Plo \
+ ./$(DEPDIR)/md5_broken.Plo ./$(DEPDIR)/md5_good.Plo \
+ ./$(DEPDIR)/pam_unix_acct.Plo ./$(DEPDIR)/pam_unix_auth.Plo \
+ ./$(DEPDIR)/pam_unix_passwd.Plo ./$(DEPDIR)/pam_unix_sess.Plo \
+ ./$(DEPDIR)/passverify.Plo ./$(DEPDIR)/support.Plo \
+ ./$(DEPDIR)/unix_chkpwd-bigcrypt.Po \
+ ./$(DEPDIR)/unix_chkpwd-md5_broken.Po \
+ ./$(DEPDIR)/unix_chkpwd-md5_good.Po \
+ ./$(DEPDIR)/unix_chkpwd-passverify.Po \
+ ./$(DEPDIR)/unix_chkpwd-unix_chkpwd.Po \
+ ./$(DEPDIR)/unix_update-bigcrypt.Po \
+ ./$(DEPDIR)/unix_update-md5_broken.Po \
+ ./$(DEPDIR)/unix_update-md5_good.Po \
+ ./$(DEPDIR)/unix_update-passverify.Po \
+ ./$(DEPDIR)/unix_update-unix_update.Po \
+ ./$(DEPDIR)/yppasswd_xdr.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -227,8 +253,9 @@ am__can_run_installinfo = \
esac
man8dir = $(mandir)/man8
NROFF = nroff
-MANS = $(man_MANS)
-DATA = $(noinst_DATA)
+MANS = $(dist_man_MANS)
+am__dist_noinst_DATA_DIST = README
+DATA = $(dist_noinst_DATA)
HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
@@ -426,6 +453,9 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log)
TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
$(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/depcomp \
+ $(top_srcdir)/build-aux/test-driver
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -454,6 +484,8 @@ DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
+ECONF_CFLAGS = @ECONF_CFLAGS@
+ECONF_LIBS = @ECONF_LIBS@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
@@ -462,7 +494,6 @@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
-HAVE_KEY_MANAGEMENT = @HAVE_KEY_MANAGEMENT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -498,6 +529,7 @@ LN_S = @LN_S@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
@@ -534,11 +566,13 @@ SECUREDIR = @SECUREDIR@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
+STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@
STRIP = @STRIP@
TIRPC_CFLAGS = @TIRPC_CFLAGS@
TIRPC_LIBS = @TIRPC_LIBS@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
@@ -607,21 +641,20 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
CLEANFILES = *~
MAINTAINERCLEANFILES = $(MANS) README
-EXTRA_DIST = README md5.c md5_crypt.c lckpwdf.-c $(MANS) CHANGELOG \
- tst-pam_unix $(XMLS)
-
-man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8
+EXTRA_DIST = md5.c md5_crypt.c lckpwdf.-c $(XMLS) CHANGELOG
+@HAVE_DOC_TRUE@dist_man_MANS = pam_unix.8 unix_chkpwd.8 unix_update.8
XMLS = README.xml pam_unix.8.xml unix_chkpwd.8.xml unix_update.8.xml
-TESTS = tst-pam_unix
+dist_check_SCRIPTS = tst-pam_unix
+TESTS = $(dist_check_SCRIPTS)
securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
-AM_CFLAGS = -I$(top_srcdir)/libpam/include \
- -I$(top_srcdir)/libpamc/include \
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
- -DUPDATE_HELPER=\"$(sbindir)/unix_update\" @TIRPC_CFLAGS@ \
- @NSL_CFLAGS@ $(am__append_1)
+ -DUPDATE_HELPER=\"$(sbindir)/unix_update\" \
+ @TIRPC_CFLAGS@ @NSL_CFLAGS@ $(WARN_CFLAGS)
+
pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module \
- $(am__append_2)
+ $(am__append_1)
pam_unix_la_LIBADD = $(top_builddir)/libpam/libpam.la \
@LIBCRYPT@ @LIBSELINUX@ @TIRPC_LIBS@ @NSL_LIBS@
@@ -646,7 +679,7 @@ unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \
unix_update_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_update\"
unix_update_LDFLAGS = @PIE_LDFLAGS@
unix_update_LDADD = @LIBCRYPT@ @LIBSELINUX@
-@ENABLE_REGENERATE_MAN_TRUE@noinst_DATA = README
+@ENABLE_REGENERATE_MAN_TRUE@dist_noinst_DATA = README
all: all-am
.SUFFIXES:
@@ -663,14 +696,13 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/pam_unix/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu modules/pam_unix/Makefile
-.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@@ -682,44 +714,6 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
-install-securelibLTLIBRARIES: $(securelib_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- @list='$(securelib_LTLIBRARIES)'; test -n "$(securelibdir)" || list=; \
- list2=; for p in $$list; do \
- if test -f $$p; then \
- list2="$$list2 $$p"; \
- else :; fi; \
- done; \
- test -z "$$list2" || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(securelibdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(securelibdir)" || exit 1; \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(securelibdir)'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(securelibdir)"; \
- }
-
-uninstall-securelibLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(securelib_LTLIBRARIES)'; test -n "$(securelibdir)" || list=; \
- for p in $$list; do \
- $(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(securelibdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(securelibdir)/$$f"; \
- done
-
-clean-securelibLTLIBRARIES:
- -test -z "$(securelib_LTLIBRARIES)" || rm -f $(securelib_LTLIBRARIES)
- @list='$(securelib_LTLIBRARIES)'; \
- locs=`for p in $$list; do echo $$p; done | \
- sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
- sort -u`; \
- test -z "$$locs" || { \
- echo rm -f $${locs}; \
- rm -f $${locs}; \
- }
-
-pam_unix.la: $(pam_unix_la_OBJECTS) $(pam_unix_la_DEPENDENCIES) $(EXTRA_pam_unix_la_DEPENDENCIES)
- $(AM_V_CCLD)$(pam_unix_la_LINK) -rpath $(securelibdir) $(pam_unix_la_OBJECTS) $(pam_unix_la_LIBADD) $(LIBS)
-
clean-noinstPROGRAMS:
@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
@@ -778,6 +772,44 @@ clean-sbinPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
+install-securelibLTLIBRARIES: $(securelib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(securelib_LTLIBRARIES)'; test -n "$(securelibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(securelibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(securelibdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(securelibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(securelibdir)"; \
+ }
+
+uninstall-securelibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(securelib_LTLIBRARIES)'; test -n "$(securelibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(securelibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(securelibdir)/$$f"; \
+ done
+
+clean-securelibLTLIBRARIES:
+ -test -z "$(securelib_LTLIBRARIES)" || rm -f $(securelib_LTLIBRARIES)
+ @list='$(securelib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+pam_unix.la: $(pam_unix_la_OBJECTS) $(pam_unix_la_DEPENDENCIES) $(EXTRA_pam_unix_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(pam_unix_la_LINK) -rpath $(securelibdir) $(pam_unix_la_OBJECTS) $(pam_unix_la_LIBADD) $(LIBS)
+
bigcrypt$(EXEEXT): $(bigcrypt_OBJECTS) $(bigcrypt_DEPENDENCIES) $(EXTRA_bigcrypt_DEPENDENCIES)
@rm -f bigcrypt$(EXEEXT)
$(AM_V_CCLD)$(bigcrypt_LINK) $(bigcrypt_OBJECTS) $(bigcrypt_LDADD) $(LIBS)
@@ -796,42 +828,48 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigcrypt-bigcrypt.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigcrypt-bigcrypt_main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigcrypt.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5_broken.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5_good.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_acct.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_auth.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_passwd.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_sess.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/passverify.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-bigcrypt.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-md5_broken.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-md5_good.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-passverify.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-unix_chkpwd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-bigcrypt.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-md5_broken.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-md5_good.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-passverify.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-unix_update.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yppasswd_xdr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigcrypt-bigcrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigcrypt-bigcrypt_main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigcrypt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5_broken.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5_good.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_acct.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_auth.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_passwd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_unix_sess.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/passverify.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-bigcrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-md5_broken.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-md5_good.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-passverify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_chkpwd-unix_chkpwd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-bigcrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-md5_broken.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-md5_good.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-passverify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_update-unix_update.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yppasswd_xdr.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -1013,10 +1051,10 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-install-man8: $(man_MANS)
+install-man8: $(dist_man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
- list2='$(man_MANS)'; \
+ list2='$(dist_man_MANS)'; \
test -n "$(man8dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
@@ -1051,7 +1089,7 @@ uninstall-man8:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man8dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.8[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
@@ -1139,7 +1177,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS)
if test -n "$$am__remaking_logs"; then \
echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
"recursion detected" >&2; \
- else \
+ elif test -n "$$redo_logs"; then \
am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
fi; \
if $(am__make_dryrun); then :; else \
@@ -1229,7 +1267,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS)
fi; \
$$success || exit 1
-check-TESTS:
+check-TESTS: $(dist_check_SCRIPTS)
@list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
@list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
@@ -1239,7 +1277,7 @@ check-TESTS:
log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
exit $$?;
-recheck: all
+recheck: all $(dist_check_SCRIPTS)
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
@set +e; $(am__set_TESTS_bases); \
bases=`for i in $$bases; do echo $$i; done \
@@ -1272,7 +1310,10 @@ tst-pam_unix.log: tst-pam_unix
@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
-distdir: $(DISTFILES)
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -1303,11 +1344,12 @@ distdir: $(DISTFILES)
fi; \
done
check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(dist_check_SCRIPTS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
check: check-am
-all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(DATA) $(HEADERS)
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS)
installdirs:
- for dir in "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(man8dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -1351,7 +1393,28 @@ clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
clean-sbinPROGRAMS clean-securelibLTLIBRARIES mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR)
+ -rm -f ./$(DEPDIR)/bigcrypt-bigcrypt.Po
+ -rm -f ./$(DEPDIR)/bigcrypt-bigcrypt_main.Po
+ -rm -f ./$(DEPDIR)/bigcrypt.Plo
+ -rm -f ./$(DEPDIR)/md5_broken.Plo
+ -rm -f ./$(DEPDIR)/md5_good.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_acct.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_auth.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_passwd.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_sess.Plo
+ -rm -f ./$(DEPDIR)/passverify.Plo
+ -rm -f ./$(DEPDIR)/support.Plo
+ -rm -f ./$(DEPDIR)/unix_chkpwd-bigcrypt.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-md5_broken.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-md5_good.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-passverify.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-unix_chkpwd.Po
+ -rm -f ./$(DEPDIR)/unix_update-bigcrypt.Po
+ -rm -f ./$(DEPDIR)/unix_update-md5_broken.Po
+ -rm -f ./$(DEPDIR)/unix_update-md5_good.Po
+ -rm -f ./$(DEPDIR)/unix_update-passverify.Po
+ -rm -f ./$(DEPDIR)/unix_update-unix_update.Po
+ -rm -f ./$(DEPDIR)/yppasswd_xdr.Plo
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1397,7 +1460,28 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
+ -rm -f ./$(DEPDIR)/bigcrypt-bigcrypt.Po
+ -rm -f ./$(DEPDIR)/bigcrypt-bigcrypt_main.Po
+ -rm -f ./$(DEPDIR)/bigcrypt.Plo
+ -rm -f ./$(DEPDIR)/md5_broken.Plo
+ -rm -f ./$(DEPDIR)/md5_good.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_acct.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_auth.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_passwd.Plo
+ -rm -f ./$(DEPDIR)/pam_unix_sess.Plo
+ -rm -f ./$(DEPDIR)/passverify.Plo
+ -rm -f ./$(DEPDIR)/support.Plo
+ -rm -f ./$(DEPDIR)/unix_chkpwd-bigcrypt.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-md5_broken.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-md5_good.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-passverify.Po
+ -rm -f ./$(DEPDIR)/unix_chkpwd-unix_chkpwd.Po
+ -rm -f ./$(DEPDIR)/unix_update-bigcrypt.Po
+ -rm -f ./$(DEPDIR)/unix_update-md5_broken.Po
+ -rm -f ./$(DEPDIR)/unix_update-md5_good.Po
+ -rm -f ./$(DEPDIR)/unix_update-passverify.Po
+ -rm -f ./$(DEPDIR)/unix_update-unix_update.Po
+ -rm -f ./$(DEPDIR)/yppasswd_xdr.Plo
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -1421,10 +1505,11 @@ uninstall-man: uninstall-man8
.MAKE: check-am install-am install-strip
-.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
- clean-generic clean-libtool clean-noinstPROGRAMS \
- clean-sbinPROGRAMS clean-securelibLTLIBRARIES cscopelist-am \
- ctags ctags-am distclean distclean-compile distclean-generic \
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am clean clean-generic clean-libtool \
+ clean-noinstPROGRAMS clean-sbinPROGRAMS \
+ clean-securelibLTLIBRARIES cscopelist-am ctags ctags-am \
+ distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
@@ -1439,7 +1524,8 @@ uninstall-man: uninstall-man8
uninstall-man8 uninstall-sbinPROGRAMS \
uninstall-securelibLTLIBRARIES
-@ENABLE_REGENERATE_MAN_TRUE@README: pam_unix.8.xml
+.PRECIOUS: Makefile
+
@ENABLE_REGENERATE_MAN_TRUE@-include $(top_srcdir)/Make.xml.rules
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/modules/pam_unix/README b/modules/pam_unix/README
index 651ed9c8..a87f34a5 100644
--- a/modules/pam_unix/README
+++ b/modules/pam_unix/README
@@ -69,6 +69,12 @@ nullok
service if their official password is blank. The nullok argument overrides
this default.
+nullresetok
+
+ Allow users to authenticate with blank password if password reset is
+ enforced even if nullok is not set. If password reset is not required and
+ nullok is not set the authentication with blank password will be denied.
+
try_first_pass
Before prompting the user for their password, the module first tries the
@@ -128,25 +134,35 @@ bigcrypt
sha256
When a user changes their password next, encrypt it with the SHA256
- algorithm. If the SHA256 algorithm is not known to the crypt(3) function,
- fall back to MD5.
+ algorithm. The SHA256 algorithm must be supported by the crypt(3) function.
sha512
When a user changes their password next, encrypt it with the SHA512
- algorithm. If the SHA512 algorithm is not known to the crypt(3) function,
- fall back to MD5.
+ algorithm. The SHA512 algorithm must be supported by the crypt(3) function.
blowfish
When a user changes their password next, encrypt it with the blowfish
- algorithm. If the blowfish algorithm is not known to the crypt(3) function,
- fall back to MD5.
+ algorithm. The blowfish algorithm must be supported by the crypt(3)
+ function.
+
+gost_yescrypt
+
+ When a user changes their password next, encrypt it with the gost-yescrypt
+ algorithm. The gost-yescrypt algorithm must be supported by the crypt(3)
+ function.
+
+yescrypt
+
+ When a user changes their password next, encrypt it with the yescrypt
+ algorithm. The yescrypt algorithm must be supported by the crypt(3)
+ function.
rounds=n
- Set the optional number of rounds of the SHA256, SHA512 and blowfish
- password hashing algorithms to n.
+ Set the optional number of rounds of the SHA256, SHA512, blowfish,
+ gost-yescrypt, and yescrypt password hashing algorithms to n.
broken_shadow
@@ -180,7 +196,7 @@ account required pam_unix.so
# Change the user's password, but at first check the strength
# with pam_cracklib(8)
password required pam_cracklib.so retry=3 minlen=6 difok=3
-password required pam_unix.so use_authtok nullok md5
+password required pam_unix.so use_authtok nullok yescrypt
session required pam_unix.so
diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c
index e1d57a07..e08e4098 100644
--- a/modules/pam_unix/bigcrypt.c
+++ b/modules/pam_unix/bigcrypt.c
@@ -13,7 +13,7 @@
* Description: The cleartext is divided into blocks of SEGMENT_SIZE=8
* characters or less. Each block is encrypted using the standard UNIX
* libc crypt function. The result of the encryption for one block
- * provides the salt for the suceeding block.
+ * provides the salt for the succeeding block.
*
* Restrictions: The buffer used to hold the encrypted result is
* statically allocated. (see MAX_PASS_LEN below). This is necessary,
diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c
index 94f0485b..9954536f 100644
--- a/modules/pam_unix/md5.c
+++ b/modules/pam_unix/md5.c
@@ -24,13 +24,16 @@
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
#else
-static void byteReverse(unsigned char *buf, unsigned longs);
+
+typedef unsigned char PAM_ATTRIBUTE_ALIGNED(4) uint8_aligned;
+
+static void byteReverse(uint8_aligned *buf, unsigned longs);
#ifndef ASM_MD5
/*
* Note: this code is harmless on little-endian machines.
*/
-static void byteReverse(unsigned char *buf, unsigned longs)
+static void byteReverse(uint8_aligned *buf, unsigned longs)
{
uint32 t;
do {
diff --git a/modules/pam_unix/md5.h b/modules/pam_unix/md5.h
index 103f168a..d9186b7f 100644
--- a/modules/pam_unix/md5.h
+++ b/modules/pam_unix/md5.h
@@ -2,12 +2,14 @@
#ifndef MD5_H
#define MD5_H
+#include "pam_cc_compat.h"
+
typedef unsigned int uint32;
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
- unsigned char in[64];
+ unsigned char in[64] PAM_ATTRIBUTE_ALIGNED(4);
};
void GoodMD5Init(struct MD5Context *);
diff --git a/modules/pam_unix/md5_crypt.c b/modules/pam_unix/md5_crypt.c
index 4ab9ec84..94f7b434 100644
--- a/modules/pam_unix/md5_crypt.c
+++ b/modules/pam_unix/md5_crypt.c
@@ -15,6 +15,7 @@
#include <string.h>
#include <stdlib.h>
#include "md5.h"
+#include "pam_inline.h"
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@@ -55,8 +56,8 @@ char *MD5Name(crypt_md5)(const char *pw, const char *salt)
return NULL;
/* If it starts with the magic string, then skip that */
- if (!strncmp(sp, magic, strlen(magic)))
- sp += strlen(magic);
+ if ((ep = pam_str_skip_prefix_len(sp, magic, strlen(magic))) != NULL)
+ sp = ep;
/* It stops at the first '$', max 8 chars */
for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
diff --git a/modules/pam_unix/pam_unix.8 b/modules/pam_unix/pam_unix.8
index b3808f1a..b396b66c 100644
--- a/modules/pam_unix/pam_unix.8
+++ b/modules/pam_unix/pam_unix.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: pam_unix
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 05/18/2017
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 06/08/2020
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM Manual
.\" Language: English
.\"
-.TH "PAM_UNIX" "8" "05/18/2017" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "PAM_UNIX" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -95,6 +95,15 @@ The default action of this module is to not permit the user access to a service
argument overrides this default\&.
.RE
.PP
+\fBnullresetok\fR
+.RS 4
+Allow users to authenticate with blank password if password reset is enforced even if
+\fBnullok\fR
+is not set\&. If password reset is not required and
+\fBnullok\fR
+is not set the authentication with blank password will be denied\&.
+.RE
+.PP
\fBtry_first_pass\fR
.RS 4
Before prompting the user for their password, the module first tries the previous stacked module\*(Aqs password in case that satisfies this module as well\&.
@@ -159,28 +168,42 @@ When a user changes their password next, encrypt it with the DEC C2 algorithm\&.
.PP
\fBsha256\fR
.RS 4
-When a user changes their password next, encrypt it with the SHA256 algorithm\&. If the SHA256 algorithm is not known to the
+When a user changes their password next, encrypt it with the SHA256 algorithm\&. The SHA256 algorithm must be supported by the
\fBcrypt\fR(3)
-function, fall back to MD5\&.
+function\&.
.RE
.PP
\fBsha512\fR
.RS 4
-When a user changes their password next, encrypt it with the SHA512 algorithm\&. If the SHA512 algorithm is not known to the
+When a user changes their password next, encrypt it with the SHA512 algorithm\&. The SHA512 algorithm must be supported by the
\fBcrypt\fR(3)
-function, fall back to MD5\&.
+function\&.
.RE
.PP
\fBblowfish\fR
.RS 4
-When a user changes their password next, encrypt it with the blowfish algorithm\&. If the blowfish algorithm is not known to the
+When a user changes their password next, encrypt it with the blowfish algorithm\&. The blowfish algorithm must be supported by the
+\fBcrypt\fR(3)
+function\&.
+.RE
+.PP
+\fBgost_yescrypt\fR
+.RS 4
+When a user changes their password next, encrypt it with the gost\-yescrypt algorithm\&. The gost\-yescrypt algorithm must be supported by the
+\fBcrypt\fR(3)
+function\&.
+.RE
+.PP
+\fByescrypt\fR
+.RS 4
+When a user changes their password next, encrypt it with the yescrypt algorithm\&. The yescrypt algorithm must be supported by the
\fBcrypt\fR(3)
-function, fall back to MD5\&.
+function\&.
.RE
.PP
\fBrounds=\fR\fB\fIn\fR\fR
.RS 4
-Set the optional number of rounds of the SHA256, SHA512 and blowfish password hashing algorithms to
+Set the optional number of rounds of the SHA256, SHA512, blowfish, gost\-yescrypt, and yescrypt password hashing algorithms to
\fIn\fR\&.
.RE
.PP
@@ -243,7 +266,7 @@ account required pam_unix\&.so
# Change the user\*(Aqs password, but at first check the strength
# with pam_cracklib(8)
password required pam_cracklib\&.so retry=3 minlen=6 difok=3
-password required pam_unix\&.so use_authtok nullok md5
+password required pam_unix\&.so use_authtok nullok yescrypt
session required pam_unix\&.so
.fi
diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml
index 1b318f11..fa02c3a6 100644
--- a/modules/pam_unix/pam_unix.8.xml
+++ b/modules/pam_unix/pam_unix.8.xml
@@ -165,6 +165,19 @@
</varlistentry>
<varlistentry>
<term>
+ <option>nullresetok</option>
+ </term>
+ <listitem>
+ <para>
+ Allow users to authenticate with blank password if password reset
+ is enforced even if <option>nullok</option> is not set. If password
+ reset is not required and <option>nullok</option> is not set the
+ authentication with blank password will be denied.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
<option>try_first_pass</option>
</term>
<listitem>
@@ -293,11 +306,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>
@@ -308,11 +320,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>
@@ -323,11 +334,38 @@
<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.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>gost_yescrypt</option>
+ </term>
+ <listitem>
+ <para>
+ When a user changes their password next,
+ encrypt it with the gost-yescrypt algorithm. The
+ gost-yescrypt algorithm must be supported by the <citerefentry>
+ <refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry> function.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <option>yescrypt</option>
+ </term>
+ <listitem>
+ <para>
+ When a user changes their password next,
+ encrypt it with the yescrypt algorithm. The
+ yescrypt algorithm must be supported by the <citerefentry>
<refentrytitle>crypt</refentrytitle><manvolnum>3</manvolnum>
- </citerefentry> function,
- fall back to MD5.
+ </citerefentry> function.
</para>
</listitem>
</varlistentry>
@@ -337,8 +375,9 @@
</term>
<listitem>
<para>
- Set the optional number of rounds of the SHA256, SHA512
- and blowfish password hashing algorithms to
+ Set the optional number of rounds of the SHA256, SHA512,
+ blowfish, gost-yescrypt, and yescrypt password hashing
+ algorithms to
<replaceable>n</replaceable>.
</para>
</listitem>
@@ -428,7 +467,7 @@ account required pam_unix.so
# Change the user's password, but at first check the strength
# with pam_cracklib(8)
password required pam_cracklib.so retry=3 minlen=6 difok=3
-password required pam_unix.so use_authtok nullok md5
+password required pam_unix.so use_authtok nullok yescrypt
session required pam_unix.so
</programlisting>
</para>
diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
index 88331149..de8d65c1 100644
--- a/modules/pam_unix/pam_unix_acct.c
+++ b/modules/pam_unix/pam_unix_acct.c
@@ -1,6 +1,8 @@
/*
+ * pam_unix account management
+ *
* Copyright Elliot Lee, 1996. All rights reserved.
- * Copyright Jan Rêkorajski, 1999. All rights reserved.
+ * Copyright Jan Rękorajski, 1999. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,18 +53,15 @@
#include <security/_pam_macros.h>
-/* indicate that the following groups are defined */
-
-#define PAM_SM_ACCOUNT
-
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <security/pam_modutil.h>
+#include "pam_cc_compat.h"
#include "support.h"
#include "passverify.h"
-int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
+int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl,
const char *user, int *daysleft)
{
int retval=0, child, fds[2];
@@ -127,7 +126,9 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
args[1] = user;
args[2] = "chkexpiry";
+ DIAG_PUSH_IGNORE_CAST_QUAL;
execve(CHKPWD_HELPER, (char *const *) args, envp);
+ DIAG_POP_IGNORE_CAST_QUAL;
pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m");
/* should not get here: exit with error */
@@ -185,12 +186,10 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- unsigned int ctrl;
+ unsigned long long ctrl;
const void *void_uname;
const char *uname;
int retval, daysleft;
- struct spwd *spent;
- struct passwd *pwent;
char buf[256];
D(("called."));
@@ -207,29 +206,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_USER_UNKNOWN;
}
- retval = get_account_info(pamh, uname, &pwent, &spent);
- if (retval == PAM_USER_UNKNOWN) {
- pam_syslog(pamh, LOG_ERR,
- "could not identify user (from getpwnam(%s))",
- uname);
- return retval;
- }
-
- if (retval == PAM_SUCCESS && spent == NULL)
- return PAM_SUCCESS;
-
- if (retval == PAM_UNIX_RUN_HELPER) {
- retval = _unix_run_verify_binary(pamh, ctrl, uname, &daysleft);
- if (retval == PAM_AUTHINFO_UNAVAIL &&
- on(UNIX_BROKEN_SHADOW, ctrl))
- return PAM_SUCCESS;
- } else if (retval != PAM_SUCCESS) {
- if (on(UNIX_BROKEN_SHADOW,ctrl))
- return PAM_SUCCESS;
- else
- return retval;
- } else
- retval = check_shadow_expiry(pamh, spent, &daysleft);
+ retval = _unix_verify_user(pamh, ctrl, uname, &daysleft);
if (on(UNIX_NO_PASS_EXPIRY, ctrl)) {
const void *pretval = NULL;
@@ -250,7 +227,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
"account %s has expired (account expired)",
uname);
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- _("Your account has expired; please contact your system administrator"));
+ _("Your account has expired; please contact your system administrator."));
break;
case PAM_NEW_AUTHTOK_REQD:
if (daysleft == 0) {
@@ -258,13 +235,13 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
"expired password for user %s (root enforced)",
uname);
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- _("You are required to change your password immediately (administrator enforced)"));
+ _("You are required to change your password immediately (administrator enforced)."));
} else {
pam_syslog(pamh, LOG_DEBUG,
"expired password for user %s (password aged)",
uname);
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- _("You are required to change your password immediately (password expired)"));
+ _("You are required to change your password immediately (password expired)."));
}
break;
case PAM_AUTHTOK_EXPIRED:
@@ -272,7 +249,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
"account %s has expired (failed to change password)",
uname);
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- _("Your account has expired; please contact your system administrator"));
+ _("Your account has expired; please contact your system administrator."));
break;
case PAM_AUTHTOK_ERR:
retval = PAM_SUCCESS;
@@ -285,19 +262,19 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
#if defined HAVE_DNGETTEXT && defined ENABLE_NLS
snprintf (buf, sizeof (buf),
dngettext(PACKAGE,
- "Warning: your password will expire in %d day",
- "Warning: your password will expire in %d days",
+ "Warning: your password will expire in %d day.",
+ "Warning: your password will expire in %d days.",
daysleft),
daysleft);
#else
if (daysleft == 1)
snprintf(buf, sizeof (buf),
- _("Warning: your password will expire in %d day"),
+ _("Warning: your password will expire in %d day."),
daysleft);
else
snprintf(buf, sizeof (buf),
/* TRANSLATORS: only used if dngettext is not supported */
- _("Warning: your password will expire in %d days"),
+ _("Warning: your password will expire in %d days."),
daysleft);
#endif
_make_remark(pamh, ctrl, PAM_TEXT_INFO, buf);
diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c
index fce6bce1..4eccff8e 100644
--- a/modules/pam_unix/pam_unix_auth.c
+++ b/modules/pam_unix/pam_unix_auth.c
@@ -1,7 +1,9 @@
/*
+ * pam_unix authentication management
+ *
* Copyright Alexander O. Yuriev, 1996. All rights reserved.
* NIS+ support by Thorsten Kukuk <kukuk@weber.uni-paderborn.de>
- * Copyright Jan Rêkorajski, 1999. All rights reserved.
+ * Copyright Jan Rękorajski, 1999. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -48,11 +50,6 @@
#include <sys/stat.h>
#include <syslog.h>
-/* indicate the following groups are defined */
-
-#define PAM_SM_AUTH
-
-#define _PAM_EXTERN_FUNCTIONS
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
@@ -74,8 +71,6 @@
* onto a normal UNIX authentication
*/
-#define _UNIX_AUTHTOK "-UN*X-PASS"
-
#define AUTH_RETURN \
do { \
D(("recording return code for next time [%d]", \
@@ -98,7 +93,7 @@ setcred_free (pam_handle_t *pamh UNUSED, void *ptr, int err UNUSED)
int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- unsigned int ctrl;
+ unsigned long long ctrl;
int retval, *ret_data = NULL;
const char *name;
const char *p;
@@ -126,21 +121,22 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
* '+' or '-' as the first character of a user name. Don't
* allow this characters here.
*/
- if (name == NULL || name[0] == '-' || name[0] == '+') {
- pam_syslog(pamh, LOG_ERR, "bad username [%s]", name);
+ if (name[0] == '-' || name[0] == '+') {
+ pam_syslog(pamh, LOG_NOTICE, "bad username [%s]", name);
retval = PAM_USER_UNKNOWN;
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;
}
@@ -148,7 +144,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;
@@ -196,7 +192,7 @@ pam_sm_setcred (pam_handle_t *pamh, int flags,
{
int retval;
const void *pretval = NULL;
- unsigned int ctrl;
+ unsigned long long ctrl;
D(("called."));
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index 9fdebefb..e988b2e3 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -1,7 +1,9 @@
/*
+ * pam_unix password management
+ *
* Main coding by Elliot Lee <sopwith@redhat.com>, Red Hat Software.
* Copyright (C) 1996.
- * Copyright (c) Jan Rêkorajski, 1999.
+ * Copyright (c) Jan Rękorajski, 1999.
* Copyright (c) Red Hat, Inc., 2007, 2008.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,20 +58,15 @@
#include <sys/stat.h>
#include <signal.h>
-#include <errno.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <security/_pam_macros.h>
-
-/* indicate the following groups are defined */
-
-#define PAM_SM_PASSWORD
-
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <security/pam_modutil.h>
+#include "pam_cc_compat.h"
#include "md5.h"
#include "support.h"
#include "passverify.h"
@@ -106,11 +103,6 @@ extern int getrpcport(const char *host, unsigned long prognum,
Sets it.
*/
-/* data tokens */
-
-#define _UNIX_OLD_AUTHTOK "-UN*X-OLD-PASS"
-#define _UNIX_NEW_AUTHTOK "-UN*X-NEW-PASS"
-
#define MAX_PASSWD_TRIES 3
#ifdef HAVE_NIS
@@ -143,7 +135,7 @@ __taddr2port (const struct netconfig *nconf, const struct netbuf *nbuf)
}
#endif
-static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl)
+static char *getNISserver(pam_handle_t *pamh, unsigned long long ctrl)
{
char *master;
char *domainname;
@@ -238,7 +230,7 @@ static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl)
#ifdef WITH_SELINUX
-static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user,
+static int _unix_run_update_binary(pam_handle_t *pamh, unsigned long long ctrl, const char *user,
const char *fromwhat, const char *towhat, int remember)
{
int retval, child, fds[2];
@@ -298,7 +290,9 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
snprintf(buffer, sizeof(buffer), "%d", remember);
args[4] = buffer;
+ DIAG_PUSH_IGNORE_CAST_QUAL;
execve(UPDATE_HELPER, (char *const *) args, envp);
+ DIAG_POP_IGNORE_CAST_QUAL;
/* should not get here: exit with error */
D(("helper binary is not available"));
@@ -355,7 +349,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
static int check_old_password(const char *forwho, const char *newpass)
{
static char buf[16384];
- char *s_luser, *s_uid, *s_npas, *s_pas;
+ char *s_pas;
int retval = PAM_SUCCESS;
FILE *opwfile;
size_t len = strlen(forwho);
@@ -369,9 +363,9 @@ static int check_old_password(const char *forwho, const char *newpass)
buf[len] == ',')) {
char *sptr;
buf[strlen(buf) - 1] = '\0';
- s_luser = strtok_r(buf, ":,", &sptr);
- s_uid = strtok_r(NULL, ":,", &sptr);
- s_npas = strtok_r(NULL, ":,", &sptr);
+ /* s_luser = */ strtok_r(buf, ":,", &sptr);
+ /* s_uid = */ strtok_r(NULL, ":,", &sptr);
+ /* s_npas = */ strtok_r(NULL, ":,", &sptr);
s_pas = strtok_r(NULL, ":,", &sptr);
while (s_pas != NULL) {
char *md5pass = Goodcrypt_md5(newpass, s_pas);
@@ -393,12 +387,11 @@ static int check_old_password(const char *forwho, const char *newpass)
static int _do_setpass(pam_handle_t* pamh, const char *forwho,
const char *fromwhat,
- char *towhat, unsigned int ctrl, int remember)
+ char *towhat, unsigned long long ctrl, int remember)
{
struct passwd *pwd = NULL;
int retval = 0;
int unlocked = 0;
- char *master = NULL;
D(("called"));
@@ -411,6 +404,8 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho,
if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) {
#ifdef HAVE_NIS
+ char *master;
+
if ((master=getNISserver(pamh, ctrl)) != NULL) {
struct timeval timeout;
struct yppasswd yppwd;
@@ -517,7 +512,7 @@ done:
return retval;
}
-static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned int ctrl)
+static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned long long ctrl)
{
struct passwd *pwent = NULL; /* Password and shadow password */
struct spwd *spent = NULL; /* file entries for the user */
@@ -547,7 +542,7 @@ static int _unix_verify_shadow(pam_handle_t *pamh, const char *user, unsigned in
}
static int _pam_unix_approve_pass(pam_handle_t * pamh
- ,unsigned int ctrl
+ ,unsigned long long ctrl
,const char *pass_old
,const char *pass_new,
int pass_min_len)
@@ -565,7 +560,8 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
pam_syslog(pamh, LOG_DEBUG, "bad authentication token");
}
_make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ?
- _("No password supplied") : _("Password unchanged"));
+ _("No password has been supplied.") :
+ _("The password has not been changed."));
return PAM_AUTHTOK_ERR;
}
/*
@@ -580,9 +576,13 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
return PAM_AUTHTOK_ERR;
}
}
- if (off(UNIX__IAMROOT, ctrl)) {
- if (strlen(pass_new) < pass_min_len)
- remark = _("You must choose a longer password");
+
+ if (strlen(pass_new) > MAXPASS) {
+ remark = _("You must choose a shorter password.");
+ D(("length exceeded [%s]", remark));
+ } else if (off(UNIX__IAMROOT, ctrl)) {
+ if ((int)strlen(pass_new) < pass_min_len)
+ remark = _("You must choose a longer password.");
D(("length check [%s]", remark));
if (on(UNIX_REMEMBER_PASSWD, ctrl)) {
if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR)
@@ -604,10 +604,10 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
int
pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- unsigned int ctrl, lctrl;
+ unsigned long long ctrl, lctrl;
int retval;
int remember = -1;
- int rounds = -1;
+ int rounds = 0;
int pass_min_len = 0;
/* <DO NOT free() THESE> */
@@ -631,8 +631,8 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
* '+' or '-' as the first character of a user name. Don't
* allow them.
*/
- if (user == NULL || user[0] == '-' || user[0] == '+') {
- pam_syslog(pamh, LOG_ERR, "bad username [%s]", user);
+ if (user[0] == '-' || user[0] == '+') {
+ pam_syslog(pamh, LOG_NOTICE, "bad username [%s]", user);
return PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
@@ -719,7 +719,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
if (retval == PAM_AUTHTOK_ERR) {
if (off(UNIX__IAMROOT, ctrl))
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- _("You must wait longer to change your password"));
+ _("You must wait longer to change your password."));
else
retval = PAM_SUCCESS;
}
diff --git a/modules/pam_unix/pam_unix_sess.c b/modules/pam_unix/pam_unix_sess.c
index 03e7dcd9..3f6a8fb3 100644
--- a/modules/pam_unix/pam_unix_sess.c
+++ b/modules/pam_unix/pam_unix_sess.c
@@ -1,8 +1,8 @@
/*
- * $Id$
+ * pam_unix session management
*
* Copyright Alexander O. Yuriev, 1996. All rights reserved.
- * Copyright Jan Rêkorajski, 1999. All rights reserved.
+ * Copyright Jan Rękorajski, 1999. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -47,10 +47,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-/* indicate the following groups are defined */
-
-#define PAM_SM_SESSION
-
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
@@ -67,9 +63,9 @@ int
pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
char *user_name, *service;
- unsigned int ctrl;
+ unsigned long long ctrl;
int retval;
- const char *login_name;
+ const char *login_name;
D(("called."));
@@ -78,24 +74,31 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR,
- "open_session - error recovering username");
+ "open_session - error recovering username");
return PAM_SESSION_ERR; /* How did we get authenticated with
no username?! */
}
retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service);
if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_CRIT,
- "open_session - error recovering service");
+ "open_session - error recovering service");
return PAM_SESSION_ERR;
}
login_name = pam_modutil_getlogin(pamh);
if (login_name == NULL) {
- login_name = "";
+ login_name = "";
+ }
+ if (off (UNIX_QUIET, ctrl)) {
+ char uid[32];
+ struct passwd *pwd = pam_modutil_getpwnam (pamh, user_name);
+ if (pwd == NULL) {
+ snprintf (uid, 32, "getpwnam error");
+ }
+ else {
+ snprintf (uid, 32, "%u", pwd->pw_uid);
+ }
+ pam_syslog(pamh, LOG_INFO, "session opened for user %s(uid=%s) by %s(uid=%lu)", user_name, uid, login_name, (unsigned long)getuid());
}
- if (off (UNIX_QUIET, ctrl))
- pam_syslog(pamh, LOG_INFO, "session opened for user %s by %s(uid=%lu)",
- user_name, login_name, (unsigned long)getuid());
-
return PAM_SUCCESS;
}
@@ -103,7 +106,7 @@ int
pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
char *user_name, *service;
- unsigned int ctrl;
+ unsigned long long ctrl;
int retval;
D(("called."));
@@ -113,19 +116,19 @@ pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR,
- "close_session - error recovering username");
+ "close_session - error recovering username");
return PAM_SESSION_ERR; /* How did we get authenticated with
no username?! */
}
retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service);
if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_CRIT,
- "close_session - error recovering service");
+ "close_session - error recovering service");
return PAM_SESSION_ERR;
}
if (off (UNIX_QUIET, ctrl))
- pam_syslog(pamh, LOG_INFO, "session closed for user %s",
- user_name);
+ pam_syslog(pamh, LOG_INFO, "session closed for user %s",
+ user_name);
return PAM_SUCCESS;
}
diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c
index 9c1771e2..a571b4f7 100644
--- a/modules/pam_unix/passverify.c
+++ b/modules/pam_unix/passverify.c
@@ -25,6 +25,8 @@
#include <crypt.h>
#endif
+#include "pam_cc_compat.h"
+#include "pam_inline.h"
#include "md5.h"
#include "bigcrypt.h"
#include "passverify.h"
@@ -65,8 +67,8 @@ strip_hpux_aging(char *hash)
}
}
-int
-verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
+PAMH_ARG_DECL(int verify_pwd_hash,
+ const char *p, char *hash, unsigned int nullok)
{
size_t hash_len;
char *pp = NULL;
@@ -87,7 +89,7 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
} else if (!p || *hash == '*' || *hash == '!') {
retval = PAM_AUTH_ERR;
} else {
- if (!strncmp(hash, "$1$", 3)) {
+ if (pam_str_skip_prefix(hash, "$1$") != NULL) {
pp = Goodcrypt_md5(p, hash);
if (pp && strcmp(pp, hash) != 0) {
_pam_delete(pp);
@@ -103,6 +105,44 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
* Ok, we don't know the crypt algorithm, but maybe
* libcrypt knows about it? We should try it.
*/
+#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE
+ /* Get the status of the hash from checksalt */
+ int retval_checksalt = crypt_checksalt(hash);
+
+ /*
+ * Check for hashing methods that are disabled by
+ * libcrypt configuration and/or system preset.
+ */
+ if (retval_checksalt == CRYPT_SALT_METHOD_DISABLED) {
+ /*
+ * pam_syslog() needs a pam handle,
+ * but that's not available here.
+ */
+ pam_syslog(pamh, LOG_ERR,
+ "The support for password hash \"%.6s\" "
+ "has been disabled in libcrypt "
+ "configuration.",
+ hash);
+ }
+ /*
+ * Check for malformed hashes, like descrypt hashes
+ * starting with "$2...", which might have been
+ * generated by unsafe base64 encoding functions
+ * as used in glibc <= 2.16.
+ * Such hashes are likely to be rejected by many
+ * recent implementations of libcrypt.
+ */
+ if (retval_checksalt == CRYPT_SALT_INVALID) {
+ pam_syslog(pamh, LOG_ERR,
+ "The password hash \"%.6s\" is unknown to "
+ "libcrypt.",
+ hash);
+ }
+#else
+#ifndef HELPER_COMPILE
+ (void)pamh;
+#endif
+#endif
#ifdef HAVE_CRYPT_R
struct crypt_data *cdata;
cdata = malloc(sizeof(*cdata));
@@ -166,25 +206,30 @@ PAMH_ARG_DECL(int get_account_info,
save_euid = geteuid();
save_uid = getuid();
- if (save_uid == (*pwd)->pw_uid)
- setreuid(save_euid, save_uid);
- else {
- setreuid(0, -1);
- if (setreuid(-1, (*pwd)->pw_uid) == -1) {
- setreuid(-1, 0);
- setreuid(0, -1);
- if(setreuid(-1, (*pwd)->pw_uid) == -1)
+ if (save_uid == (*pwd)->pw_uid) {
+ if (setreuid(save_euid, save_uid))
+ return PAM_CRED_INSUFFICIENT;
+ } else {
+ if (setreuid(0, -1))
+ return PAM_CRED_INSUFFICIENT;
+ if (setreuid(-1, (*pwd)->pw_uid)) {
+ if (setreuid(-1, 0)
+ || setreuid(0, -1)
+ || setreuid(-1, (*pwd)->pw_uid)) {
return PAM_CRED_INSUFFICIENT;
+ }
}
}
*spwdent = pam_modutil_getspnam(pamh, name);
- if (save_uid == (*pwd)->pw_uid)
- setreuid(save_uid, save_euid);
- else {
- setreuid(-1, 0);
- setreuid(save_uid, -1);
- setreuid(-1, save_euid);
+ if (save_uid == (*pwd)->pw_uid) {
+ if (setreuid(save_uid, save_euid))
+ return PAM_CRED_INSUFFICIENT;
+ } else {
+ if (setreuid(-1, 0)
+ || setreuid(save_uid, -1)
+ || setreuid(-1, save_euid))
+ return PAM_CRED_INSUFFICIENT;
}
if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL)
@@ -244,7 +289,13 @@ PAMH_ARG_DECL(int check_shadow_expiry,
D(("account expired"));
return PAM_ACCT_EXPIRED;
}
+#if defined(CRYPT_CHECKSALT_AVAILABLE) && CRYPT_CHECKSALT_AVAILABLE
+ if (spent->sp_lstchg == 0 ||
+ crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_METHOD_LEGACY ||
+ crypt_checksalt(spent->sp_pwdp) == CRYPT_SALT_TOO_CHEAP) {
+#else
if (spent->sp_lstchg == 0) {
+#endif
D(("need a new password"));
*daysleft = 0;
return PAM_NEW_AUTHTOK_REQD;
@@ -372,10 +423,15 @@ crypt_md5_wrapper(const char *pass_new)
}
PAMH_ARG_DECL(char * create_password_hash,
- const char *password, unsigned int ctrl, int rounds)
+ const char *password, unsigned long long ctrl, int rounds)
{
const char *algoid;
+#if defined(CRYPT_GENSALT_OUTPUT_SIZE) && CRYPT_GENSALT_OUTPUT_SIZE > 64
+ /* Strings returned by crypt_gensalt_rn will be no longer than this. */
+ char salt[CRYPT_GENSALT_OUTPUT_SIZE];
+#else
char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
+#endif
char *sp;
#ifdef HAVE_CRYPT_R
struct crypt_data *cdata = NULL;
@@ -384,8 +440,12 @@ PAMH_ARG_DECL(char * create_password_hash,
if (on(UNIX_MD5_PASS, ctrl)) {
/* algoid = "$1" */
return crypt_md5_wrapper(password);
+ } else if (on(UNIX_YESCRYPT_PASS, ctrl)) {
+ algoid = "$y$";
+ } else if (on(UNIX_GOST_YESCRYPT_PASS, ctrl)) {
+ algoid = "$gy$";
} 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)) {
@@ -406,6 +466,13 @@ PAMH_ARG_DECL(char * create_password_hash,
return crypted;
}
+#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
#ifdef HAVE_CRYPT_GENSALT_R
if (on(UNIX_BLOWFISH_PASS, ctrl)) {
char entropy[17];
@@ -423,6 +490,7 @@ PAMH_ARG_DECL(char * create_password_hash,
#ifdef HAVE_CRYPT_GENSALT_R
}
#endif
+#endif /* CRYPT_GENSALT_IMPLEMENTS_AUTO_ENTROPY */
#ifdef HAVE_CRYPT_R
sp = NULL;
cdata = malloc(sizeof(*cdata));
@@ -434,10 +502,11 @@ PAMH_ARG_DECL(char * create_password_hash,
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_YESCRYPT_PASS, ctrl) ? "yescrypt" :
+ on(UNIX_GOST_YESCRYPT_PASS, ctrl) ? "gost_yescrypt" :
on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
@@ -447,7 +516,7 @@ PAMH_ARG_DECL(char * create_password_hash,
#ifdef HAVE_CRYPT_R
free(cdata);
#endif
- return crypt_md5_wrapper(password);
+ return NULL;
}
sp = x_strdup(sp);
#ifdef HAVE_CRYPT_R
@@ -958,7 +1027,9 @@ PAMH_ARG_DECL(int unix_update_shadow,
fclose(opwfile);
if (!wroteentry && !err) {
+ DIAG_PUSH_IGNORE_CAST_QUAL;
spwdent.sp_namp = (char *)forwho;
+ DIAG_POP_IGNORE_CAST_QUAL;
spwdent.sp_pwdp = towhat;
spwdent.sp_lstchg = time(NULL) / (60 * 60 * 24);
if (spwdent.sp_lstchg == 0)
@@ -1017,21 +1088,21 @@ int
helper_verify_password(const char *name, const char *p, int nullok)
{
struct passwd *pwd = NULL;
- char *salt = NULL;
+ char *hash = NULL;
int retval;
- retval = get_pwd_hash(name, &pwd, &salt);
+ retval = get_pwd_hash(name, &pwd, &hash);
- if (pwd == NULL || salt == NULL) {
+ if (pwd == NULL || hash == NULL) {
helper_log_err(LOG_NOTICE, "check pass; user unknown");
retval = PAM_USER_UNKNOWN;
} else {
- retval = verify_pwd_hash(p, salt, nullok);
+ retval = verify_pwd_hash(p, hash, nullok);
}
- if (salt) {
- _pam_overwrite(salt);
- _pam_drop(salt);
+ if (hash) {
+ _pam_overwrite(hash);
+ _pam_drop(hash);
}
p = NULL; /* no longer needed here */
@@ -1154,7 +1225,7 @@ read_passwords(int fd, int npass, char **passwords)
#endif
/* ****************************************************************** *
- * Copyright (c) Jan Rêkorajski 1999.
+ * Copyright (c) Jan Rękorajski 1999.
* Copyright (c) Andrew G. Morgan 1996-8.
* Copyright (c) Alex O. Yuriev, 1996.
* Copyright (c) Cristian Gafton 1996.
diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h
index caf7ae8a..e9a88fbf 100644
--- a/modules/pam_unix/passverify.h
+++ b/modules/pam_unix/passverify.h
@@ -13,9 +13,6 @@
#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
int
-verify_pwd_hash(const char *p, char *hash, unsigned int nullok);
-
-int
is_pwd_shadowed(const struct passwd *pwd);
char *
@@ -65,8 +62,11 @@ read_passwords(int fd, int npass, char **passwords);
#define PAMH_ARG(...) pamh, __VA_ARGS__
#endif
+PAMH_ARG_DECL(int verify_pwd_hash,
+ const char *p, char *hash, unsigned int nullok);
+
PAMH_ARG_DECL(char * create_password_hash,
- const char *password, unsigned int ctrl, int rounds);
+ const char *password, unsigned long long ctrl, int rounds);
PAMH_ARG_DECL(int get_account_info,
const char *name, struct passwd **pwd, struct spwd **spwdent);
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index f2e28d35..41db1f04 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -28,86 +28,14 @@
#include <security/pam_ext.h>
#include <security/pam_modutil.h>
+#include "pam_cc_compat.h"
+#include "pam_inline.h"
#include "support.h"
#include "passverify.h"
-static char *
-search_key (const char *key, const char *filename)
-{
- FILE *fp;
- char *buf = NULL;
- size_t buflen = 0;
- char *retval = NULL;
-
- fp = fopen (filename, "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;
-
- 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;
-
- if (cp[strlen (cp) - 1] == '\n')
- cp[strlen (cp) - 1] = '\0';
-
- tmp = strsep (&cp, " \t=");
- if (cp != NULL)
- while (isspace ((int)*cp) || *cp == '=')
- ++cp;
-
- if (strcasecmp (tmp, key) == 0)
- {
- retval = strdup (cp);
- break;
- }
- }
- fclose (fp);
-
- free (buf);
-
- return retval;
-}
-
-
/* this is a front-end for module-application conversations */
-int _make_remark(pam_handle_t * pamh, unsigned int ctrl,
+int _make_remark(pam_handle_t * pamh, unsigned long long ctrl,
int type, const char *text)
{
int retval = PAM_SUCCESS;
@@ -122,10 +50,11 @@ int _make_remark(pam_handle_t * pamh, unsigned int ctrl,
* set the control flags for the UNIX module.
*/
-int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
- int *pass_min_len, int argc, const char **argv)
+unsigned long long _set_ctrl(pam_handle_t *pamh, int flags, int *remember,
+ int *rounds, int *pass_min_len, int argc,
+ const char **argv)
{
- unsigned int ctrl;
+ unsigned long long ctrl;
char *val;
int j;
@@ -153,7 +82,7 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
}
/* preset encryption method with value from /etc/login.defs */
- val = search_key ("ENCRYPT_METHOD", LOGIN_DEFS);
+ val = pam_modutil_search_key(pamh, LOGIN_DEFS, "ENCRYPT_METHOD");
if (val) {
for (j = 0; j < UNIX_CTRLS_; ++j) {
if (unix_args[j].token && unix_args[j].is_hash_algo
@@ -171,10 +100,11 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
/* read number of rounds for crypt algo */
if (rounds && (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl))) {
- val=search_key ("SHA_CRYPT_MAX_ROUNDS", LOGIN_DEFS);
+ val = pam_modutil_search_key(pamh, LOGIN_DEFS, "SHA_CRYPT_MAX_ROUNDS");
if (val) {
*rounds = strtol(val, NULL, 10);
+ set(UNIX_ALGO_ROUNDS, ctrl);
free (val);
}
}
@@ -183,17 +113,20 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
/* now parse the arguments to this module */
for (; argc-- > 0; ++argv) {
+ const char *str = NULL;
D(("pam_unix arg: %s", *argv));
for (j = 0; j < UNIX_CTRLS_; ++j) {
if (unix_args[j].token
- && !strncmp(*argv, unix_args[j].token, strlen(unix_args[j].token))) {
+ && (str = pam_str_skip_prefix_len(*argv,
+ unix_args[j].token,
+ strlen(unix_args[j].token))) != NULL) {
break;
}
}
- if (j >= UNIX_CTRLS_) {
+ if (str == NULL) {
pam_syslog(pamh, LOG_ERR,
"unrecognized option [%s]", *argv);
} else {
@@ -204,7 +137,7 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
"option remember not allowed for this module type");
continue;
}
- *remember = strtol(*argv + 9, NULL, 10);
+ *remember = strtol(str, NULL, 10);
if ((*remember == INT_MIN) || (*remember == INT_MAX))
*remember = -1;
if (*remember > 400)
@@ -215,14 +148,14 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
"option minlen not allowed for this module type");
continue;
}
- *pass_min_len = atoi(*argv + 7);
+ *pass_min_len = atoi(str);
} else if (j == UNIX_ALGO_ROUNDS) {
if (rounds == NULL) {
pam_syslog(pamh, LOG_ERR,
"option rounds not allowed for this module type");
continue;
}
- *rounds = strtol(*argv + 7, NULL, 10);
+ *rounds = strtol(str, NULL, 10);
}
ctrl &= unix_args[j].mask; /* for turning things off */
@@ -242,23 +175,33 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
set(UNIX__NONULL, ctrl);
}
- /* Set default rounds for blowfish */
- if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) {
- *rounds = 5;
- set(UNIX_ALGO_ROUNDS, ctrl);
+ /* Set default rounds for blowfish, gost-yescrypt and yescrypt */
+ if (off(UNIX_ALGO_ROUNDS, ctrl) && rounds != NULL) {
+ if (on(UNIX_BLOWFISH_PASS, ctrl) ||
+ on(UNIX_GOST_YESCRYPT_PASS, ctrl) ||
+ on(UNIX_YESCRYPT_PASS, ctrl)) {
+ *rounds = 5;
+ set(UNIX_ALGO_ROUNDS, ctrl);
+ }
}
/* Enforce sane "rounds" values */
if (on(UNIX_ALGO_ROUNDS, ctrl)) {
- if (on(UNIX_BLOWFISH_PASS, ctrl)) {
+ if (on(UNIX_GOST_YESCRYPT_PASS, ctrl) ||
+ on(UNIX_YESCRYPT_PASS, ctrl)) {
+ if (*rounds < 3 || *rounds > 11)
+ *rounds = 5;
+ } else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
if (*rounds < 4 || *rounds > 31)
*rounds = 5;
} else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) {
- if ((*rounds < 1000) || (*rounds == INT_MAX))
+ if ((*rounds < 1000) || (*rounds == INT_MAX)) {
/* don't care about bogus values */
+ *rounds = 0;
unset(UNIX_ALGO_ROUNDS, ctrl);
- if (*rounds >= 10000000)
+ } else if (*rounds >= 10000000) {
*rounds = 9999999;
+ }
}
}
@@ -273,11 +216,6 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds,
return ctrl;
}
-static void _cleanup(pam_handle_t * pamh UNUSED, void *x, int error_status UNUSED)
-{
- _pam_delete(x);
-}
-
/* ************************************************************** *
* Useful non-trivial functions *
* ************************************************************** */
@@ -417,7 +355,7 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name,
}
#else
/* we don't have NIS support, make compiler happy. */
- nis = 0;
+ (void) nis;
#endif
if (matched && (ret != NULL)) {
@@ -529,7 +467,7 @@ int _unix_comesfromsource(pam_handle_t *pamh,
#include <sys/wait.h>
static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
- unsigned int ctrl, const char *user)
+ unsigned long long ctrl, const char *user)
{
int retval, child, fds[2];
struct sigaction newsa, oldsa;
@@ -593,7 +531,9 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
args[2]="nonull";
}
+ DIAG_PUSH_IGNORE_CAST_QUAL;
execve(CHKPWD_HELPER, (char *const *) args, envp);
+ DIAG_POP_IGNORE_CAST_QUAL;
/* should not get here: exit with error */
D(("helper binary is not available"));
@@ -655,10 +595,11 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
*/
int
-_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
+_unix_blankpasswd (pam_handle_t *pamh, unsigned long long ctrl, const char *name)
{
struct passwd *pwd = NULL;
char *salt = NULL;
+ int daysleft;
int retval;
D(("called"));
@@ -669,6 +610,15 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
* else (CG)
*/
+ if (on(UNIX_NULLRESETOK, ctrl)) {
+ retval = _unix_verify_user(pamh, ctrl, name, &daysleft);
+ if (retval == PAM_NEW_AUTHTOK_REQD) {
+ /* password reset is enforced, allow authentication with empty password */
+ pam_syslog(pamh, LOG_DEBUG, "user [%s] has expired blank password, enabling nullok", name);
+ set(UNIX__NULLOK, ctrl);
+ }
+ }
+
if (on(UNIX__NONULL, ctrl))
return 0; /* will fail but don't let on yet */
@@ -703,11 +653,12 @@ _unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
}
int _unix_verify_password(pam_handle_t * pamh, const char *name
- ,const char *p, unsigned int ctrl)
+ ,const char *p, unsigned long long ctrl)
{
struct passwd *pwd = NULL;
char *salt = NULL;
char *data_name;
+ char pw[MAXPASS + 1];
int retval;
@@ -734,6 +685,11 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
strcpy(data_name + sizeof(FAIL_PREFIX) - 1, name);
}
+ if (p != NULL && strlen(p) > MAXPASS) {
+ memset(pw, 0, sizeof(pw));
+ p = strncpy(pw, p, sizeof(pw) - 1);
+ }
+
if (retval != PAM_SUCCESS) {
if (retval == PAM_UNIX_RUN_HELPER) {
D(("running helper binary"));
@@ -758,7 +714,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
}
} else {
- retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
+ retval = verify_pwd_hash(pamh, p, salt, off(UNIX__NONULL, ctrl));
}
if (retval == PAM_SUCCESS) {
@@ -843,6 +799,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
cleanup:
+ memset(pw, 0, sizeof(pw)); /* clear memory of the password */
if (data_name)
_pam_delete(data_name);
if (salt)
@@ -853,8 +810,45 @@ cleanup:
return retval;
}
+int
+_unix_verify_user(pam_handle_t *pamh,
+ unsigned long long ctrl,
+ const char *name,
+ int *daysleft)
+{
+ int retval;
+ struct spwd *spent;
+ struct passwd *pwent;
+
+ retval = get_account_info(pamh, name, &pwent, &spent);
+ if (retval == PAM_USER_UNKNOWN) {
+ pam_syslog(pamh, LOG_ERR,
+ "could not identify user (from getpwnam(%s))",
+ name);
+ return retval;
+ }
+
+ if (retval == PAM_SUCCESS && spent == NULL)
+ return PAM_SUCCESS;
+
+ if (retval == PAM_UNIX_RUN_HELPER) {
+ retval = _unix_run_verify_binary(pamh, ctrl, name, daysleft);
+ if (retval == PAM_AUTHINFO_UNAVAIL &&
+ on(UNIX_BROKEN_SHADOW, ctrl))
+ return PAM_SUCCESS;
+ } else if (retval != PAM_SUCCESS) {
+ if (on(UNIX_BROKEN_SHADOW,ctrl))
+ return PAM_SUCCESS;
+ else
+ return retval;
+ } else
+ retval = check_shadow_expiry(pamh, spent, daysleft);
+
+ return retval;
+}
+
/* ****************************************************************** *
- * Copyright (c) Jan Rêkorajski 1999.
+ * Copyright (c) Jan Rękorajski 1999.
* Copyright (c) Andrew G. Morgan 1996-8.
* Copyright (c) Alex O. Yuriev, 1996.
* Copyright (c) Cristian Gafton 1996.
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index b4c279c3..19754dc1 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -22,8 +22,8 @@
typedef struct {
const char *token;
- unsigned int mask; /* shall assume 32 bits of flags */
- unsigned int flag;
+ unsigned long long mask; /* shall assume 64 bits of flags */
+ unsigned long long flag;
unsigned int is_hash_algo;
} UNIX_Ctrls;
@@ -48,7 +48,7 @@ typedef struct {
/* the generic mask */
-#define _ALL_ON_ (~0U)
+#define _ALL_ON_ (~0ULL)
/* end of macro definitions definitions for the control flags */
@@ -98,47 +98,53 @@ typedef struct {
#define UNIX_QUIET 28 /* Don't print informational messages */
#define UNIX_NO_PASS_EXPIRY 29 /* Don't check for password expiration if not used for authentication */
#define UNIX_DES 30 /* DES, default */
+#define UNIX_GOST_YESCRYPT_PASS 31 /* new password hashes will use gost-yescrypt */
+#define UNIX_YESCRYPT_PASS 32 /* new password hashes will use yescrypt */
+#define UNIX_NULLRESETOK 33 /* allow empty password if password reset is enforced */
/* -------------- */
-#define UNIX_CTRLS_ 31 /* number of ctrl arguments defined */
+#define UNIX_CTRLS_ 34 /* number of ctrl arguments defined */
-#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl))
+#define UNIX_DES_CRYPT(ctrl) (off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl)&&off(UNIX_GOST_YESCRYPT_PASS,ctrl)&&off(UNIX_YESCRYPT_PASS,ctrl))
static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
{
-/* symbol token name ctrl mask ctrl *
- * ----------------------- ------------------- --------------------- -------- */
-
-/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0},
-/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0},
-/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0},
-/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0},
-/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060), 020, 0},
-/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060), 040, 0},
-/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0},
-/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600), 0200, 0},
-/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600), 0400, 0},
-/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
-/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
-/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
-/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
-/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000, 1},
-/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0, 0},
-/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0},
-/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0},
-/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0},
-/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000, 1},
-/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0},
-/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0},
-/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0},
-/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0},
-/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000, 1},
-/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000, 1},
-/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0},
-/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000, 1},
-/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0},
-/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0},
-/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0},
-/* UNIX_DES */ {"des", _ALL_ON_^(0260420000), 0, 1},
+/* symbol token name ctrl mask ctrl *
+ * --------------------------- -------------------- ------------------------- ---------------- */
+
+/* UNIX__OLD_PASSWD */ {NULL, _ALL_ON_, 01, 0},
+/* UNIX__VERIFY_PASSWD */ {NULL, _ALL_ON_, 02, 0},
+/* UNIX__IAMROOT */ {NULL, _ALL_ON_, 04, 0},
+/* UNIX_AUDIT */ {"audit", _ALL_ON_, 010, 0},
+/* UNIX_USE_FIRST_PASS */ {"use_first_pass", _ALL_ON_^(060ULL), 020, 0},
+/* UNIX_TRY_FIRST_PASS */ {"try_first_pass", _ALL_ON_^(060ULL), 040, 0},
+/* UNIX_AUTHTOK_TYPE */ {"authtok_type=", _ALL_ON_, 0100, 0},
+/* UNIX__PRELIM */ {NULL, _ALL_ON_^(0600ULL), 0200, 0},
+/* UNIX__UPDATE */ {NULL, _ALL_ON_^(0600ULL), 0400, 0},
+/* UNIX__NONULL */ {NULL, _ALL_ON_, 01000, 0},
+/* UNIX__QUIET */ {NULL, _ALL_ON_, 02000, 0},
+/* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000, 0},
+/* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000, 0},
+/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(015660420000ULL), 020000, 1},
+/* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000ULL), 0, 0},
+/* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000, 0},
+/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000, 0},
+/* UNIX_NIS */ {"nis", _ALL_ON_, 0200000, 0},
+/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(015660420000ULL), 0400000, 1},
+/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000, 0},
+/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000, 0},
+/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000, 0},
+/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000, 0},
+/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(015660420000ULL), 020000000, 1},
+/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(015660420000ULL), 040000000, 1},
+/* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000, 0},
+/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(015660420000ULL), 0200000000, 1},
+/* UNIX_MIN_PASS_LEN */ {"minlen=", _ALL_ON_, 0400000000, 0},
+/* UNIX_QUIET */ {"quiet", _ALL_ON_, 01000000000, 0},
+/* UNIX_NO_PASS_EXPIRY */ {"no_pass_expiry", _ALL_ON_, 02000000000, 0},
+/* UNIX_DES */ {"des", _ALL_ON_^(015660420000ULL), 0, 1},
+/* UNIX_GOST_YESCRYPT_PASS */ {"gost_yescrypt", _ALL_ON_^(015660420000ULL), 04000000000, 1},
+/* UNIX_YESCRYPT_PASS */ {"yescrypt", _ALL_ON_^(015660420000ULL), 010000000000, 1},
+/* UNIX_NULLRESETOK */ {"nullresetok", _ALL_ON_, 020000000000, 0},
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
@@ -151,27 +157,26 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
_pam_drop(xx); \
}
-extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl
- ,int type, const char *text);
-extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int *rounds,
- int *pass_min_len, int argc, const char **argv);
+extern int _make_remark(pam_handle_t * pamh, unsigned long long ctrl,
+ int type, const char *text);
+extern unsigned long long _set_ctrl(pam_handle_t * pamh, int flags,
+ int *remember, int *rounds,
+ int *pass_min_len,
+ int argc, const char **argv);
extern int _unix_getpwnam (pam_handle_t *pamh,
const char *name, int files, int nis,
struct passwd **ret);
extern int _unix_comesfromsource (pam_handle_t *pamh,
const char *name, int files, int nis);
-extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl,
+extern int _unix_blankpasswd(pam_handle_t *pamh, unsigned long long ctrl,
const char *name);
-extern int _unix_verify_password(pam_handle_t * pamh, const char *name
- ,const char *p, unsigned int ctrl);
-extern int _unix_read_password(pam_handle_t * pamh
- ,unsigned int ctrl
- ,const char *comment
- ,const char *prompt1
- ,const char *prompt2
- ,const char *data_name
- ,const void **pass);
+extern int _unix_verify_password(pam_handle_t * pamh, const char *name,
+ const char *p, unsigned long long ctrl);
+
+extern int _unix_verify_user(pam_handle_t *pamh, unsigned long long ctrl,
+ const char *name, int *daysleft);
extern int _unix_run_verify_binary(pam_handle_t *pamh,
- unsigned int ctrl, const char *user, int *daysleft);
+ unsigned long long ctrl,
+ const char *user, int *daysleft);
#endif /* _PAM_UNIX_SUPPORT_H */
diff --git a/modules/pam_unix/unix_chkpwd.8 b/modules/pam_unix/unix_chkpwd.8
index 46048995..e5d40ad3 100644
--- a/modules/pam_unix/unix_chkpwd.8
+++ b/modules/pam_unix/unix_chkpwd.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: unix_chkpwd
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 05/18/2017
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 06/08/2020
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM Manual
.\" Language: English
.\"
-.TH "UNIX_CHKPWD" "8" "05/18/2017" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "UNIX_CHKPWD" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c
index 39c84dbf..88647e58 100644
--- a/modules/pam_unix/unix_chkpwd.c
+++ b/modules/pam_unix/unix_chkpwd.c
@@ -2,7 +2,7 @@
* This program is designed to run setuid(root) or with sufficient
* privilege to read all of the unix password databases. It is designed
* to provide a mechanism for the current user (defined by this
- * process' uid) to verify their own password.
+ * process's uid) to verify their own password.
*
* The password is read from the standard input. The exit status of
* this program indicates whether the user is authenticated or not.
@@ -188,7 +188,14 @@ int main(int argc, char *argv[])
#endif
helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user);
}
- return PAM_AUTH_ERR;
+ /* if helper_verify_password() returned PAM_USER_UNKNOWN, the
+ most appropriate error to propagate to
+ _unix_verify_password() is PAM_AUTHINFO_UNAVAIL; otherwise
+ return general failure */
+ if (retval == PAM_USER_UNKNOWN)
+ return PAM_AUTHINFO_UNAVAIL;
+ else
+ return PAM_AUTH_ERR;
} else {
if (getuid() != 0) {
#ifdef HAVE_LIBAUDIT
diff --git a/modules/pam_unix/unix_update.8 b/modules/pam_unix/unix_update.8
index c5eab08c..4a7a3d1b 100644
--- a/modules/pam_unix/unix_update.8
+++ b/modules/pam_unix/unix_update.8
@@ -1,13 +1,13 @@
'\" t
.\" Title: unix_update
.\" Author: [see the "AUTHOR" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 05/18/2017
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 06/08/2020
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM Manual
.\" Language: English
.\"
-.TH "UNIX_UPDATE" "8" "05/18/2017" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "UNIX_UPDATE" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------