diff options
Diffstat (limited to 'modules/pam_access')
-rw-r--r-- | modules/pam_access/Makefile.am | 7 | ||||
-rw-r--r-- | modules/pam_access/Makefile.in | 18 | ||||
-rw-r--r-- | modules/pam_access/README | 14 | ||||
-rw-r--r-- | modules/pam_access/README.xml | 32 | ||||
-rw-r--r-- | modules/pam_access/access.conf.5 | 10 | ||||
-rw-r--r-- | modules/pam_access/access.conf.5.xml | 22 | ||||
-rw-r--r-- | modules/pam_access/pam_access.8 | 22 | ||||
-rw-r--r-- | modules/pam_access/pam_access.8.xml | 92 | ||||
-rw-r--r-- | modules/pam_access/pam_access.c | 236 |
9 files changed, 321 insertions, 132 deletions
diff --git a/modules/pam_access/Makefile.am b/modules/pam_access/Makefile.am index 5723dd59..8af2852a 100644 --- a/modules/pam_access/Makefile.am +++ b/modules/pam_access/Makefile.am @@ -15,11 +15,14 @@ dist_check_SCRIPTS = tst-pam_access TESTS = $(dist_check_SCRIPTS) securelibdir = $(SECUREDIR) +if HAVE_VENDORDIR +secureconfdir = $(VENDOR_SCONFIGDIR) +else secureconfdir = $(SCONFIGDIR) +endif AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ - -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" \ - -DACCESS_CONF_GLOB=\"$(SCONFIGDIR)/access.d/*.conf\" $(WARN_CFLAGS) + $(WARN_CFLAGS) AM_LDFLAGS = -no-undefined -avoid-version -module if HAVE_VERSIONING AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map diff --git a/modules/pam_access/Makefile.in b/modules/pam_access/Makefile.in index 6f9abf45..9dadd2d3 100644 --- a/modules/pam_access/Makefile.in +++ b/modules/pam_access/Makefile.in @@ -431,6 +431,7 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ +DOCBOOK_RNG = @DOCBOOK_RNG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -443,11 +444,13 @@ EXEEXT = @EXEEXT@ EXE_CFLAGS = @EXE_CFLAGS@ EXE_LDFLAGS = @EXE_LDFLAGS@ FGREP = @FGREP@ +FILECMD = @FILECMD@ FO2PDF = @FO2PDF@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ +HTML_STYLESHEET = @HTML_STYLESHEET@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -479,12 +482,14 @@ LIBSELINUX = @LIBSELINUX@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ +LOGIND_CFLAGS = @LOGIND_CFLAGS@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ +MAN_STYLESHEET = @MAN_STYLESHEET@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ @@ -507,6 +512,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PDF_STYLESHEET = @PDF_STYLESHEET@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -517,12 +523,16 @@ SECUREDIR = @SECUREDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STRINGPARAM_HMAC = @STRINGPARAM_HMAC@ +STRINGPARAM_PROFILECONDITIONS = @STRINGPARAM_PROFILECONDITIONS@ STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@ STRIP = @STRIP@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIRPC_CFLAGS = @TIRPC_CFLAGS@ TIRPC_LIBS = @TIRPC_LIBS@ +TXT_STYLESHEET = @TXT_STYLESHEET@ USE_NLS = @USE_NLS@ +VENDOR_SCONFIGDIR = @VENDOR_SCONFIGDIR@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ XGETTEXT = @XGETTEXT@ @@ -596,10 +606,10 @@ XMLS = README.xml access.conf.5.xml pam_access.8.xml dist_check_SCRIPTS = tst-pam_access TESTS = $(dist_check_SCRIPTS) securelibdir = $(SECUREDIR) -secureconfdir = $(SCONFIGDIR) +@HAVE_VENDORDIR_FALSE@secureconfdir = $(SCONFIGDIR) +@HAVE_VENDORDIR_TRUE@secureconfdir = $(VENDOR_SCONFIGDIR) AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ - -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" \ - -DACCESS_CONF_GLOB=\"$(SCONFIGDIR)/access.d/*.conf\" $(WARN_CFLAGS) + $(WARN_CFLAGS) AM_LDFLAGS = -no-undefined -avoid-version -module $(am__append_1) securelib_LTLIBRARIES = pam_access.la diff --git a/modules/pam_access/README b/modules/pam_access/README index 26aad33e..891e7688 100644 --- a/modules/pam_access/README +++ b/modules/pam_access/README @@ -18,6 +18,20 @@ of parsing. This means that once a pattern is matched in some file no further files are parsed. If a config file is explicitly specified with the accessfile option the files in the above directory are not parsed. +By default rules for access management are taken from config file /etc/security +/access.conf or, if that one is not present, the file %vendordir%/security/ +access.conf. These settings can be overruled by setting in a config file +explicitly specified with the accessfile option. Then individual *.conf files +from the /etc/security/access.d/ and %vendordir%/security/access.d directories +are read. If /etc/security/access.d/@filename@.conf exists, then %vendordir%/ +security/access.d/@filename@.conf will not be used. All access.d/*.conf files +are sorted by their @filename@.conf in lexicographic order regardless of which +of the directories they reside in. The effect of the individual files is the +same as if all the files were concatenated together in the order of parsing. +This means that once a pattern is matched in some file no further files are +parsed. If a config file is explicitly specified with the accessfile option the +files in the above directories are not parsed. + If Linux PAM is compiled with audit support the module will report when it denies access based on origin (host, tty, etc.). diff --git a/modules/pam_access/README.xml b/modules/pam_access/README.xml index 8c7d078b..408aed00 100644 --- a/modules/pam_access/README.xml +++ b/modules/pam_access/README.xml @@ -1,39 +1,23 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" -"http://www.docbook.org/xml/4.3/docbookx.dtd" -[ -<!-- -<!ENTITY pamaccess SYSTEM "pam_access.8.xml"> ---> -<!-- -<!ENTITY accessconf SYSTEM "access.conf.5.xml"> ---> -]> +<article xmlns="http://docbook.org/ns/docbook" version="5.0"> -<article> - - <articleinfo> + <info> <title> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_access.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_access-name"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_access.8.xml" xpointer='xpointer(id("pam_access-name")/*)'/> </title> - </articleinfo> + </info> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_access.8.xml" xpointer='xpointer(//refsect1[@id = "pam_access-description"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_access.8.xml" xpointer='xpointer(id("pam_access-description")/*)'/> </section> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_access.8.xml" xpointer='xpointer(//refsect1[@id = "pam_access-options"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="pam_access.8.xml" xpointer='xpointer(id("pam_access-options")/*)'/> </section> <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="access.conf.5.xml" xpointer='xpointer(//refsect1[@id = "access.conf-examples"]/*)'/> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="access.conf.5.xml" xpointer='xpointer(id("access.conf-examples")/*)'/> </section> -</article> +</article>
\ No newline at end of file diff --git a/modules/pam_access/access.conf.5 b/modules/pam_access/access.conf.5 index 3204aedf..774e5cd9 100644 --- a/modules/pam_access/access.conf.5 +++ b/modules/pam_access/access.conf.5 @@ -1,13 +1,13 @@ '\" t .\" Title: access.conf .\" Author: [see the "AUTHORS" section] -.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 09/03/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/> +.\" Date: 05/07/2023 .\" Manual: Linux-PAM Manual -.\" Source: Linux-PAM Manual +.\" Source: [FIXME: source] .\" Language: English .\" -.TH "ACCESS\&.CONF" "5" "09/03/2021" "Linux-PAM Manual" "Linux\-PAM Manual" +.TH "ACCESS\&.CONF" "5" "05/07/2023" "[FIXME: source]" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -210,7 +210,7 @@ option, the spaces will become part of the actual item and the line will be most .PP \fBpam_access\fR(8), \fBpam.d\fR(5), -\fBpam\fR(8) +\fBpam\fR(7) .SH "AUTHORS" .PP Original diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml index 8fdbc31d..e1e5531f 100644 --- a/modules/pam_access/access.conf.5.xml +++ b/modules/pam_access/access.conf.5.xml @@ -1,8 +1,4 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" - "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> - -<refentry id="access.conf"> +<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="access.conf"> <refmeta> <refentrytitle>access.conf</refentrytitle> @@ -16,7 +12,7 @@ </refnamediv> - <refsect1 id='access.conf-description'> + <refsect1 xml:id="access.conf-description"> <title>DESCRIPTION</title> <para> The <filename>/etc/security/access.conf</filename> file specifies @@ -126,7 +122,7 @@ </refsect1> - <refsect1 id="access.conf-examples"> + <refsect1 xml:id="access.conf-examples"> <title>EXAMPLES</title> <para> These are some example lines which might be specified in @@ -135,7 +131,7 @@ <para> User <emphasis>root</emphasis> should be allowed to get access via - <emphasis>cron</emphasis>, X11 terminal <emphasis remap='I'>:0</emphasis>, + <emphasis>cron</emphasis>, X11 terminal <emphasis remap="I">:0</emphasis>, <emphasis>tty1</emphasis>, ..., <emphasis>tty5</emphasis>, <emphasis>tty6</emphasis>. </para> @@ -216,7 +212,7 @@ </refsect1> - <refsect1 id="access.conf-notes"> + <refsect1 xml:id="access.conf-notes"> <title>NOTES</title> <para> The default separators of list items in a field are space, ',', and tabulator @@ -228,16 +224,16 @@ </para> </refsect1> - <refsect1 id="access.conf-see_also"> + <refsect1 xml:id="access.conf-see_also"> <title>SEE ALSO</title> <para> <citerefentry><refentrytitle>pam_access</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>, - <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry> + <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>7</manvolnum></citerefentry> </para> </refsect1> - <refsect1 id="access.conf-author"> + <refsect1 xml:id="access.conf-author"> <title>AUTHORS</title> <para> Original <citerefentry><refentrytitle>login.access</refentrytitle><manvolnum>5</manvolnum></citerefentry> @@ -250,4 +246,4 @@ introduced by Mike Becher <mike.becher@lrz-muenchen.de>. </para> </refsect1> -</refentry> +</refentry>
\ No newline at end of file diff --git a/modules/pam_access/pam_access.8 b/modules/pam_access/pam_access.8 index 92de516d..5b0e1a3f 100644 --- a/modules/pam_access/pam_access.8 +++ b/modules/pam_access/pam_access.8 @@ -1,13 +1,13 @@ '\" t .\" Title: pam_access .\" Author: [see the "AUTHORS" section] -.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> -.\" Date: 09/03/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/> +.\" Date: 05/07/2023 .\" Manual: Linux-PAM Manual -.\" Source: Linux-PAM Manual +.\" Source: Linux-PAM .\" Language: English .\" -.TH "PAM_ACCESS" "8" "09/03/2021" "Linux-PAM Manual" "Linux-PAM Manual" +.TH "PAM_ACCESS" "8" "05/07/2023" "Linux\-PAM" "Linux\-PAM Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -51,25 +51,25 @@ option the files in the above directory are not parsed\&. If Linux PAM is compiled with audit support the module will report when it denies access based on origin (host, tty, etc\&.)\&. .SH "OPTIONS" .PP -\fBaccessfile=\fR\fB\fI/path/to/access\&.conf\fR\fR +accessfile=/path/to/access\&.conf .RS 4 Indicate an alternative access\&.conf style configuration file to override the default\&. This can be useful when different services need different access lists\&. .RE .PP -\fBdebug\fR +debug .RS 4 A lot of debug information is printed with \fBsyslog\fR(3)\&. .RE .PP -\fBnoaudit\fR +noaudit .RS 4 Do not report logins from disallowed hosts and ttys to the audit subsystem\&. .RE .PP -\fBfieldsep=\fR\fB\fIseparators\fR\fR +fieldsep=separators .RS 4 This option modifies the field separator character that pam_access will recognize when parsing the access configuration file\&. For example: \fBfieldsep=|\fR @@ -78,14 +78,14 @@ will cause the default `:\*(Aq character to be treated as part of a field value item is likely to be of the form "hostname:0" which includes a `:\*(Aq character in its value\&. But you should not need this\&. .RE .PP -\fBlistsep=\fR\fB\fIseparators\fR\fR +listsep=separators .RS 4 This option modifies the list separator character that pam_access will recognize when parsing the access configuration file\&. For example: \fBlistsep=,\fR will cause the default ` \*(Aq (space) and `\et\*(Aq (tab) characters to be treated as part of a list element value and `,\*(Aq becomes the only list element separator\&. Doing this may be useful on a system with group information obtained from a Windows domain, where the default built\-in groups "Domain Users", "Domain Admins" contain a space\&. .RE .PP -\fBnodefgroup\fR +nodefgroup .RS 4 User tokens which are not enclosed in parentheses will not be matched against the group database\&. The backwards compatible default is to try the group database match even for tokens not enclosed in parentheses\&. .RE @@ -133,7 +133,7 @@ Default configuration file .PP \fBaccess.conf\fR(5), \fBpam.d\fR(5), -\fBpam\fR(8)\&. +\fBpam\fR(7)\&. .SH "AUTHORS" .PP The logdaemon style login access control scheme was designed and implemented by Wietse Venema\&. The pam_access PAM module was developed by Alexei Nogin <alexei@nogin\&.dnttm\&.ru>\&. The IPv6 support and the network(address) / netmask feature was developed and provided by Mike Becher <mike\&.becher@lrz\-muenchen\&.de>\&. diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml index 9a6556cc..cc01d5ca 100644 --- a/modules/pam_access/pam_access.8.xml +++ b/modules/pam_access/pam_access.8.xml @@ -1,16 +1,13 @@ -<?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_access'> +<refentry xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="pam_access"> <refmeta> <refentrytitle>pam_access</refentrytitle> <manvolnum>8</manvolnum> - <refmiscinfo class='setdesc'>Linux-PAM Manual</refmiscinfo> + <refmiscinfo class="source">Linux-PAM</refmiscinfo> + <refmiscinfo class="manual">Linux-PAM Manual</refmiscinfo> </refmeta> - <refnamediv id='pam_access-name'> + <refnamediv xml:id="pam_access-name"> <refname>pam_access</refname> <refpurpose> PAM module for logdaemon style login access control @@ -20,31 +17,31 @@ <!-- body begins here --> <refsynopsisdiv> - <cmdsynopsis id="pam_access-cmdsynopsis"> + <cmdsynopsis xml:id="pam_access-cmdsynopsis" sepchar=" "> <command>pam_access.so</command> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> debug </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> nodefgroup </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> noaudit </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> accessfile=<replaceable>file</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> fieldsep=<replaceable>sep</replaceable> </arg> - <arg choice="opt"> + <arg choice="opt" rep="norepeat"> listsep=<replaceable>sep</replaceable> </arg> </cmdsynopsis> </refsynopsisdiv> - <refsect1 id="pam_access-description"> + <refsect1 xml:id="pam_access-description"> <title>DESCRIPTION</title> <para> The pam_access PAM module is mainly for access management. @@ -53,7 +50,7 @@ or on terminal line names, X <varname>$DISPLAY</varname> values, or PAM service names in case of non-networked logins. </para> - <para> + <para condition="without_vendordir"> By default rules for access management are taken from config file <filename>/etc/security/access.conf</filename> if you don't specify another file. @@ -66,19 +63,39 @@ If a config file is explicitly specified with the <option>accessfile</option> option the files in the above directory are not parsed. </para> + <para condition="with_vendordir"> + By default rules for access management are taken from config file + <filename>/etc/security/access.conf</filename> or, if that one is not + present, the file <filename>%vendordir%/security/access.conf</filename>. + These settings can be overruled by setting in a config file explicitly + specified with the <option>accessfile</option> option. + Then individual <filename>*.conf</filename> files from the + <filename>/etc/security/access.d/</filename> and + <filename>%vendordir%/security/access.d</filename> directories are read. + If <filename>/etc/security/access.d/@filename@.conf</filename> exists, then + <filename>%vendordir%/security/access.d/@filename@.conf</filename> will not be used. + All <filename>access.d/*.conf</filename> files are sorted by their + <filename>@filename@.conf</filename> in lexicographic order regardless of which + of the directories they reside in. + The effect of the individual files is the same as if all the files were + concatenated together in the order of parsing. This means that once + a pattern is matched in some file no further files are parsed. + If a config file is explicitly specified with the <option>accessfile</option> + option the files in the above directories are not parsed. + </para> <para> If Linux PAM is compiled with audit support the module will report when it denies access based on origin (host, tty, etc.). </para> </refsect1> - <refsect1 id="pam_access-options"> + <refsect1 xml:id="pam_access-options"> <title>OPTIONS</title> <variablelist> <varlistentry> <term> - <option>accessfile=<replaceable>/path/to/access.conf</replaceable></option> + accessfile=/path/to/access.conf </term> <listitem> <para> @@ -91,7 +108,7 @@ <varlistentry> <term> - <option>debug</option> + debug </term> <listitem> <para> @@ -103,7 +120,7 @@ <varlistentry> <term> - <option>noaudit</option> + noaudit </term> <listitem> <para> @@ -114,19 +131,19 @@ <varlistentry> <term> - <option>fieldsep=<replaceable>separators</replaceable></option> + fieldsep=separators </term> <listitem> <para> This option modifies the field separator character that pam_access will recognize when parsing the access configuration file. For example: - <emphasis remap='B'>fieldsep=|</emphasis> will cause the + <emphasis remap="B">fieldsep=|</emphasis> will cause the default `:' character to be treated as part of a field value and `|' becomes the field separator. Doing this may be useful in conjunction with a system that wants to use pam_access with X based applications, since the - <emphasis remap='B'>PAM_TTY</emphasis> item is likely to be + <emphasis remap="B">PAM_TTY</emphasis> item is likely to be of the form "hostname:0" which includes a `:' character in its value. But you should not need this. </para> @@ -135,14 +152,14 @@ <varlistentry> <term> - <option>listsep=<replaceable>separators</replaceable></option> + listsep=separators </term> <listitem> <para> This option modifies the list separator character that pam_access will recognize when parsing the access configuration file. For example: - <emphasis remap='B'>listsep=,</emphasis> will cause the + <emphasis remap="B">listsep=,</emphasis> will cause the default ` ' (space) and `\t' (tab) characters to be treated as part of a list element value and `,' becomes the only list element separator. Doing this may be useful on a system @@ -155,7 +172,7 @@ <varlistentry> <term> - <option>nodefgroup</option> + nodefgroup </term> <listitem> <para> @@ -170,7 +187,7 @@ </variablelist> </refsect1> - <refsect1 id="pam_access-types"> + <refsect1 xml:id="pam_access-types"> <title>MODULE TYPES PROVIDED</title> <para> All module types (<option>auth</option>, <option>account</option>, @@ -178,7 +195,7 @@ </para> </refsect1> - <refsect1 id="pam_access-return_values"> + <refsect1 xml:id="pam_access-return_values"> <title>RETURN VALUES</title> <variablelist> <varlistentry> @@ -224,19 +241,26 @@ </variablelist> </refsect1> - <refsect1 id="pam_access-files"> + <refsect1 xml:id="pam_access-files"> <title>FILES</title> <variablelist> <varlistentry> - <term><filename>/etc/security/access.conf</filename></term> + <term>/etc/security/access.conf</term> <listitem> <para>Default configuration file</para> </listitem> </varlistentry> + <varlistentry condition="with_vendordir"> + <term>%vendordir%/security/access.conf</term> + <listitem> + <para>Default configuration file if + <filename>/etc/security/access.conf</filename> does not exist.</para> + </listitem> + </varlistentry> </variablelist> </refsect1> - <refsect1 id="pam_access-see_also"> + <refsect1 xml:id="pam_access-see_also"> <title>SEE ALSO</title> <para> <citerefentry> @@ -246,12 +270,12 @@ <refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum> </citerefentry>, <citerefentry> - <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum> + <refentrytitle>pam</refentrytitle><manvolnum>7</manvolnum> </citerefentry>. </para> </refsect1> - <refsect1 id="pam_access-authors"> + <refsect1 xml:id="pam_access-authors"> <title>AUTHORS</title> <para> The logdaemon style login access control scheme was designed and implemented by @@ -262,4 +286,4 @@ was developed and provided by Mike Becher <mike.becher@lrz-muenchen.de>. </para> </refsect1> -</refentry> +</refentry>
\ No newline at end of file diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c index 277192b9..f70b7e49 100644 --- a/modules/pam_access/pam_access.c +++ b/modules/pam_access/pam_access.c @@ -56,6 +56,13 @@ #include "pam_cc_compat.h" #include "pam_inline.h" +#define PAM_ACCESS_CONFIG (SCONFIGDIR "/access.conf") +#define ACCESS_CONF_GLOB (SCONFIGDIR "/access.d/*.conf") +#ifdef VENDOR_SCONFIGDIR +#define VENDOR_PAM_ACCESS_CONFIG (VENDOR_SCONFIGDIR "/access.conf") +#define VENDOR_ACCESS_CONF_GLOB (VENDOR_SCONFIGDIR "/access.d/*.conf") +#endif + /* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */ /* @@ -151,6 +158,95 @@ parse_args(pam_handle_t *pamh, struct login_info *loginfo, return 1; /* OK */ } +/* --- evaluting all files in VENDORDIR/security/access.d and /etc/security/access.d --- */ +static const char *base_name(const char *path) +{ + const char *base = strrchr(path, '/'); + return base ? base+1 : path; +} + +static int +compare_filename(const void *a, const void *b) +{ + return strcmp(base_name(* (const char * const *) a), + base_name(* (const char * const *) b)); +} + +/* Evaluating a list of files which have to be parsed in the right order: + * + * - If etc/security/access.d/@filename@.conf exists, then + * %vendordir%/security/access.d/@filename@.conf should not be used. + * - All files in both access.d directories are sorted by their @filename@.conf in + * lexicographic order regardless of which of the directories they reside in. */ +static char **read_access_dir(pam_handle_t *pamh) +{ + glob_t globbuf; + size_t i=0; + int glob_rv = glob(ACCESS_CONF_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf); + char **file_list; + size_t file_list_size = glob_rv == 0 ? globbuf.gl_pathc : 0; + +#ifdef VENDOR_ACCESS_CONF_GLOB + glob_t globbuf_vendor; + int glob_rv_vendor = glob(VENDOR_ACCESS_CONF_GLOB, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf_vendor); + if (glob_rv_vendor == 0) + file_list_size += globbuf_vendor.gl_pathc; +#endif + file_list = malloc((file_list_size + 1) * sizeof(char*)); + if (file_list == NULL) { + pam_syslog(pamh, LOG_ERR, "Cannot allocate memory for file list: %m"); +#ifdef VENDOR_ACCESS_CONF_GLOB + if (glob_rv_vendor == 0) + globfree(&globbuf_vendor); +#endif + if (glob_rv == 0) + globfree(&globbuf); + return NULL; + } + + if (glob_rv == 0) { + for (i = 0; i < globbuf.gl_pathc; i++) { + file_list[i] = strdup(globbuf.gl_pathv[i]); + if (file_list[i] == NULL) { + pam_syslog(pamh, LOG_ERR, "strdup failed: %m"); + break; + } + } + } +#ifdef VENDOR_ACCESS_CONF_GLOB + if (glob_rv_vendor == 0) { + for (size_t j = 0; j < globbuf_vendor.gl_pathc; j++) { + if (glob_rv == 0 && globbuf.gl_pathc > 0) { + int double_found = 0; + for (size_t k = 0; k < globbuf.gl_pathc; k++) { + if (strcmp(base_name(globbuf.gl_pathv[k]), + base_name(globbuf_vendor.gl_pathv[j])) == 0) { + double_found = 1; + break; + } + } + if (double_found) + continue; + } + file_list[i] = strdup(globbuf_vendor.gl_pathv[j]); + if (file_list[i] == NULL) { + pam_syslog(pamh, LOG_ERR, "strdup failed: %m"); + break; + } + i++; + } + globfree(&globbuf_vendor); + } +#endif + file_list[i] = NULL; + qsort(file_list, i, sizeof(char *), compare_filename); + + if (glob_rv == 0) + globfree(&globbuf); + + return file_list; +} + /* --- static functions for checking whether the user should be let in --- */ typedef int match_func (pam_handle_t *, char *, struct login_info *); @@ -567,7 +663,7 @@ static int group_match (pam_handle_t *pamh, const char *tok, const char* usr, int debug) { - char grptok[BUFSIZ]; + char grptok[BUFSIZ] = {}; if (debug) pam_syslog (pamh, LOG_DEBUG, @@ -577,7 +673,6 @@ group_match (pam_handle_t *pamh, const char *tok, const char* usr, return NO; /* token is received under the format '(...)' */ - memset(grptok, 0, BUFSIZ); strncpy(grptok, tok + 1, strlen(tok) - 2); if (pam_modutil_user_in_group_nam_nam(pamh, usr, grptok)) @@ -637,7 +732,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) if ((str_len = strlen(string)) > tok_len && strcasecmp(tok, string + str_len - tok_len) == 0) return YES; - } else if (tok[tok_len - 1] == '.') { + } else if (tok[tok_len - 1] == '.') { /* internet network numbers (end with ".") */ struct addrinfo hint; memset (&hint, '\0', sizeof (hint)); @@ -678,7 +773,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) return NO; } - /* Assume network/netmask with an IP of a host. */ + /* Assume network/netmask, IP address or hostname. */ return network_netmask_match(pamh, tok, string, item); } @@ -696,7 +791,7 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, /* * If the token has the magic value "ALL" the match always succeeds. * Otherwise, return YES if the token fully matches the string. - * "NONE" token matches NULL string. + * "NONE" token matches NULL string. */ if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ @@ -714,7 +809,8 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, /* network_netmask_match - match a string against one token * where string is a hostname or ip (v4,v6) address and tok - * represents either a single ip (v4,v6) address or a network/netmask + * represents either a hostname, a single ip (v4,v6) address + * or a network/netmask */ static int network_netmask_match (pam_handle_t *pamh, @@ -723,10 +819,12 @@ network_netmask_match (pam_handle_t *pamh, char *netmask_ptr; char netmask_string[MAXHOSTNAMELEN + 1]; int addr_type; + struct addrinfo *ai = NULL; if (item->debug) - pam_syslog (pamh, LOG_DEBUG, + pam_syslog (pamh, LOG_DEBUG, "network_netmask_match: tok=%s, item=%s", tok, string); + /* OK, check if tok is of type addr/mask */ if ((netmask_ptr = strchr(tok, '/')) != NULL) { @@ -760,54 +858,108 @@ network_netmask_match (pam_handle_t *pamh, netmask_ptr = number_to_netmask(netmask, addr_type, netmask_string, MAXHOSTNAMELEN); } - } + + /* + * Construct an addrinfo list from the IP address. + * This should not fail as the input is a correct IP address... + */ + if (getaddrinfo (tok, NULL, NULL, &ai) != 0) + { + return NO; + } + } else - /* NO, then check if it is only an addr */ - if (isipaddr(tok, NULL, NULL) != YES) + { + /* + * It is either an IP address or a hostname. + * Let getaddrinfo sort everything out + */ + if (getaddrinfo (tok, NULL, NULL, &ai) != 0) { + pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok); + return NO; } + netmask_ptr = NULL; + } if (isipaddr(string, NULL, NULL) != YES) { - /* Assume network/netmask with a name of a host. */ struct addrinfo hint; + /* Assume network/netmask with a name of a host. */ memset (&hint, '\0', sizeof (hint)); hint.ai_flags = AI_CANONNAME; hint.ai_family = AF_UNSPEC; if (item->gai_rv != 0) + { + freeaddrinfo(ai); return NO; + } else if (!item->res && (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0) + { + freeaddrinfo(ai); return NO; + } else { struct addrinfo *runp = item->res; + struct addrinfo *runp1; while (runp != NULL) { char buf[INET6_ADDRSTRLEN]; - DIAG_PUSH_IGNORE_CAST_ALIGN; - inet_ntop (runp->ai_family, - runp->ai_family == AF_INET - ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr - : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, - buf, sizeof (buf)); - DIAG_POP_IGNORE_CAST_ALIGN; + if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0) + { + freeaddrinfo(ai); + return NO; + } - if (are_addresses_equal(buf, tok, netmask_ptr)) + for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) { - return YES; + char buf1[INET6_ADDRSTRLEN]; + + if (runp->ai_family != runp1->ai_family) + continue; + + if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0) + { + freeaddrinfo(ai); + return NO; + } + + if (are_addresses_equal (buf, buf1, netmask_ptr)) + { + freeaddrinfo(ai); + return YES; + } } runp = runp->ai_next; } } } else - return (are_addresses_equal(string, tok, netmask_ptr)); + { + struct addrinfo *runp1; + + for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) + { + char buf1[INET6_ADDRSTRLEN]; + + (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST); + + if (are_addresses_equal(string, buf1, netmask_ptr)) + { + freeaddrinfo(ai); + return YES; + } + } + } + + freeaddrinfo(ai); return NO; } @@ -828,7 +980,6 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, char hostname[MAXHOSTNAMELEN + 1]; int rv; - /* set username */ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) { @@ -853,6 +1004,18 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, return PAM_ABORT; } +#ifdef VENDOR_PAM_ACCESS_CONFIG + if (loginfo.config_file == default_config) { + /* Check whether PAM_ACCESS_CONFIG file is available. + * If it does not exist, fall back to VENDOR_PAM_ACCESS_CONFIG file. */ + struct stat buffer; + if (stat(loginfo.config_file, &buffer) != 0 && errno == ENOENT) { + default_config = VENDOR_PAM_ACCESS_CONFIG; + loginfo.config_file = default_config; + } + } +#endif + /* remote host name */ if (pam_get_item(pamh, PAM_RHOST, &void_from) @@ -916,23 +1079,18 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, rv = login_access(pamh, &loginfo); if (rv == NOMATCH && loginfo.config_file == default_config) { - glob_t globbuf; - int i, glob_rv; - - /* We do not manipulate locale as setlocale() is not - * thread safe. We could use uselocale() in future. - */ - glob_rv = glob(ACCESS_CONF_GLOB, GLOB_ERR, NULL, &globbuf); - if (!glob_rv) { - /* Parse the *.conf files. */ - for (i = 0; globbuf.gl_pathv[i] != NULL; i++) { - loginfo.config_file = globbuf.gl_pathv[i]; - rv = login_access(pamh, &loginfo); - if (rv != NOMATCH) - break; - } - globfree(&globbuf); - } + char **filename_list = read_access_dir(pamh); + if (filename_list != NULL) { + for (int i = 0; filename_list[i] != NULL; i++) { + loginfo.config_file = filename_list[i]; + rv = login_access(pamh, &loginfo); + if (rv != NOMATCH) + break; + } + for (int i = 0; filename_list[i] != NULL; i++) + free(filename_list[i]); + free(filename_list); + } } if (loginfo.gai_rv == 0 && loginfo.res) |