f2fdff
diff -up Linux-PAM-1.1.8/modules/pam_access/access.conf.access-update Linux-PAM-1.1.8/modules/pam_access/access.conf
f2fdff
--- Linux-PAM-1.1.8/modules/pam_access/access.conf.access-update	2013-06-18 16:11:21.000000000 +0200
f2fdff
+++ Linux-PAM-1.1.8/modules/pam_access/access.conf	2017-09-08 14:06:16.420102221 +0200
f2fdff
@@ -18,7 +18,7 @@
f2fdff
 # pam_access with X applications that provide PAM_TTY values that are
f2fdff
 # the display variable like "host:0".]
f2fdff
 #
f2fdff
-# 	permission : users : origins
f2fdff
+# 	permission:users:origins
f2fdff
 #
f2fdff
 # The first field should be a "+" (access granted) or "-" (access denied)
f2fdff
 # character.
f2fdff
@@ -79,44 +79,44 @@
f2fdff
 ##############################################################################
f2fdff
 #
f2fdff
 # User "root" should be allowed to get access via cron .. tty5 tty6.
f2fdff
-#+ : root : cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6
f2fdff
+#+:root:cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6
f2fdff
 #
f2fdff
 # User "root" should be allowed to get access from hosts with ip addresses.
f2fdff
-#+ : root : 192.168.200.1 192.168.200.4 192.168.200.9
f2fdff
-#+ : root : 127.0.0.1
f2fdff
+#+:root:192.168.200.1 192.168.200.4 192.168.200.9
f2fdff
+#+:root:127.0.0.1
f2fdff
 #
f2fdff
 # User "root" should get access from network 192.168.201.
f2fdff
 # This term will be evaluated by string matching.
f2fdff
 # comment: It might be better to use network/netmask instead.
f2fdff
 #          The same is 192.168.201.0/24 or 192.168.201.0/255.255.255.0
f2fdff
-#+ : root : 192.168.201.
f2fdff
+#+:root:192.168.201.
f2fdff
 #
f2fdff
 # User "root" should be able to have access from domain.
f2fdff
 # Uses string matching also.
f2fdff
-#+ : root : .foo.bar.org
f2fdff
+#+:root:.foo.bar.org
f2fdff
 #
f2fdff
 # User "root" should be denied to get access from all other sources.
f2fdff
-#- : root : ALL
f2fdff
+#-:root:ALL
f2fdff
 #
f2fdff
 # User "foo" and members of netgroup "nis_group" should be
f2fdff
 # allowed to get access from all sources.
f2fdff
 # This will only work if netgroup service is available.
f2fdff
-#+ : @nis_group foo : ALL
f2fdff
+#+:@nis_group foo:ALL
f2fdff
 #
f2fdff
 # User "john" should get access from ipv4 net/mask
f2fdff
-#+ : john : 127.0.0.0/24
f2fdff
+#+:john:127.0.0.0/24
f2fdff
 #
f2fdff
 # User "john" should get access from ipv4 as ipv6 net/mask
f2fdff
-#+ : john : ::ffff:127.0.0.0/127
f2fdff
+#+:john:::ffff:127.0.0.0/127
f2fdff
 #
f2fdff
 # User "john" should get access from ipv6 host address
f2fdff
-#+ : john : 2001:4ca0:0:101::1
f2fdff
+#+:john:2001:4ca0:0:101::1
f2fdff
 #
f2fdff
 # User "john" should get access from ipv6 host address (same as above)
f2fdff
-#+ : john : 2001:4ca0:0:101:0:0:0:1
f2fdff
+#+:john:2001:4ca0:0:101:0:0:0:1
f2fdff
 #
f2fdff
 # User "john" should get access from ipv6 net/mask
f2fdff
-#+ : john : 2001:4ca0:0:101::/64
f2fdff
+#+:john:2001:4ca0:0:101::/64
f2fdff
 #
f2fdff
 # All other users should be denied to get access from all sources.
f2fdff
-#- : ALL : ALL
f2fdff
+#-:ALL:ALL
f2fdff
diff -up Linux-PAM-1.1.8/modules/pam_access/access.conf.5.xml.access-update Linux-PAM-1.1.8/modules/pam_access/access.conf.5.xml
f2fdff
--- Linux-PAM-1.1.8/modules/pam_access/access.conf.5.xml.access-update	2013-06-18 16:11:21.000000000 +0200
f2fdff
+++ Linux-PAM-1.1.8/modules/pam_access/access.conf.5.xml	2017-09-08 14:05:41.126320653 +0200
f2fdff
@@ -21,8 +21,12 @@
f2fdff
     <para>
