]> granicus.if.org Git - linux-pam/commitdiff
pam_access: support parsing files in /etc/security/access.d/*.conf
authorTomas Mraz <tmraz@fedoraproject.org>
Wed, 31 May 2017 08:27:28 +0000 (10:27 +0200)
committerTomas Mraz <tmraz@fedoraproject.org>
Wed, 31 May 2017 08:27:28 +0000 (10:27 +0200)
* modules/pam_access/pam_access.c (login_access): Return NOMATCH if
there was no match in the parsed file.
(pam_sm_authenticate): Add glob() call to go through the ACCESS_CONF_GLOB
subdirectory and call login_access() on the individual files matched.
* modules/pam_access/pam_access.8.xml: Document the addition.
* modules/pam_access/Makefile.am: Add ACCESS_CONF_GLOB definition.

modules/pam_access/Makefile.am
modules/pam_access/pam_access.8.xml
modules/pam_access/pam_access.c

index 6c0f738ebc44d836b5077e12805d7bf54a6b044c..924b7219e3433764e599bda2580fbe1a64da1db6 100644 (file)
@@ -15,7 +15,8 @@ securelibdir = $(SECUREDIR)
 secureconfdir = $(SCONFIGDIR)
 
 AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-       -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\"
+       -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" \
+       -DACCESS_CONF_GLOB=\"$(SCONFIGDIR)/access.d/*.conf\"
 AM_LDFLAGS =  -no-undefined -avoid-version -module
 if HAVE_VERSIONING
   AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
index c629a9f3f783592d12830a2b98c7213fe31acfe2..9a6556ccbf01615af0526bedd109d37982397ec6 100644 (file)
       By default rules for access management are taken from config file
       <filename>/etc/security/access.conf</filename> if you don't specify
       another file.
+      Then individual <filename>*.conf</filename> files from the
+      <filename>/etc/security/access.d/</filename> directory are read.
+      The files are parsed one after another in the order of the system locale.
+      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 directory are not parsed.
     </para>
     <para>
       If Linux PAM is compiled with audit support the module will report
index ba3b99f91384fc7ea34cd6d9b193cd33e9c4460a..80d885ddac505610ffa51c17e8ee7747675dfbd9 100644 (file)
@@ -44,6 +44,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <sys/socket.h>
+#include <glob.h>
 #ifdef HAVE_LIBAUDIT
 #include <libaudit.h>
 #endif
@@ -87,6 +88,7 @@
 #define ALL             2
 #define YES             1
 #define NO              0
+#define NOMATCH        -1
 
  /*
   * A structure to bundle up all login-related information to keep the
@@ -415,7 +417,11 @@ login_access (pam_handle_t *pamh, struct login_info *item)
            "pam_access", 0);
     }
 #endif
-    return (match == NO || (line[0] == '+'));
+    if (match == NO)
+       return NOMATCH;
+    if (line[0] == '+')
+       return YES;
+    return NO;
 }
 
 
@@ -800,6 +806,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
     const char *user=NULL;
     const void *void_from=NULL;
     const char *from;
+    const char const *default_config = PAM_ACCESS_CONFIG;
     struct passwd *user_pw;
     char hostname[MAXHOSTNAMELEN + 1];
     int rv;
@@ -821,7 +828,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
      */
     memset(&loginfo, '\0', sizeof(loginfo));
     loginfo.user = user_pw;
-    loginfo.config_file = PAM_ACCESS_CONFIG;
+    loginfo.config_file = default_config;
 
     /* parse the argument list */
 
@@ -892,6 +899,26 @@ 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);
+       }
+    }
+
     if (loginfo.gai_rv == 0 && loginfo.res)
        freeaddrinfo(loginfo.res);