diff options
author | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 17:53:41 -0800 |
---|---|---|
committer | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 18:17:08 -0800 |
commit | 212b52cf29c06cc209bc8ac0540dbab1acdf1464 (patch) | |
tree | 58da0bf39f5c4122e4a1b4da20fdeea52b97a671 /modules/pam_lastlog | |
parent | 9c52e721044e7501c3d4567b36d222dc7326224a (diff) | |
parent | 56c8282d128fb484ffc77dff73abf42229b291d3 (diff) |
New upstream version 1.1.0
Diffstat (limited to 'modules/pam_lastlog')
-rw-r--r-- | modules/pam_lastlog/Makefile.in | 75 | ||||
-rw-r--r-- | modules/pam_lastlog/README | 11 | ||||
-rw-r--r-- | modules/pam_lastlog/pam_lastlog.8 | 254 | ||||
-rw-r--r-- | modules/pam_lastlog/pam_lastlog.8.xml | 40 | ||||
-rw-r--r-- | modules/pam_lastlog/pam_lastlog.c | 152 |
5 files changed, 454 insertions, 78 deletions
diff --git a/modules/pam_lastlog/Makefile.in b/modules/pam_lastlog/Makefile.in index 6bd440a2..d6fe7d2c 100644 --- a/modules/pam_lastlog/Makefile.in +++ b/modules/pam_lastlog/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. +# Makefile.in generated by automake 1.10.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -42,13 +42,16 @@ subdir = modules/pam_lastlog DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.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/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libprelude.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.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.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) @@ -101,23 +104,19 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ -ECHO = @ECHO@ +DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ +FGREP = @FGREP@ FO2PDF = @FO2PDF@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ @@ -129,6 +128,7 @@ 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@ @@ -152,6 +152,7 @@ LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@ LIBS = @LIBS@ LIBSELINUX = @LIBSELINUX@ LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ @@ -161,15 +162,18 @@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ +NM = @NM@ NMEDIT = @NMEDIT@ +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_VERSION = @PACKAGE_VERSION@ -PAM_READ_BOTH_CONFS = @PAM_READ_BOTH_CONFS@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIE_CFLAGS = @PIE_CFLAGS@ PIE_LDFLAGS = @PIE_LDFLAGS@ @@ -183,10 +187,9 @@ SHELL = @SHELL@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ -WITH_DEBUG = @WITH_DEBUG@ -WITH_PAMLOCKING = @WITH_PAMLOCKING@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMLCATALOG = @XMLCATALOG@ XMLLINT = @XMLLINT@ XML_CATALOG_FILE = @XML_CATALOG_FILE@ @@ -198,8 +201,7 @@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -231,6 +233,7 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -245,6 +248,7 @@ 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 = *~ @@ -267,8 +271,8 @@ $(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 \ - && exit 0; \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ @@ -367,8 +371,8 @@ install-man8: $(man8_MANS) $(man_MANS) esac; \ done; \ for i in $$list; do \ - if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ - else file=$$i; fi; \ + if test -f $$i; then file=$$i; \ + else file=$(srcdir)/$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ @@ -407,7 +411,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ - $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS @@ -450,7 +454,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) - @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \ + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ if test -n "$$list"; then \ @@ -461,7 +465,7 @@ check-TESTS: $(TESTS) if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ - *$$ws$$tst$$ws*) \ + *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ @@ -473,7 +477,7 @@ check-TESTS: $(TESTS) elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ - *$$ws$$tst$$ws*) \ + *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ @@ -487,23 +491,36 @@ check-TESTS: $(TESTS) echo "SKIP: $$tst"; \ fi; \ done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ - banner="All $$all tests passed"; \ + banner="$$All$$all $$tests passed"; \ else \ - banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all tests failed"; \ + banner="$$failed of $$all $$tests failed"; \ else \ - banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ - skipped="($$skip tests were not run)"; \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ diff --git a/modules/pam_lastlog/README b/modules/pam_lastlog/README index 9f6c5505..c7149487 100644 --- a/modules/pam_lastlog/README +++ b/modules/pam_lastlog/README @@ -18,7 +18,7 @@ debug silent - Don't inform the user about any previous login, just upate the /var/log/ + Don't inform the user about any previous login, just update the /var/log/ lastlog file. never @@ -43,6 +43,15 @@ nowtmp Don't update the wtmp entry. +noupdate + + Don't update any file. + +showfailed + + Display number of failed login attempts and the date of the last failed + attempt from btmp. The date is not displayed when nodate is specified. + EXAMPLES Add the following line to /etc/pam.d/login to display the last login time of an diff --git a/modules/pam_lastlog/pam_lastlog.8 b/modules/pam_lastlog/pam_lastlog.8 index e822c84b..33be7f1f 100644 --- a/modules/pam_lastlog/pam_lastlog.8 +++ b/modules/pam_lastlog/pam_lastlog.8 @@ -1,104 +1,292 @@ .\" Title: pam_lastlog -.\" Author: -.\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/> -.\" Date: 04/16/2008 +.\" Author: [see the "AUTHOR" section] +.\" Generator: DocBook XSL Stylesheets v1.74.0 <http://docbook.sf.net/> +.\" Date: 06/16/2009 .\" Manual: Linux-PAM Manual .\" Source: Linux-PAM Manual +.\" Language: English .\" -.TH "PAM_LASTLOG" "8" "04/16/2008" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "PAM_LASTLOG" "8" "06/16/2009" "Linux-PAM Manual" "Linux\-PAM Manual" +.\" ----------------------------------------------------------------- +.\" * (re)Define some macros +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" toupper - uppercase a string (locale-aware) +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.de toupper +.tr aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ +\\$* +.tr aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz +.. +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" SH-xref - format a cross-reference to an SH section +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.de SH-xref +.ie n \{\ +.\} +.toupper \\$* +.el \{\ +\\$* +.\} +.. +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" SH - level-one heading that works better for non-TTY output +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.de1 SH +.\" put an extra blank line of space above the head in non-TTY output +.if t \{\ +.sp 1 +.\} +.sp \\n[PD]u +.nr an-level 1 +.set-an-margin +.nr an-prevailing-indent \\n[IN] +.fi +.in \\n[an-margin]u +.ti 0 +.HTML-TAG ".NH \\n[an-level]" +.it 1 an-trap +.nr an-no-space-flag 1 +.nr an-break-flag 1 +\." make the size of the head bigger +.ps +3 +.ft B +.ne (2v + 1u) +.ie n \{\ +.\" if n (TTY output), use uppercase +.toupper \\$* +.\} +.el \{\ +.nr an-break-flag 0 +.\" if not n (not TTY), use normal case (not uppercase) +\\$1 +.in \\n[an-margin]u +.ti 0 +.\" if not n (not TTY), put a border/line under subheading +.sp -.6 +\l'\n(.lu' +.\} +.. +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" SS - level-two heading that works better for non-TTY output +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.de1 SS +.sp \\n[PD]u +.nr an-level 1 +.set-an-margin +.nr an-prevailing-indent \\n[IN] +.fi +.in \\n[IN]u +.ti \\n[SN]u +.it 1 an-trap +.nr an-no-space-flag 1 +.nr an-break-flag 1 +.ps \\n[PS-SS]u +\." make the size of the head bigger +.ps +2 +.ft B +.ne (2v + 1u) +.if \\n[.$] \&\\$* +.. +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" BB/BE - put background/screen (filled box) around block of text +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.de BB +.if t \{\ +.sp -.5 +.br +.in +2n +.ll -2n +.gcolor red +.di BX +.\} +.. +.de EB +.if t \{\ +.if "\\$2"adjust-for-leading-newline" \{\ +.sp -1 +.\} +.br +.di +.in +.ll +.gcolor +.nr BW \\n(.lu-\\n(.i +.nr BH \\n(dn+.5v +.ne \\n(BHu+.5v +.ie "\\$2"adjust-for-leading-newline" \{\ +\M[\\$1]\h'1n'\v'+.5v'\D'P \\n(BWu 0 0 \\n(BHu -\\n(BWu 0 0 -\\n(BHu'\M[] +.\} +.el \{\ +\M[\\$1]\h'1n'\v'-.5v'\D'P \\n(BWu 0 0 \\n(BHu -\\n(BWu 0 0 -\\n(BHu'\M[] +.\} +.in 0 +.sp -.5v +.nf +.BX +.in +.sp .5v +.fi +.\} +.. +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" BM/EM - put colored marker in margin next to block of text +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.de BM +.if t \{\ +.br +.ll -2n +.gcolor red +.di BX +.\} +.. +.de EM +.if t \{\ +.br +.di +.ll +.gcolor +.nr BH \\n(dn +.ne \\n(BHu +\M[\\$1]\D'P -.75n 0 0 \\n(BHu -(\\n[.i]u - \\n(INu - .75n) 0 0 -\\n(BHu'\M[] +.in 0 +.nf +.BX +.in +.fi +.\} +.. +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l -.SH "NAME" -pam_lastlog - PAM module to display date of last login -.SH "SYNOPSIS" -.HP 15 -\fBpam_lastlog\.so\fR [debug] [silent] [never] [nodate] [nohost] [noterm] [nowtmp] +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "Name" +pam_lastlog \- PAM module to display date of last login +.SH "Synopsis" +.fam C +.HP \w'\fBpam_lastlog\&.so\fR\ 'u +\fBpam_lastlog\&.so\fR [debug] [silent] [never] [nodate] [nohost] [noterm] [nowtmp] [noupdate] [showfailed] +.fam .SH "DESCRIPTION" .PP -pam_lastlog is a PAM module to display a line of information about the last login of the user\. In addition, the module maintains the -\fI/var/log/lastlog\fR -file\. +pam_lastlog is a PAM module to display a line of information about the last login of the user\&. In addition, the module maintains the +\FC/var/log/lastlog\F[] +file\&. .PP -Some applications may perform this function themselves\. In such cases, this module is not necessary\. +Some applications may perform this function themselves\&. In such cases, this module is not necessary\&. .SH "OPTIONS" .PP \fBdebug\fR .RS 4 -Print debug information\. +Print debug information\&. .RE .PP \fBsilent\fR .RS 4 -Don\'t inform the user about any previous login, just upate the -\fI/var/log/lastlog\fR -file\. +Don\'t inform the user about any previous login, just update the +\FC/var/log/lastlog\F[] +file\&. .RE .PP \fBnever\fR .RS 4 If the -\fI/var/log/lastlog\fR -file does not contain any old entries for the user, indicate that the user has never previously logged in with a welcome message\. +\FC/var/log/lastlog\F[] +file does not contain any old entries for the user, indicate that the user has never previously logged in with a welcome message\&. .RE .PP \fBnodate\fR .RS 4 -Don\'t display the date of the last login\. +Don\'t display the date of the last login\&. .RE .PP \fBnoterm\fR .RS 4 -Don\'t display the terminal name on which the last login was attempted\. +Don\'t display the terminal name on which the last login was attempted\&. .RE .PP \fBnohost\fR .RS 4 -Don\'t indicate from which host the last login was attempted\. +Don\'t indicate from which host the last login was attempted\&. .RE .PP \fBnowtmp\fR .RS 4 -Don\'t update the wtmp entry\. +Don\'t update the wtmp entry\&. +.RE +.PP +\fBnoupdate\fR +.RS 4 +Don\'t update any file\&. .RE -.SH "MODULE SERVICES PROVIDED" +.PP +\fBshowfailed\fR +.RS 4 +Display number of failed login attempts and the date of the last failed attempt from btmp\&. The date is not displayed when +\fBnodate\fR +is specified\&. +.RE +.SH "MODULE TYPES PROVIDED" .PP Only the \fBsession\fR -service is supported\. +module type is provided\&. .SH "RETURN VALUES" .PP .PP PAM_SUCCESS .RS 4 -Everything was successfull\. +Everything was successful\&. .RE .PP PAM_SERVICE_ERR .RS 4 -Internal service module error\. +Internal service module error\&. .RE .PP PAM_USER_UNKNOWN .RS 4 -User not known\. +User not known\&. .RE .SH "EXAMPLES" .PP Add the following line to -\fI/etc/pam\.d/login\fR +\FC/etc/pam\&.d/login\F[] to display the last login time of an user: .sp +.if n \{\ .RS 4 +.\} +.fam C +.ps -1 .nf - session required pam_lastlog\.so nowtmp +.if t \{\ +.sp -1 +.\} +.BB lightgray adjust-for-leading-newline +.sp -1 + + session required pam_lastlog\&.so nowtmp +.EB lightgray adjust-for-leading-newline +.if t \{\ +.sp 1 +.\} .fi +.fam +.ps +1 +.if n \{\ .RE +.\} .SH "FILES" .PP -\fI/var/log/lastlog\fR +\FC/var/log/lastlog\F[] .RS 4 Lastlog logging file .RE @@ -106,8 +294,8 @@ Lastlog logging file .PP \fBpam.conf\fR(5), -\fBpam.d\fR(8), +\fBpam.d\fR(5), \fBpam\fR(8) .SH "AUTHOR" .PP -pam_lastlog was written by Andrew G\. Morgan <morgan@kernel\.org>\. +pam_lastlog was written by Andrew G\&. Morgan <morgan@kernel\&.org>\&. diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml index 066eff58..2a6794ad 100644 --- a/modules/pam_lastlog/pam_lastlog.8.xml +++ b/modules/pam_lastlog/pam_lastlog.8.xml @@ -39,6 +39,12 @@ <arg choice="opt"> nowtmp </arg> + <arg choice="opt"> + noupdate + </arg> + <arg choice="opt"> + showfailed + </arg> </cmdsynopsis> </refsynopsisdiv> @@ -78,7 +84,7 @@ <listitem> <para> Don't inform the user about any previous login, - just upate the <filename>/var/log/lastlog</filename> file. + just update the <filename>/var/log/lastlog</filename> file. </para> </listitem> </varlistentry> @@ -137,13 +143,35 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term> + <option>noupdate</option> + </term> + <listitem> + <para> + Don't update any file. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <option>showfailed</option> + </term> + <listitem> + <para> + Display number of failed login attempts and the date of the + last failed attempt from btmp. The date is not displayed + when <option>nodate</option> is specified. + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> - <refsect1 id="pam_lastlog-services"> - <title>MODULE SERVICES PROVIDED</title> + <refsect1 id="pam_lastlog-types"> + <title>MODULE TYPES PROVIDED</title> <para> - Only the <option>session</option> service is supported. + Only the <option>session</option> module type is provided. </para> </refsect1> @@ -156,7 +184,7 @@ <term>PAM_SUCCESS</term> <listitem> <para> - Everything was successfull. + Everything was successful. </para> </listitem> </varlistentry> @@ -213,7 +241,7 @@ <refentrytitle>pam.conf</refentrytitle><manvolnum>5</manvolnum> </citerefentry>, <citerefentry> - <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum> + <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum> </citerefentry>, <citerefentry> <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum> diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index a75e1ce7..8af6b9eb 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -46,6 +46,10 @@ struct lastlog { }; #endif /* hpux */ +#ifndef _PATH_BTMP +# define _PATH_BTMP "/var/log/btmp" +#endif + /* XXX - time before ignoring lock. Is 1 sec enough? */ #define LASTLOG_IGNORE_LOCK_TIME 1 @@ -75,11 +79,13 @@ struct lastlog { #define LASTLOG_DEBUG 020 /* send info to syslog(3) */ #define LASTLOG_QUIET 040 /* keep quiet about things */ #define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */ +#define LASTLOG_BTMP 0200 /* display failed login info from btmp */ +#define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */ static int _pam_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) { - int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP); + int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP|LASTLOG_UPDATE); /* does the appliction require quiet? */ if (flags & PAM_SILENT) { @@ -105,6 +111,10 @@ _pam_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) ctrl |= LASTLOG_NEVER; } else if (!strcmp(*argv,"nowtmp")) { ctrl &= ~LASTLOG_WTMP; + } else if (!strcmp(*argv,"noupdate")) { + ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE); + } else if (!strcmp(*argv,"showfailed")) { + ctrl |= LASTLOG_BTMP; } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } @@ -135,7 +145,7 @@ get_tty(pam_handle_t *pamh) } static int -last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid) +last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t *lltime) { struct flock last_lock; struct lastlog last_login; @@ -166,6 +176,7 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid) last_lock.l_type = F_UNLCK; (void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */ + *lltime = last_login.ll_time; if (!last_login.ll_time) { if (announce & LASTLOG_DEBUG) { pam_syslog(pamh, LOG_DEBUG, @@ -216,8 +227,9 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid) } } - /* TRANSLATORS: "Last login: <date> from <host> on <terminal>" */ - retval = pam_info(pamh, _("Last login:%s%s%s"), + if (date != NULL || host != NULL || line != NULL) + /* TRANSLATORS: "Last login: <date> from <host> on <terminal>" */ + retval = pam_info(pamh, _("Last login:%s%s%s"), date ? date : "", host ? host : "", line ? line : ""); @@ -320,13 +332,13 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, } static int -last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) +last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user, time_t *lltime) { int retval; int last_fd; /* obtain the last login date and all the relevant info */ - last_fd = open(_PATH_LASTLOG, O_RDWR); + last_fd = open(_PATH_LASTLOG, announce&LASTLOG_UPDATE ? O_RDWR : O_RDONLY); if (last_fd < 0) { if (errno == ENOENT) { last_fd = open(_PATH_LASTLOG, O_RDWR|O_CREAT, @@ -353,7 +365,7 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) return PAM_SERVICE_ERR; } - retval = last_login_read(pamh, announce, last_fd, uid); + retval = last_login_read(pamh, announce, last_fd, uid, lltime); if (retval != PAM_SUCCESS) { close(last_fd); @@ -361,7 +373,9 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) return retval; } - retval = last_login_write(pamh, announce, last_fd, uid, user); + if (announce & LASTLOG_UPDATE) { + retval = last_login_write(pamh, announce, last_fd, uid, user); + } close(last_fd); D(("all done with last login")); @@ -369,6 +383,121 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) return retval; } +static int +last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t lltime) +{ + int retval; + int fd; + struct utmp ut; + struct utmp utuser; + int failed = 0; + char the_time[256]; + char *date = NULL; + char *host = NULL; + char *line = NULL; + + if (strlen(user) > UT_NAMESIZE) { + pam_syslog(pamh, LOG_WARNING, "username too long, output might be inaccurate"); + } + + /* obtain the failed login attempt records from btmp */ + fd = open(_PATH_BTMP, O_RDONLY); + if (fd < 0) { + pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", _PATH_BTMP); + D(("unable to open %s file", _PATH_BTMP)); + return PAM_SERVICE_ERR; + } + + while ((retval=pam_modutil_read(fd, (void *)&ut, + sizeof(ut))) == sizeof(ut)) { + if (ut.ut_tv.tv_sec >= lltime && strncmp(ut.ut_user, user, UT_NAMESIZE) == 0) { + memcpy(&utuser, &ut, sizeof(utuser)); + failed++; + } + } + + if (failed) { + /* we want the date? */ + if (announce & LASTLOG_DATE) { + struct tm *tm, tm_buf; + time_t lf_time; + + lf_time = utuser.ut_tv.tv_sec; + tm = localtime_r (&lf_time, &tm_buf); + strftime (the_time, sizeof (the_time), + /* TRANSLATORS: "strftime options for date of last login" */ + _(" %a %b %e %H:%M:%S %Z %Y"), tm); + + date = the_time; + } + + /* we want & have the host? */ + if ((announce & LASTLOG_HOST) + && (utuser.ut_host[0] != '\0')) { + /* TRANSLATORS: " from <host>" */ + if (asprintf(&host, _(" from %.*s"), UT_HOSTSIZE, + utuser.ut_host) < 0) { + pam_syslog(pamh, LOG_ERR, "out of memory"); + retval = PAM_BUF_ERR; + goto cleanup; + } + } + + /* we want and have the terminal? */ + if ((announce & LASTLOG_LINE) + && (utuser.ut_line[0] != '\0')) { + /* TRANSLATORS: " on <terminal>" */ + if (asprintf(&line, _(" on %.*s"), UT_LINESIZE, + utuser.ut_line) < 0) { + pam_syslog(pamh, LOG_ERR, "out of memory"); + retval = PAM_BUF_ERR; + goto cleanup; + } + } + + if (line != NULL || date != NULL || host != NULL) { + /* TRANSLATORS: "Last failed login: <date> from <host> on <terminal>" */ + pam_info(pamh, _("Last failed login:%s%s%s"), + date ? date : "", + host ? host : "", + line ? line : ""); + } + + _pam_drop(line); +#if defined HAVE_DNGETTEXT && defined ENABLE_NLS + retval = asprintf (&line, dngettext(PACKAGE, + "There was %d failed login attempt since the last successful login.", + "There were %d failed login attempts since the last successful login.", + failed), + failed); +#else + if (daysleft == 1) + retval = asprintf(&line, + _("There was %d failed login attempt since the last successful login."), + failed); + else + retval = asprintf(&line, + /* TRANSLATORS: only used if dngettext is not supported */ + _("There were %d failed login attempts since the last successful login."), + failed); +#endif + if (retval >= 0) + retval = pam_info(pamh, "%s", line); + else { + retval = PAM_BUF_ERR; + line = NULL; + } + } + +cleanup: + free(host); + free(line); + close(fd); + D(("all done with btmp")); + + return retval; +} + /* --- authentication management functions (only) --- */ PAM_EXTERN int @@ -379,6 +508,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, const void *user; const struct passwd *pwd; uid_t uid; + time_t lltime = 0; /* * this module gets the uid of the PAM_USER. Uses it to display @@ -407,7 +537,11 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, /* process the current login attempt (indicate last) */ - retval = last_login_date(pamh, ctrl, uid, user); + retval = last_login_date(pamh, ctrl, uid, user, &lltime); + + if ((ctrl & LASTLOG_BTMP) && retval == PAM_SUCCESS) { + retval = last_login_failed(pamh, ctrl, user, lltime); + } /* indicate success or failure */ |