f2fdff
       The <filename>/etc/security/access.conf</filename> file specifies
f2fdff
       (<replaceable>user/group</replaceable>, <replaceable>host</replaceable>),
f2fdff
-      (<replaceable>user/group</replaceable>, <replaceable>network/netmask</replaceable>) or
f2fdff
-      (<replaceable>user/group</replaceable>, <replaceable>tty</replaceable>)
f2fdff
+      (<replaceable>user/group</replaceable>, <replaceable>network/netmask</replaceable>),
f2fdff
+      (<replaceable>user/group</replaceable>, <replaceable>tty</replaceable>),
f2fdff
+      (<replaceable>user/group</replaceable>,
f2fdff
+      <replaceable>X-$DISPLAY-value</replaceable>), or
f2fdff
+      (<replaceable>user/group</replaceable>,
f2fdff
+      <replaceable>pam-service-name</replaceable>)
f2fdff
       combinations for which a login will be either accepted or refused.
f2fdff
     </para>
f2fdff
     <para>
f2fdff
@@ -33,7 +37,14 @@
f2fdff
       combination, or, in case of non-networked logins, the first entry
f2fdff
       that matches the
f2fdff
       (<replaceable>user/group</replaceable>, <replaceable>tty</replaceable>)
f2fdff
-      combination.  The permissions field of that table entry determines
f2fdff
+      combination, or in the case of non-networked logins without a
f2fdff
+      tty, the first entry that matches the
f2fdff
+      (<replaceable>user/group</replaceable>,
f2fdff
+      <replaceable>X-$DISPLAY-value</replaceable>) or
f2fdff
+      (<replaceable>user/group</replaceable>,
f2fdff
+      <replaceable>pam-service-name/</replaceable>)
f2fdff
+      combination.  The permissions field of that table entry
f2fdff
+      determines
f2fdff
       whether the login will be accepted or refused.
f2fdff
    </para>
f2fdff
 
f2fdff
@@ -65,14 +76,27 @@
f2fdff
     <para>
f2fdff
       The third field, the <replaceable>origins</replaceable>
f2fdff
       field, should be a list of one or more tty names (for non-networked
f2fdff
-      logins), host names, domain names (begin with "."), host addresses,
f2fdff
+      logins), X <varname>$DISPLAY</varname> values or PAM service
f2fdff
+      names (for non-networked logins without a tty), host names,
f2fdff
+      domain names (begin with "."), host addresses,
f2fdff
       internet network numbers (end with "."), internet network addresses
f2fdff
       with network mask (where network mask can be a decimal number or an
f2fdff
       internet address also), <emphasis>ALL</emphasis> (which always matches)
f2fdff
-      or <emphasis>LOCAL</emphasis>. <emphasis>LOCAL</emphasis>
f2fdff
-      keyword matches if and only if the <emphasis>PAM_RHOST</emphasis> is
f2fdff
-      not set and <origin> field is thus set from
f2fdff
-      <emphasis>PAM_TTY</emphasis> or <emphasis>PAM_SERVICE</emphasis>".
f2fdff
+      or <emphasis>LOCAL</emphasis>. The <emphasis>LOCAL</emphasis>
f2fdff
+      keyword matches if and only if
f2fdff
+      <citerefentry><refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
f2fdff
+      when called with an <parameter>item_type</parameter> of
f2fdff
+      <emphasis>PAM_RHOST</emphasis>, returns NULL or an
f2fdff
+      empty string (and therefore the
f2fdff
+      <replaceable>origins</replaceable> field is compared against the
f2fdff
+      return value of
f2fdff
+      <citerefentry><refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum></citerefentry>
f2fdff
+      called with an <parameter>item_type</parameter> of
f2fdff
+      <emphasis>PAM_TTY</emphasis> or, absent that,
f2fdff
+      <emphasis>PAM_SERVICE</emphasis>).
f2fdff
+    </para>
f2fdff
+
f2fdff
+    <para>
f2fdff
       If supported by the system you can use
f2fdff
       <emphasis>@netgroupname</emphasis> in host or user patterns. The
f2fdff
       <emphasis>@@netgroupname</emphasis> syntax is supported in the user
f2fdff
@@ -115,7 +139,7 @@
f2fdff
       <emphasis>tty1</emphasis>, ..., <emphasis>tty5</emphasis>,
f2fdff
       <emphasis>tty6</emphasis>.
f2fdff
     </para>
f2fdff
-    <para>+ : root : crond :0 tty1 tty2 tty3 tty4 tty5 tty6</para>
f2fdff
+    <para>+:root:crond :0 tty1 tty2 tty3 tty4 tty5 tty6</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>root</emphasis> should be allowed to get access from
f2fdff
@@ -123,8 +147,8 @@
f2fdff
       connection have to be a IPv4 one, a IPv6 connection from a host with
