diff options
Diffstat (limited to 'modules/pam_motd')
-rw-r--r-- | modules/pam_motd/Makefile.am | 16 | ||||
-rw-r--r-- | modules/pam_motd/Makefile.in | 112 | ||||
-rw-r--r-- | modules/pam_motd/README | 46 | ||||
-rw-r--r-- | modules/pam_motd/pam_motd.8 | 89 | ||||
-rw-r--r-- | modules/pam_motd/pam_motd.8.xml | 88 | ||||
-rw-r--r-- | modules/pam_motd/pam_motd.c | 312 |
6 files changed, 546 insertions, 117 deletions
diff --git a/modules/pam_motd/Makefile.am b/modules/pam_motd/Makefile.am index bd499c54..956dad2b 100644 --- a/modules/pam_motd/Makefile.am +++ b/modules/pam_motd/Makefile.am @@ -5,17 +5,20 @@ CLEANFILES = *~ MAINTAINERCLEANFILES = $(MANS) README -EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_motd +EXTRA_DIST = $(XMLS) -man_MANS = pam_motd.8 +if HAVE_DOC +dist_man_MANS = pam_motd.8 +endif XMLS = README.xml pam_motd.8.xml - -TESTS = tst-pam_motd +dist_check_SCRIPTS = tst-pam_motd +TESTS = $(dist_check_SCRIPTS) securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) -AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + $(WARN_CFLAGS) AM_LDFLAGS = -no-undefined -avoid-version -module if HAVE_VERSIONING AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map @@ -25,7 +28,6 @@ securelib_LTLIBRARIES = pam_motd.la pam_motd_la_LIBADD = $(top_builddir)/libpam/libpam.la if ENABLE_REGENERATE_MAN -noinst_DATA = README -README: pam_motd.8.xml +dist_noinst_DATA = README -include $(top_srcdir)/Make.xml.rules endif diff --git a/modules/pam_motd/Makefile.in b/modules/pam_motd/Makefile.in index 05504cc9..9ed9e2e4 100644 --- a/modules/pam_motd/Makefile.in +++ b/modules/pam_motd/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.13.4 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,7 +20,17 @@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -85,9 +95,6 @@ build_triplet = @build@ host_triplet = @host@ @HAVE_VERSIONING_TRUE@am__append_1 = -Wl,--version-script=$(srcdir)/../modules.map subdir = modules/pam_motd -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp \ - $(top_srcdir)/build-aux/test-driver README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ @@ -103,6 +110,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \ + $(am__dist_noinst_DATA_DIST) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -157,7 +166,8 @@ am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/pam_motd.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -186,8 +196,9 @@ am__can_run_installinfo = \ esac man8dir = $(mandir)/man8 NROFF = nroff -MANS = $(man_MANS) -DATA = $(noinst_DATA) +MANS = $(dist_man_MANS) +am__dist_noinst_DATA_DIST = README +DATA = $(dist_noinst_DATA) 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 @@ -384,6 +395,9 @@ TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -412,6 +426,8 @@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ +ECONF_CFLAGS = @ECONF_CFLAGS@ +ECONF_LIBS = @ECONF_LIBS@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ @@ -420,7 +436,6 @@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ -HAVE_KEY_MANAGEMENT = @HAVE_KEY_MANAGEMENT@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -456,6 +471,7 @@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -492,11 +508,13 @@ SECUREDIR = @SECUREDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@ STRIP = @STRIP@ TIRPC_CFLAGS = @TIRPC_CFLAGS@ TIRPC_LIBS = @TIRPC_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ @@ -565,17 +583,20 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ CLEANFILES = *~ MAINTAINERCLEANFILES = $(MANS) README -EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_motd -man_MANS = pam_motd.8 +EXTRA_DIST = $(XMLS) +@HAVE_DOC_TRUE@dist_man_MANS = pam_motd.8 XMLS = README.xml pam_motd.8.xml -TESTS = tst-pam_motd +dist_check_SCRIPTS = tst-pam_motd +TESTS = $(dist_check_SCRIPTS) securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) -AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + $(WARN_CFLAGS) + AM_LDFLAGS = -no-undefined -avoid-version -module $(am__append_1) securelib_LTLIBRARIES = pam_motd.la pam_motd_la_LIBADD = $(top_builddir)/libpam/libpam.la -@ENABLE_REGENERATE_MAN_TRUE@noinst_DATA = README +@ENABLE_REGENERATE_MAN_TRUE@dist_noinst_DATA = README all: all-am .SUFFIXES: @@ -592,14 +613,13 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu modules/pam_motd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu modules/pam_motd/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -655,21 +675,27 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_motd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pam_motd.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -683,10 +709,10 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -install-man8: $(man_MANS) +install-man8: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ - list2='$(man_MANS)'; \ + list2='$(dist_man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ @@ -721,7 +747,7 @@ uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ - l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ @@ -809,7 +835,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ - else \ + elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ @@ -899,7 +925,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) fi; \ $$success || exit 1 -check-TESTS: +check-TESTS: $(dist_check_SCRIPTS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @@ -909,7 +935,7 @@ check-TESTS: log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; -recheck: all +recheck: all $(dist_check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ @@ -942,7 +968,10 @@ tst-pam_motd.log: tst-pam_motd @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -973,6 +1002,7 @@ distdir: $(DISTFILES) fi; \ done check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(dist_check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(MANS) $(DATA) @@ -1021,7 +1051,7 @@ clean-am: clean-generic clean-libtool clean-securelibLTLIBRARIES \ mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/pam_motd.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1067,7 +1097,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/pam_motd.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -1090,15 +1120,16 @@ uninstall-man: uninstall-man8 .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ - clean-generic clean-libtool clean-securelibLTLIBRARIES \ - cscopelist-am ctags ctags-am distclean distclean-compile \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-man8 \ - install-pdf install-pdf-am install-ps install-ps-am \ +.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-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man 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 \ @@ -1106,7 +1137,8 @@ uninstall-man: uninstall-man8 recheck tags tags-am uninstall uninstall-am uninstall-man \ uninstall-man8 uninstall-securelibLTLIBRARIES -@ENABLE_REGENERATE_MAN_TRUE@README: pam_motd.8.xml +.PRECIOUS: Makefile + @ENABLE_REGENERATE_MAN_TRUE@-include $(top_srcdir)/Make.xml.rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/modules/pam_motd/README b/modules/pam_motd/README index c16938c1..cd1e27e9 100644 --- a/modules/pam_motd/README +++ b/modules/pam_motd/README @@ -5,23 +5,55 @@ pam_motd — Display the motd file DESCRIPTION pam_motd is a PAM module that can be used to display arbitrary motd (message of -the day) files after a successful login. By default the /etc/motd file is -shown. The message size is limited to 64KB. +the day) files after a successful login. By default, pam_motd shows files in +the following locations: + +/etc/motd +/run/motd +/usr/lib/motd +/etc/motd.d/ +/run/motd.d/ +/usr/lib/motd.d/ + +Each message size is limited to 64KB. + +If /etc/motd does not exist, then /run/motd is shown. If /run/motd does not +exist, then /usr/lib/motd is shown. + +Similar overriding behavior applies to the directories. Files in /etc/motd.d/ +override files with the same name in /run/motd.d/ and /usr/lib/motd.d/. Files +in /run/motd.d/ override files with the same name in /usr/lib/motd.d/. + +Files the in the directories listed above are displayed in lexicographic order +by name. + +To silence a message, a symbolic link with target /dev/null may be placed in / +etc/motd.d with the same filename as the message to be silenced. Example: +Creating a symbolic link as follows silences /usr/lib/motd.d/my_motd. + +ln -s /dev/null /etc/motd.d/my_motd + +The MOTD_SHOWN=pam environment variable is set after showing the motd files, +even when all of them were silenced using symbolic links. OPTIONS motd=/path/filename - The /path/filename file is displayed as message of the day. + The /path/filename file is displayed as message of the day. Multiple paths + to try can be specified as a colon-separated list. By default this option + is set to /etc/motd:/run/motd:/usr/lib/motd. motd_dir=/path/dirname.d The /path/dirname.d directory is scanned and each file contained inside of - it is displayed. + it is displayed. Multiple directories to scan can be specified as a + colon-separated list. By default this option is set to /etc/motd.d:/run/ + motd.d:/usr/lib/motd.d. -When no options are given, the default is to display both /etc/motd and the -contents of /etc/motd.d. Specifying either option (or both) will disable this -default behavior. +When no options are given, the default behavior applies for both options. +Specifying either option (or both) will disable the default behavior for both +options. EXAMPLES diff --git a/modules/pam_motd/pam_motd.8 b/modules/pam_motd/pam_motd.8 index 21c2ed76..63da02fa 100644 --- a/modules/pam_motd/pam_motd.8 +++ b/modules/pam_motd/pam_motd.8 @@ -1,13 +1,13 @@ '\" t .\" Title: pam_motd .\" Author: [see the "AUTHOR" section] -.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/> -.\" Date: 05/18/2018 +.\" 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_MOTD" "8" "05/18/2018" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "PAM_MOTD" "8" "06/08/2020" "Linux-PAM Manual" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -31,32 +31,85 @@ pam_motd \- Display the motd file .SH "SYNOPSIS" .HP \w'\fBpam_motd\&.so\fR\ 'u -\fBpam_motd\&.so\fR [motd=\fI/path/filename\fR] +\fBpam_motd\&.so\fR [motd=\fI/path/filename\fR] [motd_dir=\fI/path/dirname\&.d\fR] .SH "DESCRIPTION" .PP -pam_motd is a PAM module that can be used to display arbitrary motd (message of the day) files after a successful login\&. By default the +pam_motd is a PAM module that can be used to display arbitrary motd (message of the day) files after a successful login\&. By default, pam_motd shows files in the following locations: +.PP +.RS 4 /etc/motd -file is shown\&. The message size is limited to 64KB\&. +.RE +.RS 4 +/run/motd +.RE +.RS 4 +/usr/lib/motd +.RE +.RS 4 +/etc/motd\&.d/ +.RE +.RS 4 +/run/motd\&.d/ +.RE +.RS 4 +/usr/lib/motd\&.d/ +.RE +.PP +Each message size is limited to 64KB\&. +.PP +If +/etc/motd +does not exist, then +/run/motd +is shown\&. If +/run/motd +does not exist, then +/usr/lib/motd +is shown\&. +.PP +Similar overriding behavior applies to the directories\&. Files in +/etc/motd\&.d/ +override files with the same name in +/run/motd\&.d/ +and +/usr/lib/motd\&.d/\&. Files in +/run/motd\&.d/ +override files with the same name in +/usr/lib/motd\&.d/\&. +.PP +Files the in the directories listed above are displayed in lexicographic order by name\&. +.PP +To silence a message, a symbolic link with target +/dev/null +may be placed in +/etc/motd\&.d +with the same filename as the message to be silenced\&. Example: Creating a symbolic link as follows silences +/usr/lib/motd\&.d/my_motd\&. +.PP +\fBln \-s /dev/null /etc/motd\&.d/my_motd\fR +.PP +The +\fBMOTD_SHOWN=pam\fR +environment variable is set after showing the motd files, even when all of them were silenced using symbolic links\&. .SH "OPTIONS" .PP \fBmotd=\fR\fB\fI/path/filename\fR\fR .RS 4 The /path/filename -file is displayed as message of the day\&. +file is displayed as message of the day\&. Multiple paths to try can be specified as a colon\-separated list\&. By default this option is set to +/etc/motd:/run/motd:/usr/lib/motd\&. .RE .PP \fBmotd_dir=\fR\fB\fI/path/dirname\&.d\fR\fR .RS 4 The /path/dirname\&.d -directory is scanned and each file contained inside of it is displayed\&. +directory is scanned and each file contained inside of it is displayed\&. Multiple directories to scan can be specified as a colon\-separated list\&. By default this option is set to +/etc/motd\&.d:/run/motd\&.d:/usr/lib/motd\&.d\&. .RE .PP -When no options are given, the default is to display both -/etc/motd -and the contents of -/etc/motd\&.d\&. Specifying either option (or both) will disable this default behavior\&. +When no options are given, the default behavior applies for both options\&. Specifying either option (or both) will disable the default behavior for both options\&. .SH "MODULE TYPES PROVIDED" .PP Only the @@ -64,9 +117,19 @@ Only the module type is provided\&. .SH "RETURN VALUES" .PP +PAM_ABORT +.RS 4 +Not all relevant data or options could be obtained\&. +.RE +.PP +PAM_BUF_ERR +.RS 4 +Memory buffer error\&. +.RE +.PP PAM_IGNORE .RS 4 -This is the only return value of this module\&. +This is the default return value of this module\&. .RE .SH "EXAMPLES" .PP diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml index 906c4ed0..b533530b 100644 --- a/modules/pam_motd/pam_motd.8.xml +++ b/modules/pam_motd/pam_motd.8.xml @@ -21,6 +21,9 @@ <arg choice="opt"> motd=<replaceable>/path/filename</replaceable> </arg> + <arg choice="opt"> + motd_dir=<replaceable>/path/dirname.d</replaceable> + </arg> </cmdsynopsis> </refsynopsisdiv> @@ -31,10 +34,54 @@ <para> pam_motd is a PAM module that can be used to display arbitrary motd (message of the day) files after a successful - login. By default the <filename>/etc/motd</filename> file is - shown. The message size is limited to 64KB. + login. By default, pam_motd shows files in the + following locations: + </para> + <para> + <simplelist type='vert'> + <member><filename>/etc/motd</filename></member> + <member><filename>/run/motd</filename></member> + <member><filename>/usr/lib/motd</filename></member> + <member><filename>/etc/motd.d/</filename></member> + <member><filename>/run/motd.d/</filename></member> + <member><filename>/usr/lib/motd.d/</filename></member> + </simplelist> + </para> + <para> + Each message size is limited to 64KB. + </para> + <para> + If <filename>/etc/motd</filename> does not exist, + then <filename>/run/motd</filename> is shown. If + <filename>/run/motd</filename> does not exist, then + <filename>/usr/lib/motd</filename> is shown. + </para> + <para> + Similar overriding behavior applies to the directories. + Files in <filename>/etc/motd.d/</filename> override files + with the same name in <filename>/run/motd.d/</filename> and + <filename>/usr/lib/motd.d/</filename>. Files in <filename>/run/motd.d/</filename> + override files with the same name in <filename>/usr/lib/motd.d/</filename>. + </para> + <para> + Files the in the directories listed above are displayed in + lexicographic order by name. + </para> + <para> + To silence a message, + a symbolic link with target <filename>/dev/null</filename> + may be placed in <filename>/etc/motd.d</filename> with + the same filename as the message to be silenced. Example: + Creating a symbolic link as follows silences <filename>/usr/lib/motd.d/my_motd</filename>. + </para> + <para> + <command>ln -s /dev/null /etc/motd.d/my_motd</command> + </para> + <para> + The <emphasis remap='B'>MOTD_SHOWN=pam</emphasis> environment variable + is set after showing the motd files, even when all of them were silenced + using symbolic links. </para> - </refsect1> <refsect1 id="pam_motd-options"> @@ -47,8 +94,10 @@ </term> <listitem> <para> - The <filename>/path/filename</filename> file is displayed - as message of the day. + The <filename>/path/filename</filename> file is displayed + as message of the day. Multiple paths to try can be + specified as a colon-separated list. By default this option + is set to <filename>/etc/motd:/run/motd:/usr/lib/motd</filename>. </para> </listitem> </varlistentry> @@ -59,16 +108,17 @@ <listitem> <para> The <filename>/path/dirname.d</filename> directory is scanned - and each file contained inside of it is displayed. + and each file contained inside of it is displayed. Multiple + directories to scan can be specified as a colon-separated list. + By default this option is set to <filename>/etc/motd.d:/run/motd.d:/usr/lib/motd.d</filename>. </para> </listitem> </varlistentry> </variablelist> <para> - When no options are given, the default is to display both - <filename>/etc/motd</filename> and the contents of - <filename>/etc/motd.d</filename>. Specifying either option (or both) - will disable this default behavior. + When no options are given, the default behavior applies for both + options. Specifying either option (or both) will disable the + default behavior for both options. </para> </refsect1> @@ -83,10 +133,26 @@ <title>RETURN VALUES</title> <variablelist> <varlistentry> + <term>PAM_ABORT</term> + <listitem> + <para> + Not all relevant data or options could be obtained. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>PAM_BUF_ERR</term> + <listitem> + <para> + Memory buffer error. + </para> + </listitem> + </varlistentry> + <varlistentry> <term>PAM_IGNORE</term> <listitem> <para> - This is the only return value of this module. + This is the default return value of this module. </para> </listitem> </varlistentry> diff --git a/modules/pam_motd/pam_motd.c b/modules/pam_motd/pam_motd.c index cc828d7e..46f4fe61 100644 --- a/modules/pam_motd/pam_motd.c +++ b/modules/pam_motd/pam_motd.c @@ -1,13 +1,8 @@ -/* pam_motd module */ - /* - * Modified for pam_motd by Ben Collins <bcollins@debian.org> - * - * Based off of: - * $Id$ + * pam_motd module * + * Modified for pam_motd by Ben Collins <bcollins@debian.org> * Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24 - * */ #include "config.h" @@ -22,22 +17,16 @@ #include <sys/stat.h> #include <pwd.h> #include <syslog.h> +#include <errno.h> #include <security/_pam_macros.h> #include <security/pam_ext.h> -/* - * here, we make a definition for the externally accessible function - * in this file (this definition is required for static a module - * but strongly encouraged generally) it is used to instruct the - * modules include file to define the function prototypes. - */ - -#define PAM_SM_SESSION -#define DEFAULT_MOTD "/etc/motd" -#define DEFAULT_MOTD_D "/etc/motd.d" - #include <security/pam_modules.h> #include <security/pam_modutil.h> +#include "pam_inline.h" + +#define DEFAULT_MOTD "/etc/motd:/run/motd:/usr/lib/motd" +#define DEFAULT_MOTD_D "/etc/motd.d:/run/motd.d:/usr/lib/motd.d" /* --- session management functions (only) --- */ @@ -48,8 +37,8 @@ pam_sm_close_session (pam_handle_t *pamh UNUSED, int flags UNUSED, return PAM_IGNORE; } -static char default_motd[] = DEFAULT_MOTD; -static char default_motd_dir[] = DEFAULT_MOTD_D; +static const char default_motd[] = DEFAULT_MOTD; +static const char default_motd_dir[] = DEFAULT_MOTD_D; static void try_to_display_fd(pam_handle_t *pamh, int fd) { @@ -75,26 +64,222 @@ static void try_to_display_fd(pam_handle_t *pamh, int fd) _pam_drop(mtmp); } -static void try_to_display_directory(pam_handle_t *pamh, const char *dirname) +/* + * Split a DELIM-separated string ARG into an array. + * Outputs a newly allocated array of strings OUT_ARG_SPLIT + * and the number of strings OUT_NUM_STRS. + * Returns 0 in case of error, 1 in case of success. + */ +static int pam_split_string(const pam_handle_t *pamh, char *arg, char delim, + char ***out_arg_split, unsigned int *out_num_strs) +{ + char *arg_extracted = NULL; + const char *arg_ptr = arg; + char **arg_split = NULL; + char delim_str[2]; + unsigned int i = 0; + unsigned int num_strs = 0; + int retval = 0; + + delim_str[0] = delim; + delim_str[1] = '\0'; + + if (arg == NULL) { + goto out; + } + + while (arg_ptr != NULL) { + num_strs++; + arg_ptr = strchr(arg_ptr + sizeof(const char), delim); + } + + arg_split = calloc(num_strs, sizeof(*arg_split)); + if (arg_split == NULL) { + pam_syslog(pamh, LOG_CRIT, "failed to allocate string array"); + goto out; + } + + arg_extracted = strtok_r(arg, delim_str, &arg); + while (arg_extracted != NULL && i < num_strs) { + arg_split[i++] = arg_extracted; + arg_extracted = strtok_r(NULL, delim_str, &arg); + } + + retval = 1; + + out: + *out_num_strs = num_strs; + *out_arg_split = arg_split; + + return retval; +} + +/* Join A_STR and B_STR, inserting a "/" between them if one is not already trailing + * in A_STR or beginning B_STR. A pointer to a newly allocated string holding the + * joined string is returned in STRP_OUT. + * Returns -1 in case of error, or the number of bytes in the joined string in + * case of success. */ +static int join_dir_strings(char **strp_out, const char *a_str, const char *b_str) +{ + int has_sep = 0; + int retval = -1; + char *join_strp = NULL; + + if (strp_out == NULL || a_str == NULL || b_str == NULL) { + goto out; + } + if (strlen(a_str) == 0) { + goto out; + } + + has_sep = (a_str[strlen(a_str) - 1] == '/') || (b_str[0] == '/'); + + retval = asprintf(&join_strp, "%s%s%s", a_str, + (has_sep == 1) ? "" : "/", b_str); + + if (retval < 0) { + goto out; + } + + *strp_out = join_strp; + + out: + return retval; +} + +static int compare_strings(const void *a, const void *b) +{ + const char *a_str = *(const char * const *)a; + const char *b_str = *(const char * const *)b; + + if (a_str == NULL && b_str == NULL) { + return 0; + } + else if (a_str == NULL) { + return -1; + } + else if (b_str == NULL) { + return 1; + } + else { + return strcmp(a_str, b_str); + } +} + +static int filter_dirents(const struct dirent *d) +{ + return (d->d_type == DT_REG || d->d_type == DT_LNK); +} + +static void try_to_display_directories_with_overrides(pam_handle_t *pamh, + char **motd_dir_path_split, unsigned int num_motd_dirs, int report_missing) { - DIR *dirp; + struct dirent ***dirscans = NULL; + unsigned int *dirscans_sizes = NULL; + unsigned int dirscans_size_total = 0; + char **dirnames_all = NULL; + unsigned int i; + int i_dirnames = 0; + + if (pamh == NULL || motd_dir_path_split == NULL) { + goto out; + } + if (num_motd_dirs < 1) { + goto out; + } + + if ((dirscans = calloc(num_motd_dirs, sizeof(*dirscans))) == NULL) { + pam_syslog(pamh, LOG_CRIT, "failed to allocate dirent arrays"); + goto out; + } + if ((dirscans_sizes = calloc(num_motd_dirs, sizeof(*dirscans_sizes))) == NULL) { + pam_syslog(pamh, LOG_CRIT, "failed to allocate dirent array sizes"); + goto out; + } + + for (i = 0; i < num_motd_dirs; i++) { + int rv; + rv = scandir(motd_dir_path_split[i], &(dirscans[i]), + filter_dirents, alphasort); + if (rv < 0) { + if (errno != ENOENT || report_missing) { + pam_syslog(pamh, LOG_ERR, "error scanning directory %s: %m", + motd_dir_path_split[i]); + } + } else { + dirscans_sizes[i] = rv; + } + dirscans_size_total += dirscans_sizes[i]; + } + + if (dirscans_size_total == 0) + goto out; + + /* Allocate space for all file names found in the directories, including duplicates. */ + if ((dirnames_all = calloc(dirscans_size_total, sizeof(*dirnames_all))) == NULL) { + pam_syslog(pamh, LOG_CRIT, "failed to allocate dirname array"); + goto out; + } + + for (i = 0; i < num_motd_dirs; i++) { + unsigned int j; + + for (j = 0; j < dirscans_sizes[i]; j++) { + dirnames_all[i_dirnames] = dirscans[i][j]->d_name; + i_dirnames++; + } + } + + qsort(dirnames_all, dirscans_size_total, + sizeof(const char *), compare_strings); + + for (i = 0; i < dirscans_size_total; i++) { + unsigned int j; + + if (dirnames_all[i] == NULL) { + continue; + } + + /* Skip duplicate file names. */ + if (i > 0 && strcmp(dirnames_all[i], dirnames_all[i - 1]) == 0) { + continue; + } - dirp = opendir(dirname); + for (j = 0; j < num_motd_dirs; j++) { + char *abs_path = NULL; + int fd; - if (dirp != NULL) { - struct dirent *entry; + if (join_dir_strings(&abs_path, motd_dir_path_split[j], + dirnames_all[i]) < 0 || abs_path == NULL) { + continue; + } - while ((entry = readdir(dirp))) { - int fd = openat(dirfd(dirp), entry->d_name, O_RDONLY); + fd = open(abs_path, O_RDONLY, 0); + _pam_drop(abs_path); if (fd >= 0) { try_to_display_fd(pamh, fd); close(fd); + + /* We displayed a file, skip to the next file name. */ + break; } } + } - closedir(dirp); + out: + _pam_drop(dirnames_all); + if (dirscans_sizes != NULL) { + for (i = 0; i < num_motd_dirs; i++) { + unsigned int j; + + for (j = 0; j < dirscans_sizes[i]; j++) + _pam_drop(dirscans[i][j]); + _pam_drop(dirscans[i]); + } + _pam_drop(dirscans_sizes); } + _pam_drop(dirscans); } int pam_sm_open_session(pam_handle_t *pamh, int flags, @@ -102,16 +287,24 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, { int retval = PAM_IGNORE; const char *motd_path = NULL; + char *motd_path_copy = NULL; + unsigned int num_motd_paths = 0; + char **motd_path_split = NULL; const char *motd_dir_path = NULL; + char *motd_dir_path_copy = NULL; + unsigned int num_motd_dir_paths = 0; + char **motd_dir_path_split = NULL; + int report_missing; if (flags & PAM_SILENT) { return retval; } for (; argc-- > 0; ++argv) { - if (!strncmp(*argv,"motd=",5)) { + const char *str; + if ((str = pam_str_skip_prefix(*argv, "motd=")) != NULL) { - motd_path = 5 + *argv; + motd_path = str; if (*motd_path != '\0') { D(("set motd path: %s", motd_path)); } else { @@ -120,9 +313,9 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, "motd= specification missing argument - ignored"); } } - else if (!strncmp(*argv,"motd_dir=",9)) { + else if ((str = pam_str_skip_prefix(*argv, "motd_dir=")) != NULL) { - motd_dir_path = 9 + *argv; + motd_dir_path = str; if (*motd_dir_path != '\0') { D(("set motd.d path: %s", motd_dir_path)); } else { @@ -138,21 +331,62 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, if (motd_path == NULL && motd_dir_path == NULL) { motd_path = default_motd; motd_dir_path = default_motd_dir; + report_missing = 0; + } else { + report_missing = 1; } if (motd_path != NULL) { - int fd = open(motd_path, O_RDONLY, 0); + motd_path_copy = strdup(motd_path); + } - if (fd >= 0) { - try_to_display_fd(pamh, fd); - close(fd); + if (motd_path_copy != NULL) { + if (pam_split_string(pamh, motd_path_copy, ':', + &motd_path_split, &num_motd_paths) == 0) { + goto out; } } - if (motd_dir_path != NULL) - try_to_display_directory(pamh, motd_dir_path); + if (motd_dir_path != NULL) { + motd_dir_path_copy = strdup(motd_dir_path); + } - return retval; + if (motd_dir_path_copy != NULL) { + if (pam_split_string(pamh, motd_dir_path_copy, ':', + &motd_dir_path_split, &num_motd_dir_paths) == 0) { + goto out; + } + } + + if (motd_path_split != NULL) { + unsigned int i; + + for (i = 0; i < num_motd_paths; i++) { + int fd = open(motd_path_split[i], O_RDONLY, 0); + + if (fd >= 0) { + try_to_display_fd(pamh, fd); + close(fd); + + /* We found and displayed a file, move onto next filename. */ + break; + } + } + } + + if (motd_dir_path_split != NULL) + try_to_display_directories_with_overrides(pamh, motd_dir_path_split, + num_motd_dir_paths, report_missing); + + out: + _pam_drop(motd_path_copy); + _pam_drop(motd_path_split); + _pam_drop(motd_dir_path_copy); + _pam_drop(motd_dir_path_split); + + retval = pam_putenv(pamh, "MOTD_SHOWN=pam"); + + return retval == PAM_SUCCESS ? PAM_IGNORE : retval; } /* end of module definition */ |