summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Mraz <tmraz@fedoraproject.org>2017-05-31 10:27:28 +0200
committerTomas Mraz <tmraz@fedoraproject.org>2017-05-31 10:27:28 +0200
commit7d0c508a52ebc9c702e1b6e66f46e4a6dc028c4a (patch)
tree8baa315fe88b9602c43e2369c3c011ef10bc18c2
parent5a6a2d169c06cd7e1959c34261d637c3f1c1f573 (diff)
downloadlinux-pam-git-7d0c508a52ebc9c702e1b6e66f46e4a6dc028c4a.tar.gz
pam_access: support parsing files in /etc/security/access.d/*.conf
* 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.
-rw-r--r--modules/pam_access/Makefile.am3
-rw-r--r--modules/pam_access/pam_access.8.xml8
-rw-r--r--modules/pam_access/pam_access.c31
3 files changed, 39 insertions, 3 deletions
diff --git a/modules/pam_access/Makefile.am b/modules/pam_access/Makefile.am
index 6c0f738e..924b7219 100644
--- a/modules/pam_access/Makefile.am
+++ b/modules/pam_access/Makefile.am
@@ -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
diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml
index c629a9f3..9a6556cc 100644
--- a/modules/pam_access/pam_access.8.xml
+++ b/modules/pam_access/pam_access.8.xml
@@ -57,6 +57,14 @@
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
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
index ba3b99f9..80d885dd 100644
--- a/modules/pam_access/pam_access.c
+++ b/modules/pam_access/pam_access.c
@@ -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);