summaryrefslogtreecommitdiff
path: root/modules/pam_time
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_time')
-rw-r--r--modules/pam_time/Makefile.am34
-rw-r--r--modules/pam_time/Makefile.in1217
-rw-r--r--modules/pam_time/README35
-rw-r--r--modules/pam_time/README.xml34
-rw-r--r--modules/pam_time/pam_time.8122
-rw-r--r--modules/pam_time/pam_time.8.xml198
-rw-r--r--modules/pam_time/pam_time.c677
-rw-r--r--modules/pam_time/time.conf65
-rw-r--r--modules/pam_time/time.conf.5115
-rw-r--r--modules/pam_time/time.conf.5.xml149
-rwxr-xr-xmodules/pam_time/tst-pam_time2
11 files changed, 2648 insertions, 0 deletions
diff --git a/modules/pam_time/Makefile.am b/modules/pam_time/Makefile.am
new file mode 100644
index 00000000..833d51a6
--- /dev/null
+++ b/modules/pam_time/Makefile.am
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk <kukuk@suse.de>
+#
+
+CLEANFILES = *~
+MAINTAINERCLEANFILES = $(MANS) README
+
+EXTRA_DIST = $(XMLS)
+
+if HAVE_DOC
+dist_man_MANS = time.conf.5 pam_time.8
+endif
+XMLS = README.xml time.conf.5.xml pam_time.8.xml
+dist_check_SCRIPTS = tst-pam_time
+TESTS = $(dist_check_SCRIPTS)
+
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ -DPAM_TIME_CONF=\"$(SCONFIGDIR)/time.conf\" $(WARN_CFLAGS)
+AM_LDFLAGS = -no-undefined -avoid-version -module
+if HAVE_VERSIONING
+ AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
+endif
+pam_time_la_LIBADD = $(top_builddir)/libpam/libpam.la
+
+securelib_LTLIBRARIES = pam_time.la
+dist_secureconf_DATA = time.conf
+
+if ENABLE_REGENERATE_MAN
+dist_noinst_DATA = README
+-include $(top_srcdir)/Make.xml.rules
+endif
diff --git a/modules/pam_time/Makefile.in b/modules/pam_time/Makefile.in
new file mode 100644
index 00000000..331bcc31
--- /dev/null
+++ b/modules/pam_time/Makefile.in
@@ -0,0 +1,1217 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# 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,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Copyright (c) 2005, 2006, 2009 Thorsten Kukuk <kukuk@suse.de>
+#
+
+
+VPATH = @srcdir@
+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 \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map
+subdir = modules/pam_time
+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 \
+ $(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/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
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \
+ $(am__dist_noinst_DATA_DIST) $(dist_secureconf_DATA) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(man5dir)" \
+ "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(secureconfdir)"
+LTLIBRARIES = $(securelib_LTLIBRARIES)
+pam_time_la_DEPENDENCIES = $(top_builddir)/libpam/libpam.la
+pam_time_la_SOURCES = pam_time.c
+pam_time_la_OBJECTS = pam_time.lo
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/pam_time.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+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_time.c
+DIST_SOURCES = pam_time.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(dist_man_MANS)
+am__dist_noinst_DATA_DIST = README
+DATA = $(dist_noinst_DATA) $(dist_secureconf_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+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@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BROWSER = @BROWSER@
+BUILD_CFLAGS = @BUILD_CFLAGS@
+BUILD_CPPFLAGS = @BUILD_CPPFLAGS@
+BUILD_LDFLAGS = @BUILD_LDFLAGS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+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@
+FO2PDF = @FO2PDF@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBAUDIT = @LIBAUDIT@
+LIBCRACK = @LIBCRACK@
+LIBCRYPT = @LIBCRYPT@
+LIBDB = @LIBDB@
+LIBDL = @LIBDL@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBPRELUDE_CFLAGS = @LIBPRELUDE_CFLAGS@
+LIBPRELUDE_CONFIG = @LIBPRELUDE_CONFIG@
+LIBPRELUDE_CONFIG_PREFIX = @LIBPRELUDE_CONFIG_PREFIX@
+LIBPRELUDE_LDFLAGS = @LIBPRELUDE_LDFLAGS@
+LIBPRELUDE_LIBS = @LIBPRELUDE_LIBS@
+LIBPRELUDE_PREFIX = @LIBPRELUDE_PREFIX@
+LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@
+LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+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@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NIS_CFLAGS = @NIS_CFLAGS@
+NIS_LIBS = @NIS_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSL_CFLAGS = @NSL_CFLAGS@
+NSL_LIBS = @NSL_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SCONFIGDIR = @SCONFIGDIR@
+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@
+XMLCATALOG = @XMLCATALOG@
+XMLLINT = @XMLLINT@
+XML_CATALOG_FILE = @XML_CATALOG_FILE@
+XSLTPROC = @XSLTPROC@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libc_cv_fpie = @libc_cv_fpie@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+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@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *~
+MAINTAINERCLEANFILES = $(MANS) README
+EXTRA_DIST = $(XMLS)
+@HAVE_DOC_TRUE@dist_man_MANS = time.conf.5 pam_time.8
+XMLS = README.xml time.conf.5.xml pam_time.8.xml
+dist_check_SCRIPTS = tst-pam_time
+TESTS = $(dist_check_SCRIPTS)
+securelibdir = $(SECUREDIR)
+secureconfdir = $(SCONFIGDIR)
+AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
+ -DPAM_TIME_CONF=\"$(SCONFIGDIR)/time.conf\" $(WARN_CFLAGS)
+
+AM_LDFLAGS = -no-undefined -avoid-version -module $(am__append_1)
+pam_time_la_LIBADD = $(top_builddir)/libpam/libpam.la
+securelib_LTLIBRARIES = pam_time.la
+dist_secureconf_DATA = time.conf
+@ENABLE_REGENERATE_MAN_TRUE@dist_noinst_DATA = README
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/pam_time/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu modules/pam_time/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__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)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(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_time.la: $(pam_time_la_OBJECTS) $(pam_time_la_DEPENDENCIES) $(EXTRA_pam_time_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) -rpath $(securelibdir) $(pam_time_la_OBJECTS) $(pam_time_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_time.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 -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 -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man5: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man5dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.5[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man5:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man5dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.5[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+install-man8: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; 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,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+install-dist_secureconfDATA: $(dist_secureconf_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_secureconf_DATA)'; test -n "$(secureconfdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(secureconfdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(secureconfdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(secureconfdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(secureconfdir)" || exit $$?; \
+ done
+
+uninstall-dist_secureconfDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_secureconf_DATA)'; test -n "$(secureconfdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(secureconfdir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+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)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ 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)
+ @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 \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+tst-pam_time.log: tst-pam_time
+ @p='tst-pam_time'; \
+ b='tst-pam_time'; \
+ $(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); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@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: $(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)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(dist_check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(MANS) $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(securelibdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(secureconfdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-securelibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/pam_time.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_secureconfDATA install-man \
+ install-securelibLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man5 install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/pam_time.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dist_secureconfDATA uninstall-man \
+ uninstall-securelibLTLIBRARIES
+
+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-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 \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-man5 install-man8 install-pdf install-pdf-am \
+ install-ps install-ps-am install-securelibLTLIBRARIES \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am recheck tags tags-am uninstall \
+ uninstall-am uninstall-dist_secureconfDATA uninstall-man \
+ uninstall-man5 uninstall-man8 uninstall-securelibLTLIBRARIES
+
+.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.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/modules/pam_time/README b/modules/pam_time/README
new file mode 100644
index 00000000..9b20847c
--- /dev/null
+++ b/modules/pam_time/README
@@ -0,0 +1,35 @@
+pam_time — PAM module for time control access
+
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+DESCRIPTION
+
+The pam_time PAM module does not authenticate the user, but instead it
+restricts access to a system and or specific applications at various times of
+the day and on specific days or over various terminal lines. This module can be
+configured to deny access to (individual) users based on their name, the time
+of day, the day of week, the service they are applying for and their terminal
+from which they are making their request.
+
+By default rules for time/port access are taken from config file /etc/security/
+time.conf. An alternative file can be specified with the conffile option.
+
+If Linux PAM is compiled with audit support the module will report when it
+denies access.
+
+EXAMPLES
+
+These are some example lines which might be specified in /etc/security/
+time.conf.
+
+All users except for root are denied access to console-login at all times:
+
+login ; tty* & !ttyp* ; !root ; !Al0000-2400
+
+
+Games (configured to use PAM) are only to be accessed out of working hours.
+This rule does not apply to the user waster:
+
+games ; * ; !waster ; Wd0000-2400 | Wk1800-0800
+
+
diff --git a/modules/pam_time/README.xml b/modules/pam_time/README.xml
new file mode 100644
index 00000000..6c11eec1
--- /dev/null
+++ b/modules/pam_time/README.xml
@@ -0,0 +1,34 @@
+<?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 pamtime SYSTEM "pam_time.8.xml">
+-->
+<!--
+<!ENTITY timeconf SYSTEM "time.conf.5.xml">
+-->
+]>
+
+<article>
+
+ <articleinfo>
+
+ <title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_time.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_time-name"]/*)'/>
+ </title>
+
+ </articleinfo>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="pam_time.8.xml" xpointer='xpointer(//refsect1[@id = "pam_time-description"]/*)'/>
+ </section>
+
+ <section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="time.conf.5.xml" xpointer='xpointer(//refsect1[@id = "time.conf-examples"]/*)'/>
+ </section>
+
+</article>
diff --git a/modules/pam_time/pam_time.8 b/modules/pam_time/pam_time.8
new file mode 100644
index 00000000..0d7eca96
--- /dev/null
+++ b/modules/pam_time/pam_time.8
@@ -0,0 +1,122 @@
+'\" t
+.\" Title: pam_time
+.\" Author: [see the "AUTHOR" section]
+.\" 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_TIME" "8" "06/08/2020" "Linux-PAM Manual" "Linux-PAM Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+pam_time \- PAM module for time control access
+.SH "SYNOPSIS"
+.HP \w'\fBpam_time\&.so\fR\ 'u
+\fBpam_time\&.so\fR [conffile=conf\-file] [debug] [noaudit]
+.SH "DESCRIPTION"
+.PP
+The pam_time PAM module does not authenticate the user, but instead it restricts access to a system and or specific applications at various times of the day and on specific days or over various terminal lines\&. This module can be configured to deny access to (individual) users based on their name, the time of day, the day of week, the service they are applying for and their terminal from which they are making their request\&.
+.PP
+By default rules for time/port access are taken from config file
+/etc/security/time\&.conf\&. An alternative file can be specified with the
+\fIconffile\fR
+option\&.
+.PP
+If Linux PAM is compiled with audit support the module will report when it denies access\&.
+.SH "OPTIONS"
+.PP
+\fBconffile=/path/to/time\&.conf\fR
+.RS 4
+Indicate an alternative time\&.conf style configuration file to override the default\&.
+.RE
+.PP
+\fBdebug\fR
+.RS 4
+Some debug information is printed with
+\fBsyslog\fR(3)\&.
+.RE
+.PP
+\fBnoaudit\fR
+.RS 4
+Do not report logins at disallowed time to the audit subsystem\&.
+.RE
+.SH "MODULE TYPES PROVIDED"
+.PP
+Only the
+\fBaccount\fR
+type is provided\&.
+.SH "RETURN VALUES"
+.PP
+PAM_SUCCESS
+.RS 4
+Access was granted\&.
+.RE
+.PP
+PAM_ABORT
+.RS 4
+Not all relevant data could be gotten\&.
+.RE
+.PP
+PAM_BUF_ERR
+.RS 4
+Memory buffer error\&.
+.RE
+.PP
+PAM_PERM_DENIED
+.RS 4
+Access was not granted\&.
+.RE
+.PP
+PAM_USER_UNKNOWN
+.RS 4
+The user is not known to the system\&.
+.RE
+.SH "FILES"
+.PP
+/etc/security/time\&.conf
+.RS 4
+Default configuration file
+.RE
+.SH "EXAMPLES"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+#%PAM\-1\&.0
+#
+# apply pam_time accounting to login requests
+#
+login account required pam_time\&.so
+
+.fi
+.if n \{\
+.RE
+.\}
+.SH "SEE ALSO"
+.PP
+\fBtime.conf\fR(5),
+\fBpam.d\fR(5),
+\fBpam\fR(8)\&.
+.SH "AUTHOR"
+.PP
+pam_time was written by Andrew G\&. Morgan <morgan@kernel\&.org>\&.
diff --git a/modules/pam_time/pam_time.8.xml b/modules/pam_time/pam_time.8.xml
new file mode 100644
index 00000000..4708220c
--- /dev/null
+++ b/modules/pam_time/pam_time.8.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+
+<refentry id='pam_time'>
+
+ <refmeta>
+ <refentrytitle>pam_time</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class='setdesc'>Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv id='pam_time-name'>
+ <refname>pam_time</refname>
+ <refpurpose>
+ PAM module for time control access
+ </refpurpose>
+ </refnamediv>
+
+<!-- body begins here -->
+
+ <refsynopsisdiv>
+ <cmdsynopsis id="pam_time-cmdsynopsis">
+ <command>pam_time.so</command>
+ <arg choice="opt">
+ conffile=conf-file
+ </arg>
+ <arg choice="opt">
+ debug
+ </arg>
+ <arg choice="opt">
+ noaudit
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+
+ <refsect1 id="pam_time-description">
+ <title>DESCRIPTION</title>
+ <para>
+ The pam_time PAM module does not authenticate the user, but instead
+ it restricts access to a system and or specific applications at
+ various times of the day and on specific days or over various
+ terminal lines. This module can be configured to deny access to
+ (individual) users based on their name, the time of day, the day of
+ week, the service they are applying for and their terminal from which
+ they are making their request.
+ </para>
+ <para>
+ By default rules for time/port access are taken from config file
+ <filename>/etc/security/time.conf</filename>.
+ An alternative file can be specified with the <emphasis>conffile</emphasis> option.
+ </para>
+ <para>
+ If Linux PAM is compiled with audit support the module will report
+ when it denies access.
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_time-options">
+ <title>OPTIONS</title>
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>conffile=/path/to/time.conf</option>
+ </term>
+ <listitem>
+ <para>
+ Indicate an alternative time.conf style configuration file to override the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>debug</option>
+ </term>
+ <listitem>
+ <para>
+ Some debug information is printed with
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>noaudit</option>
+ </term>
+ <listitem>
+ <para>
+ Do not report logins at disallowed time to the audit subsystem.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="pam_time-types">
+ <title>MODULE TYPES PROVIDED</title>
+ <para>
+ Only the <option>account</option> type is provided.
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_time-return_values">
+ <title>RETURN VALUES</title>
+ <variablelist>
+ <varlistentry>
+ <term>PAM_SUCCESS</term>
+ <listitem>
+ <para>
+ Access was granted.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_ABORT</term>
+ <listitem>
+ <para>
+ Not all relevant data could be gotten.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_BUF_ERR</term>
+ <listitem>
+ <para>
+ Memory buffer error.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_PERM_DENIED</term>
+ <listitem>
+ <para>
+ Access was not granted.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>PAM_USER_UNKNOWN</term>
+ <listitem>
+ <para>
+ The user is not known to the system.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="pam_time-files">
+ <title>FILES</title>
+ <variablelist>
+ <varlistentry>
+ <term><filename>/etc/security/time.conf</filename></term>
+ <listitem>
+ <para>Default configuration file</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id='pam_time-examples'>
+ <title>EXAMPLES</title>
+ <programlisting>
+#%PAM-1.0
+#
+# apply pam_time accounting to login requests
+#
+login account required pam_time.so
+ </programlisting>
+ </refsect1>
+
+ <refsect1 id="pam_time-see_also">
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>time.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+
+ <refsect1 id="pam_time-authors">
+ <title>AUTHOR</title>
+ <para>
+ pam_time was written by Andrew G. Morgan &lt;morgan@kernel.org&gt;.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/modules/pam_time/pam_time.c b/modules/pam_time/pam_time.c
new file mode 100644
index 00000000..089ae22d
--- /dev/null
+++ b/modules/pam_time/pam_time.c
@@ -0,0 +1,677 @@
+/*
+ * pam_time module
+ *
+ * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/6/22
+ * (File syntax and much other inspiration from the shadow package
+ * shadow-960129)
+ * Field parsing rewritten by Tomas Mraz <tm@t8m.info>
+ */
+
+#include "config.h"
+
+#include <sys/file.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <time.h>
+#include <syslog.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <netdb.h>
+
+#include <security/_pam_macros.h>
+#include <security/pam_modules.h>
+#include <security/pam_ext.h>
+#include <security/pam_modutil.h>
+#include "pam_inline.h"
+
+#ifdef HAVE_LIBAUDIT
+#include <libaudit.h>
+#endif
+
+#define PAM_TIME_BUFLEN 1000
+#define FIELD_SEPARATOR ';' /* this is new as of .02 */
+
+#define PAM_DEBUG_ARG 0x0001
+#define PAM_NO_AUDIT 0x0002
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+typedef enum { AND, OR } operator;
+
+static int
+_pam_parse (const pam_handle_t *pamh, int argc, const char **argv, const char **conffile)
+{
+ int ctrl = 0;
+
+ *conffile = PAM_TIME_CONF;
+ /* step through arguments */
+ for (; argc-- > 0; ++argv) {
+ const char *str;
+
+ /* generic options */
+
+ if (!strcmp(*argv, "debug")) {
+ ctrl |= PAM_DEBUG_ARG;
+ } else if (!strcmp(*argv, "noaudit")) {
+ ctrl |= PAM_NO_AUDIT;
+ } else if ((str = pam_str_skip_prefix(*argv, "conffile=")) != NULL) {
+ if (str[0] == '\0') {
+ pam_syslog(pamh, LOG_ERR,
+ "conffile= specification missing argument - ignored");
+ } else {
+ *conffile = str;
+ D(("new Configuration File: %s", *conffile));
+ }
+ } else {
+ pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
+ }
+ }
+
+ return ctrl;
+}
+
+/* --- static functions for checking whether the user should be let in --- */
+
+static char *
+shift_buf(char *mem, int from)
+{
+ char *start = mem;
+ while ((*mem = mem[from]) != '\0')
+ ++mem;
+ memset(mem, '\0', PAM_TIME_BUFLEN - (mem - start));
+ return mem;
+}
+
+static void
+trim_spaces(char *buf, char *from)
+{
+ while (from > buf) {
+ --from;
+ if (*from == ' ')
+ *from = '\0';
+ else
+ break;
+ }
+}
+
+#define STATE_NL 0 /* new line starting */
+#define STATE_COMMENT 1 /* inside comment */
+#define STATE_FIELD 2 /* field following */
+#define STATE_EOF 3 /* end of file or error */
+
+static int
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state, const char *file)
+{
+ char *to;
+ char *src;
+ int i;
+ char c;
+ int onspace;
+
+ /* is buf set ? */
+ if (! *buf) {
+ *buf = (char *) calloc(1, PAM_TIME_BUFLEN+1);
+ if (! *buf) {
+ pam_syslog(pamh, LOG_CRIT, "out of memory");
+ D(("no memory"));
+ *state = STATE_EOF;
+ return -1;
+ }
+ *from = 0;
+ *state = STATE_NL;
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", file);
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
+ }
+ }
+
+
+ if (*from > 0)
+ to = shift_buf(*buf, *from);
+ else
+ to = *buf;
+
+ while (fd != -1 && to - *buf < PAM_TIME_BUFLEN) {
+ i = pam_modutil_read(fd, to, PAM_TIME_BUFLEN - (to - *buf));
+ if (i < 0) {
+ pam_syslog(pamh, LOG_ERR, "error reading %s: %m", file);
+ close(fd);
+ memset(*buf, 0, PAM_TIME_BUFLEN);
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
+ } else if (!i) {
+ close(fd);
+ fd = -1; /* end of file reached */
+ }
+
+ to += i;
+ }
+
+ if (to == *buf) {
+ /* nothing previously in buf, nothing read */
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
+ }
+
+ memset(to, '\0', PAM_TIME_BUFLEN - (to - *buf));
+
+ to = *buf;
+ onspace = 1; /* delete any leading spaces */
+
+ for (src = to; (c=*src) != '\0'; ++src) {
+ if (*state == STATE_COMMENT && c != '\n') {
+ continue;
+ }
+
+ switch (c) {
+ case '\n':
+ *state = STATE_NL;
+ *to = '\0';
+ *from = (src - *buf) + 1;
+ trim_spaces(*buf, to);
+ return fd;
+
+ case '\t':
+ case ' ':
+ if (!onspace) {
+ onspace = 1;
+ *to++ = ' ';
+ }
+ break;
+
+ case '!':
+ onspace = 1; /* ignore following spaces */
+ *to++ = '!';
+ break;
+
+ case '#':
+ *state = STATE_COMMENT;
+ break;
+
+ case FIELD_SEPARATOR:
+ *state = STATE_FIELD;
+ *to = '\0';
+ *from = (src - *buf) + 1;
+ trim_spaces(*buf, to);
+ return fd;
+
+ case '\\':
+ if (src[1] == '\n') {
+ ++src; /* skip it */
+ break;
+ }
+ /* fallthrough */
+ default:
+ *to++ = c;
+ onspace = 0;
+ }
+ if (src > to)
+ *src = '\0'; /* clearing */
+ }
+
+ if (*state != STATE_COMMENT) {
+ *state = STATE_COMMENT;
+ pam_syslog(pamh, LOG_ERR, "field too long - ignored");
+ **buf = '\0';
+ } else {
+ *to = '\0';
+ trim_spaces(*buf, to);
+ }
+
+ *from = 0;
+ return fd;
+}
+
+/* read a member from a field */
+
+static int
+logic_member(const char *string, int *at)
+{
+ int c,to;
+ int done=0;
+ int token=0;
+
+ to=*at;
+ do {
+ c = string[to++];
+
+ switch (c) {
+
+ case '\0':
+ --to;
+ done = 1;
+ break;
+
+ case '&':
+ case '|':
+ case '!':
+ if (token) {
+ --to;
+ }
+ done = 1;
+ break;
+
+ default:
+ if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
+ || c == '-' || c == '.' || c == '/' || c == ':') {
+ token = 1;
+ } else if (token) {
+ --to;
+ done = 1;
+ } else {
+ ++*at;
+ }
+ }
+ } while (!done);
+
+ return to - *at;
+}
+
+typedef enum { VAL, OP } expect;
+
+static int
+logic_field(pam_handle_t *pamh, const void *me, const char *x, int rule,
+ int (*agrees)(pam_handle_t *pamh,
+ const void *, const char *, int, int))
+{
+ int left=FALSE, right, not=FALSE;
+ operator oper=OR;
+ int at=0, l;
+ expect next=VAL;
+
+ while ((l = logic_member(x,&at))) {
+ int c = x[at];
+
+ if (next == VAL) {
+ if (c == '!')
+ not = !not;
+ else if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
+ || c == '-' || c == '.' || c == '/' || c == ':') {
+ right = not ^ agrees(pamh, me, x+at, l, rule);
+ if (oper == AND)
+ left &= right;
+ else
+ left |= right;
+ next = OP;
+ } else {
+ pam_syslog(pamh, LOG_ERR,
+ "garbled syntax; expected name (rule #%d)",
+ rule);
+ return FALSE;
+ }
+ } else { /* OP */
+ switch (c) {
+ case '&':
+ oper = AND;
+ break;
+ case '|':
+ oper = OR;
+ break;
+ default:
+ pam_syslog(pamh, LOG_ERR,
+ "garbled syntax; expected & or | (rule #%d)",
+ rule);
+ D(("%c at %d",c,at));
+ return FALSE;
+ }
+ next = VAL;
+ not = FALSE;
+ }
+ at += l;
+ }
+
+ return left;
+}
+
+static int
+is_same(pam_handle_t *pamh UNUSED, const void *A, const char *b,
+ int len, int rule UNUSED)
+{
+ int i;
+ const char *a;
+
+ a = A;
+ for (i=0; len > 0; ++i, --len) {
+ if (b[i] != a[i]) {
+ if (b[i++] == '*') {
+ return (!--len || !strncmp(b+i,a+strlen(a)-len,len));
+ } else
+ return FALSE;
+ }
+ }
+
+ /* Ok, we know that b is a substring from A and does not contain
+ wildcards, but now the length of both strings must be the same,
+ too. In this case it means, a[i] has to be the end of the string. */
+ if (a[i] != '\0')
+ return FALSE;
+
+ return ( !len );
+}
+
+typedef struct {
+ int day; /* array of 7 bits, one set for today */
+ int minute; /* integer, hour*100+minute for now */
+} TIME;
+
+static struct day {
+ const char *d;
+ int bit;
+} const days[11] = {
+ { "su", 01 },
+ { "mo", 02 },
+ { "tu", 04 },
+ { "we", 010 },
+ { "th", 020 },
+ { "fr", 040 },
+ { "sa", 0100 },
+ { "wk", 076 },
+ { "wd", 0101 },
+ { "al", 0177 },
+ { NULL, 0 }
+};
+
+static TIME
+time_now(void)
+{
+ struct tm *local;
+ time_t the_time;
+ TIME this;
+
+ the_time = time((time_t *)0); /* get the current time */
+ local = localtime(&the_time);
+ this.day = days[local->tm_wday].bit;
+ this.minute = local->tm_hour*100 + local->tm_min;
+
+ D(("day: 0%o, time: %.4d", this.day, this.minute));
+ return this;
+}
+
+/* take the current date and see if the range "date" passes it */
+static int
+check_time(pam_handle_t *pamh, const void *AT, const char *times,
+ int len, int rule)
+{
+ int not,pass;
+ int marked_day, time_start, time_end;
+ const TIME *at;
+ int i,j=0;
+
+ at = AT;
+ D(("chcking: 0%o/%.4d vs. %s", at->day, at->minute, times));
+
+ if (times == NULL) {
+ /* this should not happen */
+ pam_syslog(pamh, LOG_CRIT,
+ "internal error in file %s at line %d",
+ __FILE__, __LINE__);
+ return FALSE;
+ }
+
+ if (times[j] == '!') {
+ ++j;
+ not = TRUE;
+ } else {
+ not = FALSE;
+ }
+
+ for (marked_day = 0; len > 0 && isalpha(times[j]); --len) {
+ int this_day=-1;
+
+ D(("%c%c ?", times[j], times[j+1]));
+ for (i=0; days[i].d != NULL; ++i) {
+ if (tolower(times[j]) == days[i].d[0]
+ && tolower(times[j+1]) == days[i].d[1] ) {
+ this_day = days[i].bit;
+ break;
+ }
+ }
+ j += 2;
+ if (this_day == -1) {
+ pam_syslog(pamh, LOG_ERR, "bad day specified (rule #%d)", rule);
+ return FALSE;
+ }
+ marked_day ^= this_day;
+ }
+ if (marked_day == 0) {
+ pam_syslog(pamh, LOG_ERR, "no day specified");
+ return FALSE;
+ }
+ D(("day range = 0%o", marked_day));
+
+ time_start = 0;
+ for (i=0; len > 0 && i < 4 && isdigit(times[i+j]); ++i, --len) {
+ time_start *= 10;
+ time_start += times[i+j]-'0'; /* is this portable? */
+ }
+ j += i;
+
+ if (times[j] == '-') {
+ time_end = 0;
+ for (i=1; len > 0 && i < 5 && isdigit(times[i+j]); ++i, --len) {
+ time_end *= 10;
+ time_end += times[i+j]-'0'; /* is this portable */
+ }
+ j += i;
+ } else
+ time_end = -1;
+
+ D(("i=%d, time_end=%d, times[j]='%c'", i, time_end, times[j]));
+ if (i != 5 || time_end == -1) {
+ pam_syslog(pamh, LOG_ERR, "no/bad times specified (rule #%d)", rule);
+ return TRUE;
+ }
+ D(("times(%d to %d)", time_start,time_end));
+ D(("marked_day = 0%o", marked_day));
+
+ /* compare with the actual time now */
+
+ pass = FALSE;
+ if (time_start < time_end) { /* start < end ? --> same day */
+ if ((at->day & marked_day) && (at->minute >= time_start)
+ && (at->minute < time_end)) {
+ D(("time is listed"));
+ pass = TRUE;
+ }
+ } else { /* spans two days */
+ if ((at->day & marked_day) && (at->minute >= time_start)) {
+ D(("caught on first day"));
+ pass = TRUE;
+ } else {
+ marked_day <<= 1;
+ marked_day |= (marked_day & 0200) ? 1:0;
+ D(("next day = 0%o", marked_day));
+ if ((at->day & marked_day) && (at->minute <= time_end)) {
+ D(("caught on second day"));
+ pass = TRUE;
+ }
+ }
+ }
+
+ return (not ^ pass);
+}
+
+static int
+check_account(pam_handle_t *pamh, const char *service,
+ const char *tty, const char *user, const char *file)
+{
+ int from=0, state=STATE_NL, fd=-1;
+ char *buffer=NULL;
+ int count=0;
+ TIME here_and_now;
+ int retval=PAM_SUCCESS;
+
+ here_and_now = time_now(); /* find current time */
+ do {
+ int good=TRUE,intime;
+
+ /* here we get the service name field */
+
+ fd = read_field(pamh, fd, &buffer, &from, &state, file);
+ if (!buffer || !buffer[0]) {
+ /* empty line .. ? */
+ continue;
+ }
+ ++count;
+
+ if (state != STATE_FIELD) {
+ pam_syslog(pamh, LOG_ERR,
+ "%s: malformed rule #%d", file, count);
+ continue;
+ }
+
+ good = logic_field(pamh, service, buffer, count, is_same);
+ D(("with service: %s", good ? "passes":"fails" ));
+
+ /* here we get the terminal name field */
+
+ fd = read_field(pamh, fd, &buffer, &from, &state, file);
+ if (state != STATE_FIELD) {
+ pam_syslog(pamh, LOG_ERR,
+ "%s: malformed rule #%d", file, count);
+ continue;
+ }
+ good &= logic_field(pamh, tty, buffer, count, is_same);
+ D(("with tty: %s", good ? "passes":"fails" ));
+
+ /* here we get the username field */
+
+ fd = read_field(pamh, fd, &buffer, &from, &state, file);
+ if (state != STATE_FIELD) {
+ pam_syslog(pamh, LOG_ERR,
+ "%s: malformed rule #%d", file, count);
+ continue;
+ }
+ /* If buffer starts with @, we are using netgroups */
+ if (buffer[0] == '@')
+#ifdef HAVE_INNETGR
+ good &= innetgr (&buffer[1], NULL, user, NULL);
+#else
+ pam_syslog (pamh, LOG_ERR, "pam_time does not have netgroup support");
+#endif
+ else
+ good &= logic_field(pamh, user, buffer, count, is_same);
+ D(("with user: %s", good ? "passes":"fails" ));
+
+ /* here we get the time field */
+
+ fd = read_field(pamh, fd, &buffer, &from, &state, file);
+ if (state == STATE_FIELD) {
+ pam_syslog(pamh, LOG_ERR,
+ "%s: poorly terminated rule #%d", file, count);
+ continue;
+ }
+
+ intime = logic_field(pamh, &here_and_now, buffer, count, check_time);
+ D(("with time: %s", intime ? "passes":"fails" ));
+
+ if (good && !intime) {
+ /*
+ * for security parse whole file.. also need to ensure
+ * that the buffer is free()'d and the file is closed.
+ */
+ retval = PAM_PERM_DENIED;
+ } else {
+ D(("rule passed"));
+ }
+ } while (state != STATE_EOF);
+
+ return retval;
+}
+
+/* --- public account management functions --- */
+
+int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
+ int argc, const char **argv)
+{
+ const void *service=NULL, *void_tty=NULL;
+ const char *tty;
+ const char *user=NULL;
+ const char *conf_file = NULL;
+ int ctrl;
+ int rv;
+
+ ctrl = _pam_parse(pamh, argc, argv, &conf_file);
+
+ if (ctrl & PAM_DEBUG_ARG) {
+ pam_syslog(pamh, LOG_DEBUG, "conffile=%s", conf_file);
+ }
+
+ /* set service name */
+
+ if (pam_get_item(pamh, PAM_SERVICE, &service)
+ != PAM_SUCCESS || service == NULL) {
+ pam_syslog(pamh, LOG_ERR, "cannot find the current service name");
+ return PAM_ABORT;
+ }
+
+ /* set username */
+
+ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || *user == '\0') {
+ pam_syslog(pamh, LOG_NOTICE, "cannot determine user name");
+ return PAM_USER_UNKNOWN;
+ }
+
+ /* set tty name */
+
+ if (pam_get_item(pamh, PAM_TTY, &void_tty) != PAM_SUCCESS
+ || void_tty == NULL) {
+ D(("PAM_TTY not set, probing stdin"));
+ tty = ttyname(STDIN_FILENO);
+ if (tty == NULL) {
+ tty = "";
+ }
+ if (pam_set_item(pamh, PAM_TTY, tty) != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR, "couldn't set tty name");
+ return PAM_ABORT;
+ }
+ }
+ else
+ tty = void_tty;
+
+ if (tty[0] == '/') { /* full path */
+ const char *t;
+ tty++;
+ if ((t = strchr(tty, '/')) != NULL) {
+ tty = t + 1;
+ }
+ }
+
+ /* good, now we have the service name, the user and the terminal name */
+
+ D(("service=%s", service));
+ D(("user=%s", user));
+ D(("tty=%s", tty));
+
+ rv = check_account(pamh, service, tty, user, conf_file);
+ if (rv != PAM_SUCCESS) {
+#ifdef HAVE_LIBAUDIT
+ if (!(ctrl & PAM_NO_AUDIT)) {
+ pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_TIME,
+ "pam_time", rv); /* ignore return value as we fail anyway */
+ }
+#endif
+ if (ctrl & PAM_DEBUG_ARG) {
+ pam_syslog(pamh, LOG_DEBUG, "user %s rejected", user);
+ }
+ }
+ return rv;
+}
+
+/* end of module definition */
diff --git a/modules/pam_time/time.conf b/modules/pam_time/time.conf
new file mode 100644
index 00000000..68d2dadc
--- /dev/null
+++ b/modules/pam_time/time.conf
@@ -0,0 +1,65 @@
+# this is an example configuration file for the pam_time module. Its syntax
+# was initially based heavily on that of the shadow package (shadow-960129).
+#
+# the syntax of the lines is as follows:
+#
+# services;ttys;users;times
+#
+# white space is ignored and lines maybe extended with '\\n' (escaped
+# newlines). As should be clear from reading these comments,
+# text following a '#' is ignored to the end of the line.
+#
+# the combination of individual users/terminals etc is a logic list
+# namely individual tokens that are optionally prefixed with '!' (logical
+# not) and separated with '&' (logical and) and '|' (logical or).
+#
+# services
+# is a logic list of PAM service names that the rule applies to.
+#
+# ttys
+# is a logic list of terminal names that this rule applies to.
+#
+# users
+# is a logic list of users or a netgroup of users to whom this
+# rule applies.
+#
+# NB. For these items the simple wildcard '*' may be used only once.
+#
+# times
+# the format here is a logic list of day/time-range
+# entries the days are specified by a sequence of two character
+# entries, MoTuSa for example is Monday Tuesday and Saturday. Note
+# that repeated days are unset MoMo = no day, and MoWk = all weekdays
+# bar Monday. The two character combinations accepted are
+#
+# Mo Tu We Th Fr Sa Su Wk Wd Al
+#
+# the last two being week-end days and all 7 days of the week
+# respectively. As a final example, AlFr means all days except Friday.
+#
+# each day/time-range can be prefixed with a '!' to indicate "anything
+# but"
+#
+# The time-range part is two 24-hour times HHMM separated by a hyphen
+# indicating the start and finish time (if the finish time is smaller
+# than the start time it is deemed to apply on the following day).
+#
+# for a rule to be active, ALL of service+ttys+users must be satisfied
+# by the applying process.
+#
+
+#
+# Here is a simple example: running blank on tty* (any ttyXXX device),
+# the users 'you' and 'me' are denied service all of the time
+#
+
+#blank;tty* & !ttyp*;you|me;!Al0000-2400
+
+# Another silly example, user 'root' is denied xsh access
+# from pseudo terminals at the weekend and on mondays.
+
+#xsh;ttyp*;root;!WdMo0000-2400
+
+#
+# End of example file.
+#
diff --git a/modules/pam_time/time.conf.5 b/modules/pam_time/time.conf.5
new file mode 100644
index 00000000..f866f9bc
--- /dev/null
+++ b/modules/pam_time/time.conf.5
@@ -0,0 +1,115 @@
+'\" t
+.\" Title: time.conf
+.\" Author: [see the "AUTHOR" section]
+.\" 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 "TIME\&.CONF" "5" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+time.conf \- configuration file for the pam_time module
+.SH "DESCRIPTION"
+.PP
+The pam_time PAM module does not authenticate the user, but instead it restricts access to a system and or specific applications at various times of the day and on specific days or over various terminal lines\&. This module can be configured to deny access to (individual) users based on their name, the time of day, the day of week, the service they are applying for and their terminal from which they are making their request\&.
+.PP
+For this module to function correctly there must be a correctly formatted
+/etc/security/time\&.conf
+file present\&. White spaces are ignored and lines maybe extended with \*(Aq\e\*(Aq (escaped newlines)\&. Text following a \*(Aq#\*(Aq is ignored to the end of the line\&.
+.PP
+The syntax of the lines is as follows:
+.PP
+\fIservices\fR;\fIttys\fR;\fIusers\fR;\fItimes\fR
+.PP
+In words, each rule occupies a line, terminated with a newline or the beginning of a comment; a \*(Aq\fB#\fR\*(Aq\&. It contains four fields separated with semicolons, \*(Aq\fB;\fR\*(Aq\&.
+.PP
+The first field, the
+\fIservices\fR
+field, is a logic list of PAM service names that the rule applies to\&.
+.PP
+The second field, the
+\fItty\fR
+field, is a logic list of terminal names that this rule applies to\&.
+.PP
+The third field, the
+\fIusers\fR
+field, is a logic list of users or a netgroup of users to whom this rule applies\&.
+.PP
+A logic list namely means individual tokens that are optionally prefixed with \*(Aq!\*(Aq (logical not) and separated with \*(Aq&\*(Aq (logical and) and \*(Aq|\*(Aq (logical or)\&.
+.PP
+For these items the simple wildcard \*(Aq*\*(Aq may be used only once\&. With netgroups no wildcards or logic operators are allowed\&.
+.PP
+The
+\fItimes\fR
+field is used to indicate the times at which this rule applies\&. The format here is a logic list of day/time\-range entries\&. The days are specified by a sequence of two character entries, MoTuSa for example is Monday Tuesday and Saturday\&. Note that repeated days are unset MoMo = no day, and MoWk = all weekdays bar Monday\&. The two character combinations accepted are Mo Tu We Th Fr Sa Su Wk Wd Al, the last two being week\-end days and all 7 days of the week respectively\&. As a final example, AlFr means all days except Friday\&.
+.PP
+Each day/time\-range can be prefixed with a \*(Aq!\*(Aq to indicate "anything but"\&. The time\-range part is two 24\-hour times HHMM, separated by a hyphen, indicating the start and finish time (if the finish time is smaller than the start time it is deemed to apply on the following day)\&.
+.PP
+For a rule to be active, ALL of service+ttys+users must be satisfied by the applying process\&.
+.PP
+Note, currently there is no daemon enforcing the end of a session\&. This needs to be remedied\&.
+.PP
+Poorly formatted rules are logged as errors using
+\fBsyslog\fR(3)\&.
+.SH "EXAMPLES"
+.PP
+These are some example lines which might be specified in
+/etc/security/time\&.conf\&.
+.PP
+All users except for
+\fIroot\fR
+are denied access to console\-login at all times:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+login ; tty* & !ttyp* ; !root ; !Al0000\-2400
+
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+Games (configured to use PAM) are only to be accessed out of working hours\&. This rule does not apply to the user
+\fIwaster\fR:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+games ; * ; !waster ; Wd0000\-2400 | Wk1800\-0800
+
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.SH "SEE ALSO"
+.PP
+\fBpam_time\fR(8),
+\fBpam.d\fR(5),
+\fBpam\fR(8)
+.SH "AUTHOR"
+.PP
+pam_time was written by Andrew G\&. Morgan <morgan@kernel\&.org>\&.
diff --git a/modules/pam_time/time.conf.5.xml b/modules/pam_time/time.conf.5.xml
new file mode 100644
index 00000000..acbe2329
--- /dev/null
+++ b/modules/pam_time/time.conf.5.xml
@@ -0,0 +1,149 @@
+<?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="time.conf">
+
+ <refmeta>
+ <refentrytitle>time.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>time.conf</refname>
+ <refpurpose>configuration file for the pam_time module</refpurpose>
+ </refnamediv>
+
+ <refsect1 id='time.conf-description'>
+ <title>DESCRIPTION</title>
+
+ <para>
+ The pam_time PAM module does not authenticate the user, but instead
+ it restricts access to a system and or specific applications at
+ various times of the day and on specific days or over various
+ terminal lines. This module can be configured to deny access to
+ (individual) users based on their name, the time of day, the day of
+ week, the service they are applying for and their terminal from which
+ they are making their request.
+ </para>
+ <para>
+ For this module to function correctly there must be a correctly
+ formatted <filename>/etc/security/time.conf</filename> file present.
+ White spaces are ignored and lines maybe extended with '\' (escaped
+ newlines). Text following a '#' is ignored to the end of the line.
+ </para>
+
+ <para>
+ The syntax of the lines is as follows:
+ </para>
+
+ <para>
+ <replaceable>services</replaceable>;<replaceable>ttys</replaceable>;<replaceable>users</replaceable>;<replaceable>times</replaceable>
+ </para>
+ <para>
+ In words, each rule occupies a line, terminated with a newline
+ or the beginning of a comment; a '<emphasis remap='B'>#</emphasis>'.
+ It contains four fields separated with semicolons,
+ '<emphasis remap='B'>;</emphasis>'.
+ </para>
+
+ <para>
+ The first field, the <replaceable>services</replaceable> field,
+ is a logic list of PAM service names that the rule applies to.
+ </para>
+
+ <para>
+ The second field, the <replaceable>tty</replaceable>
+ field, is a logic list of terminal names that this rule applies to.
+ </para>
+
+ <para>
+ The third field, the <replaceable>users</replaceable>
+ field, is a logic list of users or a netgroup of users to whom this
+ rule applies.
+ </para>
+
+ <para>
+ A logic list namely means individual tokens that are optionally prefixed
+ with '!' (logical not) and separated with '&amp;' (logical and) and '|'
+ (logical or).
+ </para>
+
+ <para>
+ For these items the simple wildcard '*' may be used only once.
+ With netgroups no wildcards or logic operators are allowed.
+ </para>
+
+ <para>
+ The <replaceable>times</replaceable> field is used to indicate the times
+ at which this rule applies. The format here is a logic
+ list of day/time-range entries. The days are specified by a sequence of
+ two character entries, MoTuSa for example is Monday Tuesday and Saturday.
+ Note that repeated days are unset MoMo = no day, and MoWk = all weekdays
+ bar Monday. The two character combinations accepted are Mo Tu We Th Fr Sa
+ Su Wk Wd Al, the last two being week-end days and all 7 days of the week
+ respectively. As a final example, AlFr means all days except Friday.
+ </para>
+ <para>
+ Each day/time-range can be prefixed with a '!' to indicate
+ "anything but".
+ The time-range part is two 24-hour times HHMM, separated by a hyphen,
+ indicating the start and finish time (if the finish time is smaller
+ than the start time it is deemed to apply on the following day).
+ </para>
+
+ <para>
+ For a rule to be active, ALL of service+ttys+users must be satisfied
+ by the applying process.
+ </para>
+ <para>
+ Note, currently there is no daemon enforcing the end of a session.
+ This needs to be remedied.
+ </para>
+ <para>
+ Poorly formatted rules are logged as errors using
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ </para>
+ </refsect1>
+
+ <refsect1 id="time.conf-examples">
+ <title>EXAMPLES</title>
+ <para>
+ These are some example lines which might be specified in
+ <filename>/etc/security/time.conf</filename>.
+ </para>
+ <para>
+ All users except for <emphasis>root</emphasis> are denied access
+ to console-login at all times:
+ <programlisting>
+login ; tty* &amp; !ttyp* ; !root ; !Al0000-2400
+ </programlisting>
+ </para>
+
+ <para>
+ Games (configured to use PAM) are only to be accessed out of
+ working hours. This rule does not apply to the user
+ <emphasis>waster</emphasis>:
+ <programlisting>
+games ; * ; !waster ; Wd0000-2400 | Wk1800-0800
+ </programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1 id="time.conf-see_also">
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry><refentrytitle>pam_time</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1 id="time.conf-author">
+ <title>AUTHOR</title>
+ <para>
+ pam_time was written by Andrew G. Morgan &lt;morgan@kernel.org&gt;.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/modules/pam_time/tst-pam_time b/modules/pam_time/tst-pam_time
new file mode 100755
index 00000000..030717bb
--- /dev/null
+++ b/modules/pam_time/tst-pam_time
@@ -0,0 +1,2 @@
+#!/bin/sh
+../../tests/tst-dlopen .libs/pam_time.so