f2fdff
       one of this IPv4 addresses does work, too.
f2fdff
     </para>
f2fdff
-    <para>+ : root : 192.168.200.1 192.168.200.4 192.168.200.9</para>
f2fdff
-    <para>+ : root : 127.0.0.1</para>
f2fdff
+    <para>+:root:192.168.200.1 192.168.200.4 192.168.200.9</para>
f2fdff
+    <para>+:root:127.0.0.1</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>root</emphasis> should get access from network
f2fdff
@@ -134,44 +158,44 @@
f2fdff
       <emphasis>192.168.201.0/24</emphasis> or
f2fdff
       <emphasis>192.168.201.0/255.255.255.0</emphasis>.
f2fdff
     </para>
f2fdff
-    <para>+ : root : 192.168.201.</para>
f2fdff
+    <para>+:root:192.168.201.</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>root</emphasis> should be able to have access from hosts
f2fdff
       <emphasis>foo1.bar.org</emphasis> and <emphasis>foo2.bar.org</emphasis>
f2fdff
       (uses string matching also).
f2fdff
     </para>
f2fdff
-    <para>+ : root : foo1.bar.org foo2.bar.org</para>
f2fdff
+    <para>+:root:foo1.bar.org foo2.bar.org</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>root</emphasis> should be able to have access from
f2fdff
       domain <emphasis>foo.bar.org</emphasis> (uses string matching also).
f2fdff
     </para>
f2fdff
-    <para>+ : root : .foo.bar.org</para>
f2fdff
+    <para>+:root:.foo.bar.org</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>root</emphasis> should be denied to get access
f2fdff
       from all other sources.
f2fdff
     </para>
f2fdff
-    <para>- : root : ALL</para>
f2fdff
+    <para>-:root:ALL</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>foo</emphasis> and members of netgroup
f2fdff
       <emphasis>admins</emphasis> should be allowed to get access
f2fdff
       from all sources. This will only work if netgroup service is available.
f2fdff
     </para>
f2fdff
-    <para>+ : @admins foo : ALL</para>
f2fdff
+    <para>+:@admins foo:ALL</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>john</emphasis> and <emphasis>foo</emphasis>
f2fdff
       should get access from IPv6 host address.
f2fdff
     </para>
f2fdff
-    <para>+ : john foo : 2001:db8:0:101::1</para>
f2fdff
+    <para>+:john foo:2001:db8:0:101::1</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       User <emphasis>john</emphasis> should get access from IPv6 net/mask.
f2fdff
     </para>
f2fdff
-    <para>+ : john : 2001:db8:0:101::/64</para>
f2fdff
+    <para>+:john:2001:db8:0:101::/64</para>
f2fdff
 
f2fdff
     <para>
f2fdff
       Disallow console logins to all but the shutdown, sync and all
f2fdff
@@ -182,10 +206,22 @@
f2fdff
     <para>
f2fdff
       All other users should be denied to get access from all sources.
f2fdff
     </para>
f2fdff
-    <para>- : ALL : ALL</para>
f2fdff
+    <para>-:ALL:ALL</para>
f2fdff
 
f2fdff
   </refsect1>
f2fdff
 
f2fdff
+  <refsect1 id="access.conf-notes">
f2fdff
+    <title>NOTES</title>
f2fdff
+    <para>
f2fdff
+      The default separators of list items in a field are space, ',', and tabulator
f2fdff
+      characters. Thus conveniently if spaces are put at the beginning and the end of
f2fdff
+      the fields they are ignored. However if the list separator is changed with the
f2fdff
+      <emphasis>listsep</emphasis> option, the spaces will become part of the actual
f2fdff
+      item and the line will be most probably ignored. For this reason, it is not
f2fdff
+      recommended to put spaces around the ':' characters.
f2fdff
+    </para>
f2fdff
+  </refsect1>
f2fdff
+
f2fdff
   <refsect1 id="access.conf-see_also">
f2fdff
     <title>SEE ALSO</title>
f2fdff
     <para>
f2fdff
diff -up Linux-PAM-1.1.8/modules/pam_access/Makefile.am.access-update Linux-PAM-1.1.8/modules/pam_access/Makefile.am
f2fdff
--- Linux-PAM-1.1.8/modules/pam_access/Makefile.am.access-update	2013-06-18 16:11:21.000000000 +0200
f2fdff
+++ Linux-PAM-1.1.8/modules/pam_access/Makefile.am	2017-09-08 14:10:47.223163175 +0200
f2fdff
@@ -15,7 +15,8 @@ securelibdir = $(SECUREDIR)
f2fdff
 secureconfdir = $(SCONFIGDIR)
