diff options
Diffstat (limited to 'modules/pam_faillock')
-rw-r--r-- | modules/pam_faillock/Makefile.am | 19 | ||||
-rw-r--r-- | modules/pam_faillock/Makefile.in | 140 | ||||
-rw-r--r-- | modules/pam_faillock/README | 6 | ||||
-rw-r--r-- | modules/pam_faillock/README.xml | 35 | ||||
-rw-r--r-- | modules/pam_faillock/faillock.8 | 27 | ||||
-rw-r--r-- | modules/pam_faillock/faillock.8.xml | 60 | ||||
-rw-r--r-- | modules/pam_faillock/faillock.c | 17 | ||||
-rw-r--r-- | modules/pam_faillock/faillock.conf.5 | 39 | ||||
-rw-r--r-- | modules/pam_faillock/faillock.conf.5.xml | 65 | ||||
-rw-r--r-- | modules/pam_faillock/faillock.h | 1 | ||||
-rw-r--r-- | modules/pam_faillock/faillock_config.c | 266 | ||||
-rw-r--r-- | modules/pam_faillock/faillock_config.h | 90 | ||||
-rw-r--r-- | modules/pam_faillock/main.c | 165 | ||||
-rw-r--r-- | modules/pam_faillock/pam_faillock.8 | 21 | ||||
-rw-r--r-- | modules/pam_faillock/pam_faillock.8.xml | 98 | ||||
-rw-r--r-- | modules/pam_faillock/pam_faillock.c | 307 | ||||
-rw-r--r-- | modules/pam_faillock/tst-pam_faillock-retval.c | 119 |
17 files changed, 985 insertions, 490 deletions
diff --git a/modules/pam_faillock/Makefile.am b/modules/pam_faillock/Makefile.am index b1f2b3e5..ec61aeb0 100644 --- a/modules/pam_faillock/Makefile.am +++ b/modules/pam_faillock/Makefile.am @@ -15,17 +15,21 @@ endif XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml dist_check_SCRIPTS = tst-pam_faillock -TESTS = $(dist_check_SCRIPTS) +TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS) securelibdir = $(SECUREDIR) +if HAVE_VENDORDIR +secureconfdir = $(VENDOR_SCONFIGDIR) +else secureconfdir = $(SCONFIGDIR) +endif -noinst_HEADERS = faillock.h +noinst_HEADERS = faillock.h faillock_config.h AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ $(WARN_CFLAGS) -faillock_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ +faillock_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ pam_faillock_la_LDFLAGS = -no-undefined -avoid-version -module pam_faillock_la_LIBADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) @@ -33,7 +37,10 @@ if HAVE_VERSIONING pam_faillock_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map endif -faillock_LDFLAGS = @PIE_LDFLAGS@ +check_PROGRAMS = tst-pam_faillock-retval +tst_pam_faillock_retval_LDADD = $(top_builddir)/libpam/libpam.la + +faillock_LDFLAGS = @EXE_LDFLAGS@ faillock_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) dist_secureconf_DATA = faillock.conf @@ -41,8 +48,8 @@ dist_secureconf_DATA = faillock.conf securelib_LTLIBRARIES = pam_faillock.la sbin_PROGRAMS = faillock -pam_faillock_la_SOURCES = pam_faillock.c faillock.c -faillock_SOURCES = main.c faillock.c +pam_faillock_la_SOURCES = pam_faillock.c faillock.c faillock_config.c +faillock_SOURCES = main.c faillock.c faillock_config.c if ENABLE_REGENERATE_MAN dist_noinst_DATA = README diff --git a/modules/pam_faillock/Makefile.in b/modules/pam_faillock/Makefile.in index b2a80262..e9b62c30 100644 --- a/modules/pam_faillock/Makefile.in +++ b/modules/pam_faillock/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.3 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -98,21 +98,25 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map +check_PROGRAMS = tst-pam_faillock-retval$(EXEEXT) sbin_PROGRAMS = faillock$(EXEEXT) subdir = modules/pam_faillock 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 \ - $(top_srcdir)/m4/japhar_grep_cflags.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/jh_path_xml_catalog.m4 \ $(top_srcdir)/m4/ld-O1.m4 $(top_srcdir)/m4/ld-as-needed.m4 \ - $(top_srcdir)/m4/ld-no-undefined.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/ld-no-undefined.m4 \ + $(top_srcdir)/m4/ld-z-now.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libprelude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/warn_lang_flags.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \ @@ -157,7 +161,8 @@ LTLIBRARIES = $(securelib_LTLIBRARIES) am__DEPENDENCIES_1 = pam_faillock_la_DEPENDENCIES = $(top_builddir)/libpam/libpam.la \ $(am__DEPENDENCIES_1) -am_pam_faillock_la_OBJECTS = pam_faillock.lo faillock.lo +am_pam_faillock_la_OBJECTS = pam_faillock.lo faillock.lo \ + faillock_config.lo pam_faillock_la_OBJECTS = $(am_pam_faillock_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -168,13 +173,17 @@ pam_faillock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_CFLAGS) $(CFLAGS) $(pam_faillock_la_LDFLAGS) $(LDFLAGS) \ -o $@ am_faillock_OBJECTS = faillock-main.$(OBJEXT) \ - faillock-faillock.$(OBJEXT) + faillock-faillock.$(OBJEXT) faillock-faillock_config.$(OBJEXT) faillock_OBJECTS = $(am_faillock_OBJECTS) faillock_DEPENDENCIES = $(top_builddir)/libpam/libpam.la \ $(am__DEPENDENCIES_1) faillock_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(faillock_CFLAGS) \ $(CFLAGS) $(faillock_LDFLAGS) $(LDFLAGS) -o $@ +tst_pam_faillock_retval_SOURCES = tst-pam_faillock-retval.c +tst_pam_faillock_retval_OBJECTS = tst-pam_faillock-retval.$(OBJEXT) +tst_pam_faillock_retval_DEPENDENCIES = \ + $(top_builddir)/libpam/libpam.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -191,8 +200,10 @@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/faillock-faillock.Po \ + ./$(DEPDIR)/faillock-faillock_config.Po \ ./$(DEPDIR)/faillock-main.Po ./$(DEPDIR)/faillock.Plo \ - ./$(DEPDIR)/pam_faillock.Plo + ./$(DEPDIR)/faillock_config.Plo ./$(DEPDIR)/pam_faillock.Plo \ + ./$(DEPDIR)/tst-pam_faillock-retval.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -212,8 +223,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(pam_faillock_la_SOURCES) $(faillock_SOURCES) -DIST_SOURCES = $(pam_faillock_la_SOURCES) $(faillock_SOURCES) +SOURCES = $(pam_faillock_la_SOURCES) $(faillock_SOURCES) \ + tst-pam_faillock-retval.c +DIST_SOURCES = $(pam_faillock_la_SOURCES) $(faillock_SOURCES) \ + tst-pam_faillock-retval.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -400,6 +413,7 @@ am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log @@ -444,10 +458,14 @@ CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CRYPTO_LIBS = @CRYPTO_LIBS@ +CRYPT_CFLAGS = @CRYPT_CFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ +DOCBOOK_RNG = @DOCBOOK_RNG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -457,12 +475,16 @@ ECONF_CFLAGS = @ECONF_CFLAGS@ ECONF_LIBS = @ECONF_LIBS@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ +EXE_CFLAGS = @EXE_CFLAGS@ +EXE_LDFLAGS = @EXE_LDFLAGS@ FGREP = @FGREP@ +FILECMD = @FILECMD@ FO2PDF = @FO2PDF@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ +HTML_STYLESHEET = @HTML_STYLESHEET@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -476,7 +498,6 @@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBAUDIT = @LIBAUDIT@ -LIBCRACK = @LIBCRACK@ LIBCRYPT = @LIBCRYPT@ LIBDB = @LIBDB@ LIBDL = @LIBDL@ @@ -495,12 +516,14 @@ LIBSELINUX = @LIBSELINUX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ +LOGIND_CFLAGS = @LOGIND_CFLAGS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ +MAN_STYLESHEET = @MAN_STYLESHEET@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ @@ -523,8 +546,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PIE_CFLAGS = @PIE_CFLAGS@ -PIE_LDFLAGS = @PIE_LDFLAGS@ +PDF_STYLESHEET = @PDF_STYLESHEET@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -535,11 +557,16 @@ SECUREDIR = @SECUREDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +STRINGPARAM_PROFILECONDITIONS = @STRINGPARAM_PROFILECONDITIONS@ STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@ STRIP = @STRIP@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIRPC_CFLAGS = @TIRPC_CFLAGS@ TIRPC_LIBS = @TIRPC_LIBS@ +TXT_STYLESHEET = @TXT_STYLESHEET@ USE_NLS = @USE_NLS@ +VENDOR_SCONFIGDIR = @VENDOR_SCONFIGDIR@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -584,7 +611,6 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ -libc_cv_fpie = @libc_cv_fpie@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ @@ -592,9 +618,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -pam_cv_ld_O1 = @pam_cv_ld_O1@ -pam_cv_ld_as_needed = @pam_cv_ld_as_needed@ -pam_cv_ld_no_undefined = @pam_cv_ld_no_undefined@ pam_xauth_path = @pam_xauth_path@ pdfdir = @pdfdir@ prefix = @prefix@ @@ -604,6 +627,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemdunitdir = @systemdunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ @@ -614,23 +638,25 @@ EXTRA_DIST = $(XMLS) @HAVE_DOC_TRUE@dist_man_MANS = pam_faillock.8 faillock.8 faillock.conf.5 XMLS = README.xml pam_faillock.8.xml faillock.8.xml faillock.conf.5.xml dist_check_SCRIPTS = tst-pam_faillock -TESTS = $(dist_check_SCRIPTS) +TESTS = $(dist_check_SCRIPTS) $(check_PROGRAMS) securelibdir = $(SECUREDIR) -secureconfdir = $(SCONFIGDIR) -noinst_HEADERS = faillock.h +@HAVE_VENDORDIR_FALSE@secureconfdir = $(SCONFIGDIR) +@HAVE_VENDORDIR_TRUE@secureconfdir = $(VENDOR_SCONFIGDIR) +noinst_HEADERS = faillock.h faillock_config.h AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ $(WARN_CFLAGS) -faillock_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ +faillock_CFLAGS = $(AM_CFLAGS) @EXE_CFLAGS@ pam_faillock_la_LDFLAGS = -no-undefined -avoid-version -module \ $(am__append_1) pam_faillock_la_LIBADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) -faillock_LDFLAGS = @PIE_LDFLAGS@ +tst_pam_faillock_retval_LDADD = $(top_builddir)/libpam/libpam.la +faillock_LDFLAGS = @EXE_LDFLAGS@ faillock_LDADD = $(top_builddir)/libpam/libpam.la $(LIBAUDIT) dist_secureconf_DATA = faillock.conf securelib_LTLIBRARIES = pam_faillock.la -pam_faillock_la_SOURCES = pam_faillock.c faillock.c -faillock_SOURCES = main.c faillock.c +pam_faillock_la_SOURCES = pam_faillock.c faillock.c faillock_config.c +faillock_SOURCES = main.c faillock.c faillock_config.c @ENABLE_REGENERATE_MAN_TRUE@dist_noinst_DATA = README all: all-am @@ -665,6 +691,15 @@ $(top_srcdir)/configure: $(am__configure_deps) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ @@ -757,6 +792,10 @@ faillock$(EXEEXT): $(faillock_OBJECTS) $(faillock_DEPENDENCIES) $(EXTRA_faillock @rm -f faillock$(EXEEXT) $(AM_V_CCLD)$(faillock_LINK) $(faillock_OBJECTS) $(faillock_LDADD) $(LIBS) +tst-pam_faillock-retval$(EXEEXT): $(tst_pam_faillock_retval_OBJECTS) $(tst_pam_faillock_retval_DEPENDENCIES) $(EXTRA_tst_pam_faillock_retval_DEPENDENCIES) + @rm -f tst-pam_faillock-retval$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tst_pam_faillock_retval_OBJECTS) $(tst_pam_faillock_retval_LDADD) $(LIBS) + mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -764,9 +803,12 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock-faillock.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock-faillock_config.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock-main.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faillock_config.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_faillock.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst-pam_faillock-retval.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -823,6 +865,20 @@ faillock-faillock.obj: faillock.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-faillock.obj `if test -f 'faillock.c'; then $(CYGPATH_W) 'faillock.c'; else $(CYGPATH_W) '$(srcdir)/faillock.c'; fi` +faillock-faillock_config.o: faillock_config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -MT faillock-faillock_config.o -MD -MP -MF $(DEPDIR)/faillock-faillock_config.Tpo -c -o faillock-faillock_config.o `test -f 'faillock_config.c' || echo '$(srcdir)/'`faillock_config.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/faillock-faillock_config.Tpo $(DEPDIR)/faillock-faillock_config.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='faillock_config.c' object='faillock-faillock_config.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-faillock_config.o `test -f 'faillock_config.c' || echo '$(srcdir)/'`faillock_config.c + +faillock-faillock_config.obj: faillock_config.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -MT faillock-faillock_config.obj -MD -MP -MF $(DEPDIR)/faillock-faillock_config.Tpo -c -o faillock-faillock_config.obj `if test -f 'faillock_config.c'; then $(CYGPATH_W) 'faillock_config.c'; else $(CYGPATH_W) '$(srcdir)/faillock_config.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/faillock-faillock_config.Tpo $(DEPDIR)/faillock-faillock_config.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='faillock_config.c' object='faillock-faillock_config.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(faillock_CFLAGS) $(CFLAGS) -c -o faillock-faillock_config.obj `if test -f 'faillock_config.c'; then $(CYGPATH_W) 'faillock_config.c'; else $(CYGPATH_W) '$(srcdir)/faillock_config.c'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -1095,7 +1151,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ - echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ @@ -1108,7 +1164,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) fi; \ $$success || exit 1 -check-TESTS: $(dist_check_SCRIPTS) +check-TESTS: $(check_PROGRAMS) $(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) @@ -1118,7 +1174,7 @@ check-TESTS: $(dist_check_SCRIPTS) log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; -recheck: all $(dist_check_SCRIPTS) +recheck: all $(check_PROGRAMS) $(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 \ @@ -1136,6 +1192,13 @@ tst-pam_faillock.log: tst-pam_faillock --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tst-pam_faillock-retval.log: tst-pam_faillock-retval$(EXEEXT) + @p='tst-pam_faillock-retval$(EXEEXT)'; \ + b='tst-pam_faillock-retval'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ @@ -1185,7 +1248,8 @@ distdir-am: $(DISTFILES) fi; \ done check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) $(dist_check_SCRIPTS) + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) \ + $(dist_check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS) @@ -1230,14 +1294,17 @@ maintainer-clean-generic: -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am -clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ - clean-securelibLTLIBRARIES mostlyclean-am +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + clean-sbinPROGRAMS clean-securelibLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/faillock-faillock.Po + -rm -f ./$(DEPDIR)/faillock-faillock_config.Po -rm -f ./$(DEPDIR)/faillock-main.Po -rm -f ./$(DEPDIR)/faillock.Plo + -rm -f ./$(DEPDIR)/faillock_config.Plo -rm -f ./$(DEPDIR)/pam_faillock.Plo + -rm -f ./$(DEPDIR)/tst-pam_faillock-retval.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1285,9 +1352,12 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/faillock-faillock.Po + -rm -f ./$(DEPDIR)/faillock-faillock_config.Po -rm -f ./$(DEPDIR)/faillock-main.Po -rm -f ./$(DEPDIR)/faillock.Plo + -rm -f ./$(DEPDIR)/faillock_config.Plo -rm -f ./$(DEPDIR)/pam_faillock.Plo + -rm -f ./$(DEPDIR)/tst-pam_faillock-retval.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -1312,9 +1382,9 @@ uninstall-man: uninstall-man5 uninstall-man8 .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ - check-am clean clean-generic clean-libtool clean-sbinPROGRAMS \ - clean-securelibLTLIBRARIES cscopelist-am ctags ctags-am \ - distclean distclean-compile distclean-generic \ + check-am clean clean-checkPROGRAMS clean-generic clean-libtool \ + 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-dist_secureconfDATA install-dvi \ diff --git a/modules/pam_faillock/README b/modules/pam_faillock/README index c88705ad..574b37bd 100644 --- a/modules/pam_faillock/README +++ b/modules/pam_faillock/README @@ -48,6 +48,10 @@ conf=/path/to/config-file Use another configuration file instead of the default /etc/security/ faillock.conf. + Use another configuration file instead of the default which is to use the + file /etc/security/faillock.conf or, if that one is not present, the file + %vendordir%/security/faillock.conf. + The options for configuring the module behavior are described in the faillock.conf(5) manual page. The options specified on the module command line override the values from the configuration file. @@ -66,7 +70,7 @@ screensaver. Note that using the module in preauth without the silent option specified in / etc/security/faillock.conf or with requisite control field leaks an information -about existence or non-existence of an user account in the system because the +about existence or non-existence of a user account in the system because the failures are not recorded for the unknown users. The message about the user account being locked is never displayed for non-existing user accounts allowing the adversary to infer that a particular account is not existing on a system. diff --git a/modules/pam_faillock/README.xml b/modules/pam_faillock/README.xml index f0654dbe..a62c917a 100644 --- a/modules/pam_faillock/README.xml +++ b/modules/pam_faillock/README.xml @@ -1,46 +1,31 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" -"http://www.docbook.org/xml/4.3/docbookx.dtd" -[ -<!-- -<!ENTITY pamaccess SYSTEM "pam_faillock.8.xml"> ---> -]> +<article xmlns="http://docbook.org/ns/docbook" version="5.0"> -<article> - - <articleinfo> + <info> <title> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_faillock.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_faillock-name"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_faillock.8.xml" xpointer='xpointer(id("pam_faillock-name")/*)'/> </title> - </articleinfo> + </info> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-description"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_faillock.8.xml" xpointer='xpointer(id("pam_faillock-description")/*)'/> </section> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-options"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_faillock.8.xml" xpointer='xpointer(id("pam_faillock-options")/*)'/> </section> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-notes"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_faillock.8.xml" xpointer='xpointer(id("pam_faillock-notes")/*)'/> </section> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-examples"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_faillock.8.xml" xpointer='xpointer(id("pam_faillock-examples")/*)'/> </section> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_faillock.8.xml" xpointer='xpointer(//refsect1[@id = "pam_faillock-author"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_faillock.8.xml" xpointer='xpointer(id("pam_faillock-author")/*)'/> </section> -</article> +</article>
\ No newline at end of file diff --git a/modules/pam_faillock/faillock.8 b/modules/pam_faillock/faillock.8 index 3ba58aa0..5d9c5db8 100644 --- a/modules/pam_faillock/faillock.8 +++ b/modules/pam_faillock/faillock.8 @@ -1,13 +1,13 @@ '\" t .\" Title: faillock .\" Author: [see the "AUTHOR" section] -.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 06/08/2020 +.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/> +.\" Date: 05/07/2023 .\" Manual: Linux-PAM Manual -.\" Source: Linux-PAM Manual +.\" Source: Linux-PAM .\" Language: English .\" -.TH "FAILLOCK" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "FAILLOCK" "8" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -48,18 +48,27 @@ or clear the tally files of all or individual \fIusernames\fR\&. .SH "OPTIONS" .PP -\fB\-\-dir \fR\fB\fI/path/to/tally\-directory\fR\fR +\-\-conf /path/to/config\-file .RS 4 -The directory where the user files with the failure records are kept\&. The default is -/var/run/faillock\&. +The file where the configuration is located\&. The default is +/etc/security/faillock\&.conf\&. .RE .PP -\fB\-\-user \fR\fB\fIusername\fR\fR +\-\-dir /path/to/tally\-directory +.RS 4 +The directory where the user files with the failure records are kept\&. +.sp +The priority to set this option is to use the value provided from the command line\&. If this isn\*(Aqt provided, then the value from the configuration file is used\&. Finally, if neither of them has been provided, then +/var/run/faillock +is used\&. +.RE +.PP +\-\-user username .RS 4 The user whose failure records should be displayed or cleared\&. .RE .PP -\fB\-\-reset\fR +\-\-reset .RS 4 Instead of displaying the user\*(Aqs failure records, clear them\&. .RE diff --git a/modules/pam_faillock/faillock.8.xml b/modules/pam_faillock/faillock.8.xml index 6c20593c..74440fc8 100644 --- a/modules/pam_faillock/faillock.8.xml +++ b/modules/pam_faillock/faillock.8.xml @@ -1,36 +1,33 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="faillock"> +<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="faillock"> <refmeta> <refentrytitle>faillock</refentrytitle> <manvolnum>8</manvolnum> - <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> + <refmiscinfo class="source">Linux-PAM</refmiscinfo> + <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo> </refmeta> - <refnamediv id="pam_faillock-name"> + <refnamediv xml:id="pam_faillock-name"> <refname>faillock</refname> <refpurpose>Tool for displaying and modifying the authentication failure record files</refpurpose> </refnamediv> <refsynopsisdiv> - <cmdsynopsis id="faillock-cmdsynopsis"> + <cmdsynopsis xml:id="faillock-cmdsynopsis" sepchar=" "> <command>faillock</command> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> --dir <replaceable>/path/to/tally-directory</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> --user <replaceable>username</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> --reset </arg> </cmdsynopsis> </refsynopsisdiv> - <refsect1 id="faillock-description"> + <refsect1 xml:id="faillock-description"> <title>DESCRIPTION</title> @@ -51,24 +48,41 @@ </para> </refsect1> - <refsect1 id="faillock-options"> + <refsect1 xml:id="faillock-options"> <title>OPTIONS</title> <variablelist> <varlistentry> <term> - <option>--dir <replaceable>/path/to/tally-directory</replaceable></option> + --conf /path/to/config-file </term> <listitem> <para> - The directory where the user files with the failure records are kept. The - default is <filename>/var/run/faillock</filename>. + The file where the configuration is located. The default is + <filename>/etc/security/faillock.conf</filename>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + --dir /path/to/tally-directory + </term> + <listitem> + <para> + The directory where the user files with the failure records are kept. + </para> + <para> + The priority to set this option is to use the value provided + from the command line. If this isn't provided, then the value + from the configuration file is used. Finally, if neither of + them has been provided, then + <filename>/var/run/faillock</filename> is used. </para> </listitem> </varlistentry> <varlistentry> <term> - <option>--user <replaceable>username</replaceable></option> + --user username </term> <listitem> <para> @@ -78,7 +92,7 @@ </varlistentry> <varlistentry> <term> - <option>--reset</option> + --reset </term> <listitem> <para> @@ -89,11 +103,11 @@ </variablelist> </refsect1> - <refsect1 id="faillock-files"> + <refsect1 xml:id="faillock-files"> <title>FILES</title> <variablelist> <varlistentry> - <term><filename>/var/run/faillock/*</filename></term> + <term>/var/run/faillock/*</term> <listitem> <para>the files logging the authentication failures for users</para> </listitem> @@ -101,7 +115,7 @@ </variablelist> </refsect1> - <refsect1 id='faillock-see_also'> + <refsect1 xml:id="faillock-see_also"> <title>SEE ALSO</title> <para> <citerefentry> @@ -113,11 +127,11 @@ </para> </refsect1> - <refsect1 id='faillock-author'> + <refsect1 xml:id="faillock-author"> <title>AUTHOR</title> <para> faillock was written by Tomas Mraz. </para> </refsect1> -</refentry> +</refentry>
\ No newline at end of file diff --git a/modules/pam_faillock/faillock.c b/modules/pam_faillock/faillock.c index e492f5f9..091f253a 100644 --- a/modules/pam_faillock/faillock.c +++ b/modules/pam_faillock/faillock.c @@ -74,9 +74,12 @@ open_tally (const char *dir, const char *user, uid_t uid, int create) if (create) { flags |= O_CREAT; + if (access(dir, F_OK) != 0) { + mkdir(dir, 0755); + } } - fd = open(path, flags, 0600); + fd = open(path, flags, 0660); free(path); @@ -88,6 +91,18 @@ open_tally (const char *dir, const char *user, uid_t uid, int create) if (st.st_uid != uid) { ignore_return(fchown(fd, uid, -1)); } + + /* + * If umask is set to 022, as will probably in most systems, then the + * group will not be able to write to the file. So, change the file + * permissions just in case. + * Note: owners of this file are user:root, so if the permissions are + * not changed the root process writing to this file will require + * CAP_DAC_OVERRIDE. + */ + if (!(st.st_mode & S_IWGRP)) { + ignore_return(fchmod(fd, 0660)); + } } } diff --git a/modules/pam_faillock/faillock.conf.5 b/modules/pam_faillock/faillock.conf.5 index 7870153d..fd257b08 100644 --- a/modules/pam_faillock/faillock.conf.5 +++ b/modules/pam_faillock/faillock.conf.5 @@ -1,13 +1,13 @@ '\" t .\" Title: faillock.conf .\" Author: [see the "AUTHOR" section] -.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 06/08/2020 +.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/> +.\" Date: 05/07/2023 .\" Manual: Linux-PAM Manual -.\" Source: Linux-PAM Manual +.\" Source: Linux-PAM .\" Language: English .\" -.TH "FAILLOCK\&.CONF" "5" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "FAILLOCK\&.CONF" "5" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -47,49 +47,58 @@ character\&. The whitespace at the beginning of line, end of line, and around th sign is ignored\&. .SH "OPTIONS" .PP -\fBdir=\fR\fB\fI/path/to/tally\-directory\fR\fR +dir=/path/to/tally\-directory .RS 4 The directory where the user files with the failure records are kept\&. The default is /var/run/faillock\&. +.sp +Note: These files will disappear after reboot on systems configured with directory +/var/run/faillock +mounted on virtual memory\&. .RE .PP -\fBaudit\fR +audit .RS 4 Will log the user name into the system log if the user is not found\&. .RE .PP -\fBsilent\fR +silent .RS 4 Don\*(Aqt print informative messages to the user\&. Please note that when this option is not used there will be difference in the authentication behavior for users which exist on the system and non\-existing users\&. .RE .PP -\fBno_log_info\fR +no_log_info .RS 4 Don\*(Aqt log informative messages via \fBsyslog\fR(3)\&. .RE .PP -\fBlocal_users_only\fR +local_users_only .RS 4 Only track failed user authentications attempts for local users in /etc/passwd and ignore centralized (AD, IdM, LDAP, etc\&.) users\&. The \fBfaillock\fR(8) command will also no longer track user failed authentication attempts\&. Enabling this option will prevent a double\-lockout scenario where a user is locked out locally and in the centralized mechanism\&. .RE .PP -\fBdeny=\fR\fB\fIn\fR\fR +nodelay +.RS 4 +Don\*(Aqt enforce a delay after authentication failures\&. +.RE +.PP +deny=n .RS 4 Deny access if the number of consecutive authentication failures for this user during the recent interval exceeds \fIn\fR\&. The default is 3\&. .RE .PP -\fBfail_interval=\fR\fB\fIn\fR\fR +fail_interval=n .RS 4 The length of the interval during which the consecutive authentication failures must happen for the user account lock out is \fIn\fR seconds\&. The default is 900 (15 minutes)\&. .RE .PP -\fBunlock_time=\fR\fB\fIn\fR\fR +unlock_time=n .RS 4 The access will be re\-enabled after \fIn\fR @@ -108,12 +117,12 @@ option\&. Also note that it is usually undesirable to permanently lock out users as they can become easily a target of denial of service attack unless the usernames are random and kept secret to potential attackers\&. .RE .PP -\fBeven_deny_root\fR +even_deny_root .RS 4 Root account can become locked as well as regular accounts\&. .RE .PP -\fBroot_unlock_time=\fR\fB\fIn\fR\fR +root_unlock_time=n .RS 4 This option implies \fBeven_deny_root\fR @@ -124,7 +133,7 @@ seconds to root account after the account is locked\&. In case the option is not option\&. .RE .PP -\fBadmin_group=\fR\fB\fIname\fR\fR +admin_group=name .RS 4 If a group name is specified with this option, members of the group will be handled by this module the same as the root account (the options \fBeven_deny_root\fR diff --git a/modules/pam_faillock/faillock.conf.5.xml b/modules/pam_faillock/faillock.conf.5.xml index aa8500b9..cc750fbf 100644 --- a/modules/pam_faillock/faillock.conf.5.xml +++ b/modules/pam_faillock/faillock.conf.5.xml @@ -1,25 +1,22 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="faillock.conf"> +<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="faillock.conf"> <refmeta> <refentrytitle>faillock.conf</refentrytitle> <manvolnum>5</manvolnum> - <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> + <refmiscinfo class="source">Linux-PAM</refmiscinfo> + <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo> </refmeta> - <refnamediv id="faillock.conf-name"> + <refnamediv xml:id="faillock.conf-name"> <refname>faillock.conf</refname> <refpurpose>pam_faillock configuration file</refpurpose> </refnamediv> - <refsect1 id="faillock.conf-description"> + <refsect1 xml:id="faillock.conf-description"> <title>DESCRIPTION</title> <para> - <emphasis remap='B'>faillock.conf</emphasis> provides a way to configure the + <emphasis remap="B">faillock.conf</emphasis> provides a way to configure the default settings for locking the user after multiple failed authentication attempts. This file is read by the <emphasis>pam_faillock</emphasis> module and is the preferred method over configuring <emphasis>pam_faillock</emphasis> directly. @@ -31,24 +28,28 @@ </para> </refsect1> - <refsect1 id="faillock.conf-options"> + <refsect1 xml:id="faillock.conf-options"> <title>OPTIONS</title> <variablelist> <varlistentry> <term> - <option>dir=<replaceable>/path/to/tally-directory</replaceable></option> + dir=/path/to/tally-directory </term> <listitem> <para> The directory where the user files with the failure records are kept. The default is <filename>/var/run/faillock</filename>. </para> + <para> + Note: These files will disappear after reboot on systems configured with + directory <filename>/var/run/faillock</filename> mounted on virtual memory. + </para> </listitem> </varlistentry> <varlistentry> <term> - <option>audit</option> + audit </term> <listitem> <para> @@ -58,7 +59,7 @@ </varlistentry> <varlistentry> <term> - <option>silent</option> + silent </term> <listitem> <para> @@ -70,7 +71,7 @@ </varlistentry> <varlistentry> <term> - <option>no_log_info</option> + no_log_info </term> <listitem> <para> @@ -80,7 +81,7 @@ </varlistentry> <varlistentry> <term> - <option>local_users_only</option> + local_users_only </term> <listitem> <para> @@ -96,7 +97,17 @@ </varlistentry> <varlistentry> <term> - <option>deny=<replaceable>n</replaceable></option> + nodelay + </term> + <listitem> + <para> + Don't enforce a delay after authentication failures. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + deny=n </term> <listitem> <para> @@ -108,7 +119,7 @@ </varlistentry> <varlistentry> <term> - <option>fail_interval=<replaceable>n</replaceable></option> + fail_interval=n </term> <listitem> <para> @@ -121,7 +132,7 @@ </varlistentry> <varlistentry> <term> - <option>unlock_time=<replaceable>n</replaceable></option> + unlock_time=n </term> <listitem> <para> @@ -149,7 +160,7 @@ </varlistentry> <varlistentry> <term> - <option>even_deny_root</option> + even_deny_root </term> <listitem> <para> @@ -159,7 +170,7 @@ </varlistentry> <varlistentry> <term> - <option>root_unlock_time=<replaceable>n</replaceable></option> + root_unlock_time=n </term> <listitem> <para> @@ -173,7 +184,7 @@ </varlistentry> <varlistentry> <term> - <option>admin_group=<replaceable>name</replaceable></option> + admin_group=name </term> <listitem> <para> @@ -188,7 +199,7 @@ </variablelist> </refsect1> - <refsect1 id='faillock.conf-examples'> + <refsect1 xml:id="faillock.conf-examples"> <title>EXAMPLES</title> <para> /etc/security/faillock.conf file example: @@ -200,11 +211,11 @@ silent </programlisting> </refsect1> - <refsect1 id="faillock.conf-files"> + <refsect1 xml:id="faillock.conf-files"> <title>FILES</title> <variablelist> <varlistentry> - <term><filename>/etc/security/faillock.conf</filename></term> + <term>/etc/security/faillock.conf</term> <listitem> <para>the config file for custom options</para> </listitem> @@ -212,7 +223,7 @@ silent </variablelist> </refsect1> - <refsect1 id='faillock.conf-see_also'> + <refsect1 xml:id="faillock.conf-see_also"> <title>SEE ALSO</title> <para> <citerefentry> @@ -233,11 +244,11 @@ silent </para> </refsect1> - <refsect1 id='faillock.conf-author'> + <refsect1 xml:id="faillock.conf-author"> <title>AUTHOR</title> <para> pam_faillock was written by Tomas Mraz. The support for faillock.conf was written by Brian Ward. </para> </refsect1> -</refentry> +</refentry>
\ No newline at end of file diff --git a/modules/pam_faillock/faillock.h b/modules/pam_faillock/faillock.h index b22a9dfb..0ea0ffba 100644 --- a/modules/pam_faillock/faillock.h +++ b/modules/pam_faillock/faillock.h @@ -67,7 +67,6 @@ struct tally_data { }; #define FAILLOCK_DEFAULT_TALLYDIR "/var/run/faillock" -#define FAILLOCK_DEFAULT_CONF "/etc/security/faillock.conf" int open_tally(const char *dir, const char *user, uid_t uid, int create); int read_tally(int fd, struct tally_data *tallies); diff --git a/modules/pam_faillock/faillock_config.c b/modules/pam_faillock/faillock_config.c new file mode 100644 index 00000000..0d14aad1 --- /dev/null +++ b/modules/pam_faillock/faillock_config.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2022 Tomas Mraz <tm@t8m.info> + * Copyright (c) 2022 Iker Pedrosa <ipedrosa@redhat.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include <security/pam_modules.h> + +#include "faillock_config.h" +#include "faillock.h" + +#define FAILLOCK_DEFAULT_CONF SCONFIGDIR "/faillock.conf" +#ifdef VENDOR_SCONFIGDIR +#define VENDOR_FAILLOCK_DEFAULT_CONF VENDOR_SCONFIGDIR "/faillock.conf" +#endif + +static void PAM_FORMAT((printf, 3, 4)) PAM_NONNULL((3)) +config_log(const pam_handle_t *pamh, int priority, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if (pamh) { + pam_vsyslog(pamh, priority, fmt, args); + } else { + char *buf = NULL; + + if (vasprintf(&buf, fmt, args) < 0) { + fprintf(stderr, "vasprintf: %m"); + va_end(args); + return; + } + fprintf(stderr, "%s\n", buf); + free(buf); + } + va_end(args); +} + +/* parse a single configuration file */ +int +read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) +{ + char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; + const char *fname = (cfgfile != NULL) ? cfgfile : FAILLOCK_DEFAULT_CONF; + FILE *f = fopen(fname, "r"); + +#ifdef VENDOR_FAILLOCK_DEFAULT_CONF + if (f == NULL && errno == ENOENT && cfgfile == NULL) { + /* + * If the default configuration file in /etc does not exist, + * try the vendor configuration file as fallback. + */ + f = fopen(VENDOR_FAILLOCK_DEFAULT_CONF, "r"); + } +#endif /* VENDOR_FAILLOCK_DEFAULT_CONF */ + + if (f == NULL) { + /* ignore non-existent default config file */ + if (errno == ENOENT && cfgfile == NULL) + return PAM_SUCCESS; + return PAM_SERVICE_ERR; + } + + while (fgets(linebuf, sizeof(linebuf), f) != NULL) { + size_t len; + char *ptr; + char *name; + int eq; + + len = strlen(linebuf); + /* len cannot be 0 unless there is a bug in fgets */ + if (len && linebuf[len - 1] != '\n' && !feof(f)) { + (void) fclose(f); + return PAM_SERVICE_ERR; + } + + if ((ptr=strchr(linebuf, '#')) != NULL) { + *ptr = '\0'; + } else { + ptr = linebuf + len; + } + + /* drop terminating whitespace including the \n */ + while (ptr > linebuf) { + if (!isspace(*(ptr-1))) { + *ptr = '\0'; + break; + } + --ptr; + } + + /* skip initial whitespace */ + for (ptr = linebuf; isspace(*ptr); ptr++); + if (*ptr == '\0') + continue; + + /* grab the key name */ + eq = 0; + name = ptr; + while (*ptr != '\0') { + if (isspace(*ptr) || *ptr == '=') { + eq = *ptr == '='; + *ptr = '\0'; + ++ptr; + break; + } + ++ptr; + } + + /* grab the key value */ + while (*ptr != '\0') { + if (*ptr != '=' || eq) { + if (!isspace(*ptr)) { + break; + } + } else { + eq = 1; + } + ++ptr; + } + + /* set the key:value pair on opts */ + set_conf_opt(pamh, opts, name, ptr); + } + + (void)fclose(f); + return PAM_SUCCESS; +} + +void +set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, + const char *value) +{ + if (strcmp(name, "dir") == 0) { + if (value[0] != '/') { + config_log(pamh, LOG_ERR, + "Tally directory is not absolute path (%s); keeping value", + value); + } else { + free(opts->dir); + opts->dir = strdup(value); + if (opts->dir == NULL) { + opts->fatal_error = 1; + config_log(pamh, LOG_CRIT, "Error allocating memory: %m"); + } + } + } + else if (strcmp(name, "deny") == 0) { + if (sscanf(value, "%hu", &opts->deny) != 1) { + config_log(pamh, LOG_ERR, + "Bad number supplied for deny argument"); + } + } + else if (strcmp(name, "fail_interval") == 0) { + unsigned int temp; + if (sscanf(value, "%u", &temp) != 1 || + temp > MAX_TIME_INTERVAL) { + config_log(pamh, LOG_ERR, + "Bad number supplied for fail_interval argument"); + } else { + opts->fail_interval = temp; + } + } + else if (strcmp(name, "unlock_time") == 0) { + unsigned int temp; + + if (strcmp(value, "never") == 0) { + opts->unlock_time = 0; + } + else if (sscanf(value, "%u", &temp) != 1 || + temp > MAX_TIME_INTERVAL) { + config_log(pamh, LOG_ERR, + "Bad number supplied for unlock_time argument"); + } + else { + opts->unlock_time = temp; + } + } + else if (strcmp(name, "root_unlock_time") == 0) { + unsigned int temp; + + if (strcmp(value, "never") == 0) { + opts->root_unlock_time = 0; + } + else if (sscanf(value, "%u", &temp) != 1 || + temp > MAX_TIME_INTERVAL) { + config_log(pamh, LOG_ERR, + "Bad number supplied for root_unlock_time argument"); + } else { + opts->root_unlock_time = temp; + } + } + else if (strcmp(name, "admin_group") == 0) { + free(opts->admin_group); + opts->admin_group = strdup(value); + if (opts->admin_group == NULL) { + opts->fatal_error = 1; + config_log(pamh, LOG_CRIT, "Error allocating memory: %m"); + } + } + else if (strcmp(name, "even_deny_root") == 0) { + opts->flags |= FAILLOCK_FLAG_DENY_ROOT; + } + else if (strcmp(name, "audit") == 0) { + opts->flags |= FAILLOCK_FLAG_AUDIT; + } + else if (strcmp(name, "silent") == 0) { + opts->flags |= FAILLOCK_FLAG_SILENT; + } + else if (strcmp(name, "no_log_info") == 0) { + opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; + } + else if (strcmp(name, "local_users_only") == 0) { + opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; + } + else if (strcmp(name, "nodelay") == 0) { + opts->flags |= FAILLOCK_FLAG_NO_DELAY; + } + else { + config_log(pamh, LOG_ERR, "Unknown option: %s", name); + } +} + +const char *get_tally_dir(const struct options *opts) +{ + return (opts->dir != NULL) ? opts->dir : FAILLOCK_DEFAULT_TALLYDIR; +} diff --git a/modules/pam_faillock/faillock_config.h b/modules/pam_faillock/faillock_config.h new file mode 100644 index 00000000..04bc699b --- /dev/null +++ b/modules/pam_faillock/faillock_config.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022 Tomas Mraz <tm@t8m.info> + * Copyright (c) 2022 Iker Pedrosa <ipedrosa@redhat.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * faillock_config.h - load configuration options from file + * + */ + +#ifndef _FAILLOCK_CONFIG_H +#define _FAILLOCK_CONFIG_H + +#include <limits.h> +#include <stdint.h> +#include <sys/types.h> + +#include <security/pam_ext.h> + +#define FAILLOCK_FLAG_DENY_ROOT 0x1 +#define FAILLOCK_FLAG_AUDIT 0x2 +#define FAILLOCK_FLAG_SILENT 0x4 +#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 +#define FAILLOCK_FLAG_UNLOCKED 0x10 +#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 +#define FAILLOCK_FLAG_NO_DELAY 0x40 + +#define FAILLOCK_CONF_MAX_LINELEN 1023 +#define MAX_TIME_INTERVAL 604800 /* 7 days */ + +struct options { + unsigned int action; + unsigned int flags; + unsigned short deny; + unsigned int fail_interval; + unsigned int unlock_time; + unsigned int root_unlock_time; + char *dir; + const char *user; + char *admin_group; + int failures; + uint64_t latest_time; + uid_t uid; + int is_admin; + uint64_t now; + int fatal_error; + + unsigned int reset; + const char *progname; + int legacy_output; /* show failure info in pam_tally2 style */ +}; + +int read_config_file(pam_handle_t *pamh, struct options *opts, + const char *cfgfile); +void set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, + const char *value); +const char *get_tally_dir(const struct options *opts); + +#endif /* _FAILLOCK_CONFIG_H */ diff --git a/modules/pam_faillock/main.c b/modules/pam_faillock/main.c index c5780166..136be834 100644 --- a/modules/pam_faillock/main.c +++ b/modules/pam_faillock/main.c @@ -51,33 +51,40 @@ #define AUDIT_NO_ID ((unsigned int) -1) #endif +#include "pam_inline.h" #include "faillock.h" - -struct options { - unsigned int reset; - const char *dir; - const char *user; - const char *progname; -}; +#include "faillock_config.h" static int args_parse(int argc, char **argv, struct options *opts) { int i; + int rv; + const char *dir = NULL; + const char *conf = NULL; + memset(opts, 0, sizeof(*opts)); - opts->dir = FAILLOCK_DEFAULT_TALLYDIR; opts->progname = argv[0]; for (i = 1; i < argc; ++i) { - - if (strcmp(argv[i], "--dir") == 0) { + if (strcmp(argv[i], "--conf") == 0) { ++i; if (i >= argc || strlen(argv[i]) == 0) { - fprintf(stderr, "%s: No directory supplied.\n", argv[0]); + fprintf(stderr, "%s: No configuration file supplied.\n", + argv[0]); return -1; } - opts->dir = argv[i]; + conf = argv[i]; + } + else if (strcmp(argv[i], "--dir") == 0) { + ++i; + if (i >= argc || strlen(argv[i]) == 0) { + fprintf(stderr, "%s: No records directory supplied.\n", + argv[0]); + return -1; + } + dir = argv[i]; } else if (strcmp(argv[i], "--user") == 0) { ++i; @@ -85,24 +92,118 @@ args_parse(int argc, char **argv, struct options *opts) fprintf(stderr, "%s: No user name supplied.\n", argv[0]); return -1; } - opts->user = argv[i]; + opts->user = argv[i]; } else if (strcmp(argv[i], "--reset") == 0) { opts->reset = 1; } + else if (!strcmp(argv[i], "--legacy-output")) { + opts->legacy_output = 1; + } else { fprintf(stderr, "%s: Unknown option: %s\n", argv[0], argv[i]); return -1; } } + + if ((rv = read_config_file(NULL, opts, conf)) != PAM_SUCCESS) { + fprintf(stderr, "Configuration file missing or broken"); + return rv; + } + + if (dir != NULL) { + free(opts->dir); + opts->dir = strdup(dir); + if (opts->dir == NULL) { + fprintf(stderr, "Error allocating memory: %m"); + return -1; + } + } + return 0; } static void usage(const char *progname) { - fprintf(stderr, _("Usage: %s [--dir /path/to/tally-directory] [--user username] [--reset]\n"), - progname); + fprintf(stderr, + _("Usage: %s [--dir /path/to/tally-directory]" + " [--user username] [--reset] [--legacy-output]\n"), progname); + +} + +static int +get_local_time(time_t when, char *timebuf, size_t timebuf_size) +{ + struct tm *tm; + + tm = localtime(&when); + if (tm == NULL) { + return -1; + } + strftime(timebuf, timebuf_size, "%Y-%m-%d %H:%M:%S", tm); + return 0; +} + +static void +print_in_new_format(struct options *opts, const struct tally_data *tallies, const char *user) +{ + uint32_t i; + + printf("%s:\n", user); + printf("%-19s %-5s %-48s %-5s\n", "When", "Type", "Source", "Valid"); + + for (i = 0; i < tallies->count; i++) { + uint16_t status; + char timebuf[80]; + + if (get_local_time(tallies->records[i].time, timebuf, sizeof(timebuf)) != 0) { + fprintf(stderr, "%s: Invalid timestamp in the tally record\n", + opts->progname); + continue; + } + + status = tallies->records[i].status; + + printf("%-19s %-5s %-52.52s %s\n", timebuf, + status & TALLY_STATUS_RHOST ? "RHOST" : (status & TALLY_STATUS_TTY ? "TTY" : "SVC"), + tallies->records[i].source, status & TALLY_STATUS_VALID ? "V":"I"); + } +} + +static void +print_in_legacy_format(struct options *opts, const struct tally_data *tallies, const char *user) +{ + uint32_t tally_count; + static uint32_t pr_once; + + if (pr_once == 0) { + printf(_("Login Failures Latest failure From\n")); + pr_once = 1; + } + + printf("%-15.15s ", user); + + tally_count = tallies->count; + + if (tally_count > 0) { + uint32_t i; + char timebuf[80]; + + i = tally_count - 1; + + if (get_local_time(tallies->records[i].time, timebuf, sizeof(timebuf)) != 0) { + fprintf(stderr, "%s: Invalid timestamp in the tally record\n", + opts->progname); + return; + } + + printf("%5u %25s %s\n", + tally_count, timebuf, tallies->records[i].source); + } + else { + printf("%5u\n", tally_count); + } } static int @@ -112,10 +213,15 @@ do_user(struct options *opts, const char *user) int rv; struct tally_data tallies; struct passwd *pwd; + const char *dir = get_tally_dir(opts); pwd = getpwnam(user); + if (pwd == NULL) { + fprintf(stderr, "%s: Error no such user: %s\n", opts->progname, user); + return 1; + } - fd = open_tally(opts->dir, user, pwd != NULL ? pwd->pw_uid : 0, 0); + fd = open_tally(dir, user, pwd->pw_uid, 1); if (fd == -1) { if (errno == ENOENT) { @@ -154,10 +260,8 @@ do_user(struct options *opts, const char *user) } } else { - unsigned int i; - memset(&tallies, 0, sizeof(tallies)); - if ((rv=read_tally(fd, &tallies)) == -1) { + if (read_tally(fd, &tallies) == -1) { fprintf(stderr, "%s: Error reading the tally file for %s:", opts->progname, user); perror(NULL); @@ -165,21 +269,13 @@ do_user(struct options *opts, const char *user) return 5; } - printf("%s:\n", user); - printf("%-19s %-5s %-48s %-5s\n", "When", "Type", "Source", "Valid"); - - for (i = 0; i < tallies.count; i++) { - struct tm *tm; - char timebuf[80]; - uint16_t status = tallies.records[i].status; - time_t when = tallies.records[i].time; - - tm = localtime(&when); - strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm); - printf("%-19s %-5s %-52.52s %s\n", timebuf, - status & TALLY_STATUS_RHOST ? "RHOST" : (status & TALLY_STATUS_TTY ? "TTY" : "SVC"), - tallies.records[i].source, status & TALLY_STATUS_VALID ? "V":"I"); + if (opts->legacy_output == 0) { + print_in_new_format(opts, &tallies, user); } + else { + print_in_legacy_format(opts, &tallies, user); + } + free(tallies.records); } close(fd); @@ -191,8 +287,9 @@ do_allusers(struct options *opts) { struct dirent **userlist; int rv, i; + const char *dir = get_tally_dir(opts); - rv = scandir(opts->dir, &userlist, NULL, alphasort); + rv = scandir(dir, &userlist, NULL, alphasort); if (rv < 0) { fprintf(stderr, "%s: Error reading tally directory: %m\n", opts->progname); return 2; diff --git a/modules/pam_faillock/pam_faillock.8 b/modules/pam_faillock/pam_faillock.8 index 593b1fec..b4854ff5 100644 --- a/modules/pam_faillock/pam_faillock.8 +++ b/modules/pam_faillock/pam_faillock.8 @@ -1,13 +1,13 @@ '\" t .\" Title: pam_faillock .\" Author: [see the "AUTHOR" section] -.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 06/08/2020 +.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/> +.\" Date: 05/07/2023 .\" Manual: Linux-PAM Manual -.\" Source: Linux-PAM Manual +.\" Source: [FIXME: source] .\" Language: English .\" -.TH "PAM_FAILLOCK" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "PAM_FAILLOCK" "8" "05/07/2023" "[FIXME: source]" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -49,7 +49,7 @@ cause the root account to become blocked, to prevent denial\-of\-service: if you or at the machine console (not telnet/rsh, etc), this is safe\&. .SH "OPTIONS" .PP -\fB{preauth|authfail|authsucc}\fR +{preauth|authfail|authsucc} .RS 4 This argument must be set accordingly to the position of this module instance in the PAM stack\&. .sp @@ -74,7 +74,7 @@ as an account module\&. In such configuration the module must be also called in stage\&. .RE .PP -\fBconf=/path/to/config\-file\fR +conf=/path/to/config\-file .RS 4 Use another configuration file instead of the default /etc/security/faillock\&.conf\&. @@ -145,7 +145,7 @@ option specified in /etc/security/faillock\&.conf or with \fIrequisite\fR -control field leaks an information about existence or non\-existence of an user account in the system because the failures are not recorded for the unknown users\&. The message about the user account being locked is never displayed for non\-existing user accounts allowing the adversary to infer that a particular account is not existing on a system\&. +control field leaks an information about existence or non\-existence of a user account in the system because the failures are not recorded for the unknown users\&. The message about the user account being locked is never displayed for non\-existing user accounts allowing the adversary to infer that a particular account is not existing on a system\&. .SH "EXAMPLES" .PP Here are two possible configuration examples for @@ -244,6 +244,13 @@ session required pam_selinux\&.so open /var/run/faillock/* .RS 4 the files logging the authentication failures for users +.sp +Note: These files will disappear after reboot on systems configured with directory +/var/run/faillock +mounted on virtual memory\&. For persistent storage use the option +\fIdir=\fR +in file +/etc/security/faillock\&.conf\&. .RE .PP /etc/security/faillock\&.conf diff --git a/modules/pam_faillock/pam_faillock.8.xml b/modules/pam_faillock/pam_faillock.8.xml index f43b4015..ce0ae050 100644 --- a/modules/pam_faillock/pam_faillock.8.xml +++ b/modules/pam_faillock/pam_faillock.8.xml @@ -1,8 +1,4 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="pam_faillock"> +<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pam_faillock"> <refmeta> <refentrytitle>pam_faillock</refentrytitle> @@ -10,63 +6,63 @@ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> </refmeta> - <refnamediv id="pam_faillock-name"> + <refnamediv xml:id="pam_faillock-name"> <refname>pam_faillock</refname> <refpurpose>Module counting authentication failures during a specified interval</refpurpose> </refnamediv> <refsynopsisdiv> - <cmdsynopsis id="pam_faillock-cmdsynopsisauth"> + <cmdsynopsis xml:id="pam_faillock-cmdsynopsisauth" sepchar=" "> <command>auth ... pam_faillock.so</command> - <arg choice="req"> + <arg choice="req" rep="norepeat"> preauth|authfail|authsucc </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> conf=<replaceable>/path/to/config-file</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> dir=<replaceable>/path/to/tally-directory</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> even_deny_root </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> deny=<replaceable>n</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> fail_interval=<replaceable>n</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> unlock_time=<replaceable>n</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> root_unlock_time=<replaceable>n</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> admin_group=<replaceable>name</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> audit </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> silent </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> no_log_info </arg> </cmdsynopsis> - <cmdsynopsis id="pam_faillock-cmdsynopsisacct"> + <cmdsynopsis xml:id="pam_faillock-cmdsynopsisacct" sepchar=" "> <command>account ... pam_faillock.so</command> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> dir=<replaceable>/path/to/tally-directory</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> no_log_info </arg> </cmdsynopsis> </refsynopsisdiv> - <refsect1 id="pam_faillock-description"> + <refsect1 xml:id="pam_faillock-description"> <title>DESCRIPTION</title> @@ -78,20 +74,20 @@ </para> <para> Normally, failed attempts to authenticate <emphasis>root</emphasis> will - <emphasis remap='B'>not</emphasis> cause the root account to become + <emphasis remap="B">not</emphasis> cause the root account to become blocked, to prevent denial-of-service: if your users aren't given shell accounts and root may only login via <command>su</command> or at the machine console (not telnet/rsh, etc), this is safe. </para> </refsect1> - <refsect1 id="pam_faillock-options"> + <refsect1 xml:id="pam_faillock-options"> <title>OPTIONS</title> <variablelist> <varlistentry> <term> - <option>{preauth|authfail|authsucc}</option> + {preauth|authfail|authsucc} </term> <listitem> <para> @@ -131,13 +127,20 @@ </varlistentry> <varlistentry> <term> - <option>conf=/path/to/config-file</option> + conf=/path/to/config-file </term> <listitem> - <para> + <para condition="without_vendordir"> Use another configuration file instead of the default <filename>/etc/security/faillock.conf</filename>. </para> + <para condition="with_vendordir"> + Use another configuration file instead of the default + which is to use the file + <filename>/etc/security/faillock.conf</filename> or, + if that one is not present, the file + <filename>%vendordir%/security/faillock.conf</filename>. + </para> </listitem> </varlistentry> </variablelist> @@ -149,7 +152,7 @@ </para> </refsect1> - <refsect1 id="pam_faillock-types"> + <refsect1 xml:id="pam_faillock-types"> <title>MODULE TYPES PROVIDED</title> <para> The <option>auth</option> and <option>account</option> module types are @@ -157,7 +160,7 @@ </para> </refsect1> - <refsect1 id='pam_faillock-return_values'> + <refsect1 xml:id="pam_faillock-return_values"> <title>RETURN VALUES</title> <variablelist> <varlistentry> @@ -215,7 +218,7 @@ </variablelist> </refsect1> - <refsect1 id='pam_faillock-notes'> + <refsect1 xml:id="pam_faillock-notes"> <title>NOTES</title> <para> Configuring options on the module command line is not recommend. The @@ -227,14 +230,14 @@ </para> <para> Individual files with the failure records are created as owned by - the user. This allows <emphasis remap='B'>pam_faillock.so</emphasis> module + the user. This allows <emphasis remap="B">pam_faillock.so</emphasis> module to work correctly when it is called from a screensaver. </para> <para> Note that using the module in <option>preauth</option> without the <option>silent</option> option specified in <filename>/etc/security/faillock.conf</filename> or with <emphasis>requisite</emphasis> control field leaks an information about - existence or non-existence of an user account in the system because + existence or non-existence of a user account in the system because the failures are not recorded for the unknown users. The message about the user account being locked is never displayed for non-existing user accounts allowing the adversary to infer that a particular account @@ -242,7 +245,7 @@ </para> </refsect1> - <refsect1 id='pam_faillock-examples'> + <refsect1 xml:id="pam_faillock-examples"> <title>EXAMPLES</title> <para> Here are two possible configuration examples for <filename>/etc/pam.d/login</filename>. @@ -313,25 +316,40 @@ session required pam_selinux.so open </programlisting> </refsect1> - <refsect1 id="pam_faillock-files"> + <refsect1 xml:id="pam_faillock-files"> <title>FILES</title> <variablelist> <varlistentry> - <term><filename>/var/run/faillock/*</filename></term> + <term>/var/run/faillock/*</term> <listitem> <para>the files logging the authentication failures for users</para> + <para> + Note: These files will disappear after reboot on systems configured with + directory <filename>/var/run/faillock</filename> mounted on virtual memory. + For persistent storage use the option <emphasis>dir=</emphasis> in + file <filename>/etc/security/faillock.conf</filename>. + </para> </listitem> </varlistentry> <varlistentry> - <term><filename>/etc/security/faillock.conf</filename></term> + <term>/etc/security/faillock.conf</term> <listitem> <para>the config file for pam_faillock options</para> </listitem> </varlistentry> + <varlistentry condition="with_vendordir"> + <term>%vendordir%/security/faillock.conf</term> + <listitem> + <para> + the config file for pam_faillock options. It will be used if + <filename>/etc/security/faillock.conf</filename> does not exist. + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> - <refsect1 id='pam_faillock-see_also'> + <refsect1 xml:id="pam_faillock-see_also"> <title>SEE ALSO</title> <para> <citerefentry> @@ -352,11 +370,11 @@ session required pam_selinux.so open </para> </refsect1> - <refsect1 id='pam_faillock-author'> + <refsect1 xml:id="pam_faillock-author"> <title>AUTHOR</title> <para> pam_faillock was written by Tomas Mraz. </para> </refsect1> -</refentry> +</refentry>
\ No newline at end of file diff --git a/modules/pam_faillock/pam_faillock.c b/modules/pam_faillock/pam_faillock.c index f592d0a2..ca1c7035 100644 --- a/modules/pam_faillock/pam_faillock.c +++ b/modules/pam_faillock/pam_faillock.c @@ -38,7 +38,6 @@ #include <stdio.h> #include <string.h> #include <unistd.h> -#include <stdint.h> #include <stdlib.h> #include <errno.h> #include <time.h> @@ -56,77 +55,35 @@ #include "pam_inline.h" #include "faillock.h" +#include "faillock_config.h" #define FAILLOCK_ACTION_PREAUTH 0 #define FAILLOCK_ACTION_AUTHSUCC 1 #define FAILLOCK_ACTION_AUTHFAIL 2 -#define FAILLOCK_FLAG_DENY_ROOT 0x1 -#define FAILLOCK_FLAG_AUDIT 0x2 -#define FAILLOCK_FLAG_SILENT 0x4 -#define FAILLOCK_FLAG_NO_LOG_INFO 0x8 -#define FAILLOCK_FLAG_UNLOCKED 0x10 -#define FAILLOCK_FLAG_LOCAL_ONLY 0x20 - -#define MAX_TIME_INTERVAL 604800 /* 7 days */ -#define FAILLOCK_CONF_MAX_LINELEN 1023 - -#define PATH_PASSWD "/etc/passwd" - -static const char default_faillock_conf[] = FAILLOCK_DEFAULT_CONF; - -struct options { - unsigned int action; - unsigned int flags; - unsigned short deny; - unsigned int fail_interval; - unsigned int unlock_time; - unsigned int root_unlock_time; - char *dir; - const char *user; - char *admin_group; - int failures; - uint64_t latest_time; - uid_t uid; - int is_admin; - uint64_t now; - int fatal_error; -}; - -static int read_config_file( - pam_handle_t *pamh, - struct options *opts, - const char *cfgfile -); - -static void set_conf_opt( - pam_handle_t *pamh, - struct options *opts, - const char *name, - const char *value -); - static int args_parse(pam_handle_t *pamh, int argc, const char **argv, int flags, struct options *opts) { int i; + int config_arg_index = -1; int rv; - const char *conf = default_faillock_conf; + const char *conf = NULL; memset(opts, 0, sizeof(*opts)); - opts->dir = strdup(FAILLOCK_DEFAULT_TALLYDIR); opts->deny = 3; opts->fail_interval = 900; opts->unlock_time = 600; opts->root_unlock_time = MAX_TIME_INTERVAL+1; for (i = 0; i < argc; ++i) { - const char *str; + const char *str = pam_str_skip_prefix(argv[i], "conf="); - if ((str = pam_str_skip_prefix(argv[i], "conf=")) != NULL) + if (str != NULL) { conf = str; + config_arg_index = i; + } } if ((rv = read_config_file(pamh, opts, conf)) != PAM_SUCCESS) { @@ -136,7 +93,10 @@ args_parse(pam_handle_t *pamh, int argc, const char **argv, } for (i = 0; i < argc; ++i) { - if (strcmp(argv[i], "preauth") == 0) { + if (i == config_arg_index) { + continue; + } + else if (strcmp(argv[i], "preauth") == 0) { opts->action = FAILLOCK_ACTION_PREAUTH; } else if (strcmp(argv[i], "authfail") == 0) { @@ -169,221 +129,15 @@ args_parse(pam_handle_t *pamh, int argc, const char **argv, if (flags & PAM_SILENT) opts->flags |= FAILLOCK_FLAG_SILENT; - if (opts->dir == NULL) { - pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); - opts->fatal_error = 1; - } - if (opts->fatal_error) return PAM_BUF_ERR; return PAM_SUCCESS; } -/* parse a single configuration file */ -static int -read_config_file(pam_handle_t *pamh, struct options *opts, const char *cfgfile) -{ - FILE *f; - char linebuf[FAILLOCK_CONF_MAX_LINELEN+1]; - - f = fopen(cfgfile, "r"); - if (f == NULL) { - /* ignore non-existent default config file */ - if (errno == ENOENT && cfgfile == default_faillock_conf) - return PAM_SUCCESS; - return PAM_SERVICE_ERR; - } - - while (fgets(linebuf, sizeof(linebuf), f) != NULL) { - size_t len; - char *ptr; - char *name; - int eq; - - len = strlen(linebuf); - /* len cannot be 0 unless there is a bug in fgets */ - if (len && linebuf[len - 1] != '\n' && !feof(f)) { - (void) fclose(f); - return PAM_SERVICE_ERR; - } - - if ((ptr=strchr(linebuf, '#')) != NULL) { - *ptr = '\0'; - } else { - ptr = linebuf + len; - } - - /* drop terminating whitespace including the \n */ - while (ptr > linebuf) { - if (!isspace(*(ptr-1))) { - *ptr = '\0'; - break; - } - --ptr; - } - - /* skip initial whitespace */ - for (ptr = linebuf; isspace(*ptr); ptr++); - if (*ptr == '\0') - continue; - - /* grab the key name */ - eq = 0; - name = ptr; - while (*ptr != '\0') { - if (isspace(*ptr) || *ptr == '=') { - eq = *ptr == '='; - *ptr = '\0'; - ++ptr; - break; - } - ++ptr; - } - - /* grab the key value */ - while (*ptr != '\0') { - if (*ptr != '=' || eq) { - if (!isspace(*ptr)) { - break; - } - } else { - eq = 1; - } - ++ptr; - } - - /* set the key:value pair on opts */ - set_conf_opt(pamh, opts, name, ptr); - } - - (void)fclose(f); - return PAM_SUCCESS; -} - -static void -set_conf_opt(pam_handle_t *pamh, struct options *opts, const char *name, const char *value) -{ - if (strcmp(name, "dir") == 0) { - if (value[0] != '/') { - pam_syslog(pamh, LOG_ERR, - "Tally directory is not absolute path (%s); keeping default", value); - } else { - free(opts->dir); - opts->dir = strdup(value); - } - } - else if (strcmp(name, "deny") == 0) { - if (sscanf(value, "%hu", &opts->deny) != 1) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for deny argument"); - } - } - else if (strcmp(name, "fail_interval") == 0) { - unsigned int temp; - if (sscanf(value, "%u", &temp) != 1 || - temp > MAX_TIME_INTERVAL) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for fail_interval argument"); - } else { - opts->fail_interval = temp; - } - } - else if (strcmp(name, "unlock_time") == 0) { - unsigned int temp; - - if (strcmp(value, "never") == 0) { - opts->unlock_time = 0; - } - else if (sscanf(value, "%u", &temp) != 1 || - temp > MAX_TIME_INTERVAL) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for unlock_time argument"); - } - else { - opts->unlock_time = temp; - } - } - else if (strcmp(name, "root_unlock_time") == 0) { - unsigned int temp; - - if (strcmp(value, "never") == 0) { - opts->root_unlock_time = 0; - } - else if (sscanf(value, "%u", &temp) != 1 || - temp > MAX_TIME_INTERVAL) { - pam_syslog(pamh, LOG_ERR, - "Bad number supplied for root_unlock_time argument"); - } else { - opts->root_unlock_time = temp; - } - } - else if (strcmp(name, "admin_group") == 0) { - free(opts->admin_group); - opts->admin_group = strdup(value); - if (opts->admin_group == NULL) { - opts->fatal_error = 1; - pam_syslog(pamh, LOG_CRIT, "Error allocating memory: %m"); - } - } - else if (strcmp(name, "even_deny_root") == 0) { - opts->flags |= FAILLOCK_FLAG_DENY_ROOT; - } - else if (strcmp(name, "audit") == 0) { - opts->flags |= FAILLOCK_FLAG_AUDIT; - } - else if (strcmp(name, "silent") == 0) { - opts->flags |= FAILLOCK_FLAG_SILENT; - } - else if (strcmp(name, "no_log_info") == 0) { - opts->flags |= FAILLOCK_FLAG_NO_LOG_INFO; - } - else if (strcmp(name, "local_users_only") == 0) { - opts->flags |= FAILLOCK_FLAG_LOCAL_ONLY; - } - else { - pam_syslog(pamh, LOG_ERR, "Unknown option: %s", name); - } -} - static int check_local_user (pam_handle_t *pamh, const char *user) { - struct passwd pw, *pwp; - char buf[16384]; - int found = 0; - FILE *fp; - int errn; - - fp = fopen(PATH_PASSWD, "r"); - if (fp == NULL) { - pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", - PATH_PASSWD); - return -1; - } - - for (;;) { - errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp); - if (errn == ERANGE) { - pam_syslog(pamh, LOG_WARNING, "%s contains very long lines; corrupted?", - PATH_PASSWD); - break; - } - if (errn != 0) - break; - if (strcmp(pwp->pw_name, user) == 0) { - found = 1; - break; - } - } - - fclose (fp); - - if (errn != 0 && errn != ENOENT) { - pam_syslog(pamh, LOG_ERR, "unable to enumerate local accounts: %m"); - return -1; - } else { - return found; - } + return pam_modutil_check_user_in_passwd(pamh, user, NULL) == PAM_SUCCESS; } static int @@ -433,10 +187,11 @@ check_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies unsigned int i; uint64_t latest_time; int failures; + const char *dir = get_tally_dir(opts); opts->now = time(NULL); - tfd = open_tally(opts->dir, opts->user, opts->uid, 0); + tfd = open_tally(dir, opts->user, opts->uid, 0); *fd = tfd; @@ -510,9 +265,10 @@ static void reset_tally(pam_handle_t *pamh, struct options *opts, int *fd) { int rv; + const char *dir = get_tally_dir(opts); if (*fd == -1) { - *fd = open_tally(opts->dir, opts->user, opts->uid, 1); + *fd = open_tally(dir, opts->user, opts->uid, 1); } else { while ((rv=ftruncate(*fd, 0)) == -1 && errno == EINTR); @@ -531,9 +287,10 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies unsigned int oldest; uint64_t oldtime; const void *source = NULL; + const char *dir = get_tally_dir(opts); if (*fd == -1) { - *fd = open_tally(opts->dir, opts->user, opts->uid, 1); + *fd = open_tally(dir, opts->user, opts->uid, 1); } if (*fd == -1) { if (errno == EACCES) { @@ -617,9 +374,11 @@ write_tally(pam_handle_t *pamh, struct options *opts, struct tally_data *tallies } close(audit_fd); #endif - if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO)) { - pam_syslog(pamh, LOG_INFO, "Consecutive login failures for user %s account temporarily locked", - opts->user); + if (!(opts->flags & FAILLOCK_FLAG_NO_LOG_INFO) && + ((opts->flags & FAILLOCK_FLAG_DENY_ROOT) || (opts->uid != 0))) { + pam_syslog(pamh, LOG_INFO, + "Consecutive login failures for user %s account temporarily locked", + opts->user); } } @@ -647,7 +406,21 @@ faillock_message(pam_handle_t *pamh, struct options *opts) if (left > 0) { left = (left + 59)/60; /* minutes */ - pam_info(pamh, _("(%d minutes left to unlock)"), (int)left); +#if defined HAVE_DNGETTEXT && defined ENABLE_NLS + pam_info( + pamh, + dngettext(PACKAGE, + "(%d minute left to unlock)", + "(%d minutes left to unlock)", + (int)left), + (int)left); +#else + if (left == 1) + pam_info(pamh, _("(%d minute left to unlock)"), (int)left); + else + /* TRANSLATORS: only used if dngettext is not supported. */ + pam_info(pamh, _("(%d minutes left to unlock)"), (int)left); +#endif } } } @@ -685,7 +458,9 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, if (rv != PAM_SUCCESS) goto err; - pam_fail_delay(pamh, 2000000); /* 2 sec delay on failure */ + if (!(opts.flags & FAILLOCK_FLAG_NO_DELAY)) { + pam_fail_delay(pamh, 2000000); /* 2 sec delay on failure */ + } if ((rv=get_pam_user(pamh, &opts)) != PAM_SUCCESS) { goto err; diff --git a/modules/pam_faillock/tst-pam_faillock-retval.c b/modules/pam_faillock/tst-pam_faillock-retval.c new file mode 100644 index 00000000..133026cb --- /dev/null +++ b/modules/pam_faillock/tst-pam_faillock-retval.c @@ -0,0 +1,119 @@ +/* + * Check pam_faillock return values. + */ + +#include "test_assert.h" + +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <security/pam_appl.h> + +#define MODULE_NAME "pam_faillock" +#define TEST_NAME "tst-" MODULE_NAME "-retval" + +static const char service_file[] = TEST_NAME ".service"; +static const char config_filename[] = TEST_NAME ".conf"; +static const char user_name[] = "root"; +static struct pam_conv conv; + +int +main(void) +{ + pam_handle_t *pamh = NULL; + FILE *fp; + char cwd[PATH_MAX]; + + ASSERT_NE(NULL, getcwd(cwd, sizeof(cwd))); + + ASSERT_NE(NULL, fp = fopen(config_filename, "w")); + ASSERT_LT(0, fprintf(fp, + "deny = 2\n" + "unlock_time = 5\n" + "root_unlock_time = 5\n")); + ASSERT_EQ(0, fclose(fp)); + + /* root has access */ + ASSERT_NE(NULL, fp = fopen(service_file, "w")); + ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n" + "auth required %s/../pam_permit/.libs/pam_permit.so\n" + "auth required %s/.libs/%s.so authsucc even_deny_root dir=%s conf=%s\n" + "account required %s/.libs/%s.so dir=%s\n" + "password required %s/.libs/%s.so dir=%s\n" + "session required %s/.libs/%s.so dir=%s\n", + cwd, + cwd, MODULE_NAME, cwd, config_filename, + cwd, MODULE_NAME, cwd, + cwd, MODULE_NAME, cwd, + cwd, MODULE_NAME, cwd)); + + ASSERT_EQ(0, fclose(fp)); + + ASSERT_EQ(PAM_SUCCESS, + pam_start_confdir(service_file, user_name, &conv, ".", &pamh)); + ASSERT_NE(NULL, pamh); + ASSERT_EQ(PAM_SUCCESS, pam_authenticate(pamh, 0)); + ASSERT_EQ(PAM_SUCCESS, pam_setcred(pamh, 0)); + ASSERT_EQ(PAM_SUCCESS, pam_acct_mgmt(pamh, 0)); + ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_chauthtok(pamh, 0)); + ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_open_session(pamh, 0)); + ASSERT_EQ(PAM_MODULE_UNKNOWN, pam_close_session(pamh, 0)); + ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0)); + ASSERT_EQ(0, unlink(service_file)); + pamh = NULL; + + /* root tries to login 2 times without success*/ + ASSERT_NE(NULL, fp = fopen(service_file, "w")); + ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n" + "auth requisite %s/.libs/%s.so dir=%s preauth even_deny_root conf=%s\n" + "auth [success=1 default=bad] %s/../pam_debug/.libs/pam_debug.so auth=perm_denied cred=success\n" + "auth [default=die] %s/.libs/%s.so dir=%s authfail even_deny_root conf=%s\n" + "auth sufficient %s/.libs/%s.so dir=%s authsucc even_deny_root conf=%s\n", + cwd, MODULE_NAME, cwd, config_filename, + cwd, + cwd, MODULE_NAME, cwd, config_filename, + cwd, MODULE_NAME, cwd, config_filename)); + + ASSERT_EQ(0, fclose(fp)); + + ASSERT_EQ(PAM_SUCCESS, + pam_start_confdir(service_file, user_name, &conv, ".", &pamh)); + ASSERT_NE(NULL, pamh); + ASSERT_EQ(PAM_PERM_DENIED, pam_authenticate(pamh, 0)); + ASSERT_EQ(PAM_PERM_DENIED, pam_authenticate(pamh, 0)); + pamh = NULL; + ASSERT_EQ(0, unlink(service_file)); + + /* root is locked for 5 sec*/ + ASSERT_NE(NULL, fp = fopen(service_file, "w")); + ASSERT_LT(0, fprintf(fp, "#%%PAM-1.0\n" + "auth requisite %s/.libs/%s.so dir=%s preauth even_deny_root conf=%s\n" + "auth [success=1 default=bad] %s/../pam_debug/.libs/pam_debug.so auth=success cred=success\n" + "auth [default=die] %s/.libs/%s.so dir=%s authfail even_deny_root conf=%s\n" + "auth sufficient %s/.libs/%s.so dir=%s authsucc even_deny_root conf=%s\n", + cwd, MODULE_NAME, cwd, config_filename, + cwd, + cwd, MODULE_NAME, cwd, config_filename, + cwd, MODULE_NAME, cwd, config_filename)); + + ASSERT_EQ(0, fclose(fp)); + + ASSERT_EQ(PAM_SUCCESS, + pam_start_confdir(service_file, user_name, &conv, ".", &pamh)); + ASSERT_NE(NULL, pamh); + ASSERT_EQ(PAM_AUTH_ERR, pam_authenticate(pamh, 0)); + + /* waiting at least 5 sec --> login is working again*/ + sleep(6); + ASSERT_EQ(PAM_SUCCESS, pam_authenticate(pamh, 0)); + + ASSERT_EQ(PAM_SUCCESS, pam_end(pamh, 0)); + ASSERT_EQ(0, unlink(service_file)); + pamh = NULL; + + ASSERT_EQ(0,unlink(user_name)); + ASSERT_EQ(0,unlink(config_filename)); + + return 0; +} |