f2fdff
 
f2fdff
 AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
f2fdff
-	-DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" $(NIS_CFLAGS)
f2fdff
+	-DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" \
f2fdff
+	-DACCESS_CONF_GLOB=\"$(SCONFIGDIR)/access.d/*.conf\" $(NIS_CFLAGS)
f2fdff
 AM_LDFLAGS =  -no-undefined -avoid-version -module
f2fdff
 if HAVE_VERSIONING
f2fdff
   AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
f2fdff
diff -up Linux-PAM-1.1.8/modules/pam_access/pam_access.c.access-update Linux-PAM-1.1.8/modules/pam_access/pam_access.c
f2fdff
--- Linux-PAM-1.1.8/modules/pam_access/pam_access.c.access-update	2013-06-18 16:11:21.000000000 +0200
f2fdff
+++ Linux-PAM-1.1.8/modules/pam_access/pam_access.c	2017-09-08 14:03:45.620762824 +0200
f2fdff
@@ -44,6 +44,7 @@
f2fdff
 #include <arpa/inet.h>
f2fdff
 #include <netdb.h>
f2fdff
 #include <sys/socket.h>
f2fdff
+#include <glob.h>
f2fdff
 #ifdef HAVE_RPCSVC_YPCLNT_H
f2fdff
 #include <rpcsvc/ypclnt.h>
f2fdff
 #endif
f2fdff
@@ -90,6 +91,7 @@
f2fdff
 #define ALL             2
f2fdff
 #define YES             1
f2fdff
 #define NO              0
f2fdff
+#define NOMATCH        -1
f2fdff
 
f2fdff
  /*
f2fdff
   * A structure to bundle up all login-related information to keep the
f2fdff
@@ -412,13 +414,17 @@ login_access (pam_handle_t *pamh, struct
f2fdff
 	return NO;
f2fdff
     }
f2fdff
 #ifdef HAVE_LIBAUDIT
f2fdff
-    if (!item->noaudit && line[0] == '-' && (match == YES || (match == ALL &&
f2fdff
-	nonall_match == YES))) {
f2fdff
+    if (!item->noaudit && (match == YES || (match == ALL &&
f2fdff
+	nonall_match == YES)) && line[0] == '-') {
f2fdff
 	pam_modutil_audit_write(pamh, AUDIT_ANOM_LOGIN_LOCATION,
f2fdff
 	    "pam_access", 0);
f2fdff
     }
f2fdff
 #endif
f2fdff
-    return (match == NO || (line[0] == '+'));
f2fdff
+    if (match == NO)
f2fdff
+	return NOMATCH;
f2fdff
+    if (line[0] == '+')
f2fdff
+	return YES;
f2fdff
+    return NO;
f2fdff
 }
f2fdff
 
f2fdff
 
f2fdff
@@ -524,7 +530,9 @@ user_match (pam_handle_t *pamh, char *to
f2fdff
     /* Try to split on a pattern (@*[^@]+)(@+.*) */
f2fdff
     for (at = tok; *at == '@'; ++at);
f2fdff
 
f2fdff
-    if ((at = strchr(at, '@')) != NULL) {
f2fdff
+    if (tok[0] == '(' && tok[strlen(tok) - 1] == ')') {
f2fdff
+      return (group_match (pamh, tok, string, item->debug));
f2fdff
+    } else if ((at = strchr(at, '@')) != NULL) {
f2fdff
         /* split user@host pattern */
f2fdff
 	if (item->hostname == NULL)
f2fdff
 	    return NO;
f2fdff
@@ -549,9 +557,7 @@ user_match (pam_handle_t *pamh, char *to
f2fdff
 		hostname = item->hostname;
f2fdff
 	}
f2fdff
         return (netgroup_match (pamh, tok + 1, hostname, string, item->debug));
f2fdff
-    } else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')')
f2fdff
-      return (group_match (pamh, tok, string, item->debug));
f2fdff
-    else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
f2fdff
+    } else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
f2fdff
       return rv;
f2fdff
     else if (item->only_new_group_syntax == NO &&
f2fdff
 	     pam_modutil_user_in_group_nam_nam (pamh,
f2fdff
@@ -573,7 +579,7 @@ group_match (pam_handle_t *pamh, const c
f2fdff
 
f2fdff
     if (debug)
f2fdff
         pam_syslog (pamh, LOG_DEBUG,
f2fdff
-		    "group_match: grp=%s, user=%s", grptok, usr);
f2fdff
+		    "group_match: grp=%s, user=%s", tok, usr);
f2fdff
 
f2fdff
     if (strlen(tok) < 3)
f2fdff
         return NO;
f2fdff
@@ -808,6 +814,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
f2fdff
     const char *user=NULL;
f2fdff
     const void *void_from=NULL;
f2fdff
     const char *from;
f2fdff
+    const char const *default_config = PAM_ACCESS_CONFIG;
f2fdff
     struct passwd *user_pw;
f2fdff
     char hostname[MAXHOSTNAMELEN + 1];
f2fdff
     int rv;
f2fdff
@@ -829,7 +836,7 @@ pam_sm_authenticate (pam_handle_t *pamh,
f2fdff
      */
f2fdff
     memset(&loginfo, '\0', sizeof(loginfo));
f2fdff
     loginfo.user = user_pw;
f2fdff
-    loginfo.config_file = PAM_ACCESS_CONFIG;
f2fdff
+    loginfo.config_file = default_config;
f2fdff
 
f2fdff
     /* parse the argument list */
f2fdff
 
f2fdff
@@ -900,6 +907,26 @@ pam_sm_authenticate (pam_handle_t *pamh,
f2fdff
 
f2fdff
     rv = login_access(pamh, &loginfo);
f2fdff
 
f2fdff
+    if (rv == NOMATCH && loginfo.config_file == default_config) {
f2fdff
+	glob_t globbuf;
f2fdff
+	int i, glob_rv;
f2fdff
+
f2fdff
+	/* We do not manipulate locale as setlocale() is not
f2fdff
+	 * thread safe. We could use uselocale() in future.
f2fdff
+	 */
f2fdff
+	glob_rv = glob(ACCESS_CONF_GLOB, GLOB_ERR, NULL, &globbuf);
f2fdff
+	if (!glob_rv) {
f2fdff
+	    /* Parse the *.conf files. */
f2fdff
+	    for (i = 0; globbuf.gl_pathv[i] != NULL; i++) {
f2fdff
+		loginfo.config_file = globbuf.gl_pathv[i];
f2fdff
+		rv = login_access(pamh, &loginfo);
f2fdff
+		if (rv != NOMATCH)
f2fdff
+		    break;
f2fdff
+	    }
f2fdff
+	    globfree(&globbuf);
f2fdff
+	}
f2fdff
+    }
f2fdff
+
f2fdff
     if (loginfo.gai_rv == 0 && loginfo.res)
f2fdff
 	freeaddrinfo(loginfo.res);
f2fdff
 
f2fdff
diff -up Linux-PAM-1.1.8/modules/pam_access/pam_access.8.xml.access-update Linux-PAM-1.1.8/modules/pam_access/pam_access.8.xml
f2fdff
--- Linux-PAM-1.1.8/modules/pam_access/pam_access.8.xml.access-update	2013-06-18 16:11:21.000000000 +0200
f2fdff
+++ Linux-PAM-1.1.8/modules/pam_access/pam_access.8.xml	2017-09-08 14:04:25.365642960 +0200
f2fdff
@@ -50,16 +50,25 @@
f2fdff
       The pam_access PAM module is mainly for access management.
f2fdff
       It provides logdaemon style login access control based on login
f2fdff
       names, host or domain names, internet addresses or network numbers,
f2fdff
-      or on terminal line names in case of non-networked logins.
f2fdff
+      or on terminal line names, X <varname>$DISPLAY</varname> values,
f2fdff
+      or PAM service names in case of non-networked logins.
f2fdff
     </para>
f2fdff
     <para>
f2fdff
       By default rules for access management are taken from config file
f2fdff
       <filename>/etc/security/access.conf</filename> if you don't specify
f2fdff
       another file.
f2fdff
+      Then individual <filename>*.conf</filename> files from the
f2fdff
+      <filename>/etc/security/access.d/</filename> directory are read.
f2fdff
+      The files are parsed one after another in the order of the system locale.
f2fdff
+      The effect of the individual files is the same as if all the files were
f2fdff
+      concatenated together in the order of parsing. This means that once
f2fdff
+      a pattern is matched in some file no further files are parsed.
f2fdff
+      If a config file is explicitly specified with the <option>accessfile</option>
f2fdff
+      option the files in the above directory are not parsed.
f2fdff
     </para>
f2fdff
     <para>
f2fdff
       If Linux PAM is compiled with audit support the module will report
f2fdff
-      when it denies access based on origin (host or tty).
f2fdff
+      when it denies access based on origin (host, tty, etc.).
f2fdff
     </para>
f2fdff
   </refsect1>
f2fdff