summaryrefslogtreecommitdiff
path: root/modules/pam_access
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_access')
-rw-r--r--modules/pam_access/Makefile.am3
-rw-r--r--modules/pam_access/Makefile.in3
-rw-r--r--modules/pam_access/README30
-rw-r--r--modules/pam_access/access.conf28
-rw-r--r--modules/pam_access/access.conf.531
-rw-r--r--modules/pam_access/access.conf.5.xml34
-rw-r--r--modules/pam_access/pam_access.812
-rw-r--r--modules/pam_access/pam_access.8.xml8
-rw-r--r--modules/pam_access/pam_access.c41
9 files changed, 128 insertions, 62 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/Makefile.in b/modules/pam_access/Makefile.in
index a95dc1fe..02a35cb0 100644
--- a/modules/pam_access/Makefile.in
+++ b/modules/pam_access/Makefile.in
@@ -573,7 +573,8 @@ XMLS = README.xml access.conf.5.xml pam_access.8.xml
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 $(am__append_1)
securelib_LTLIBRARIES = pam_access.la
diff --git a/modules/pam_access/README b/modules/pam_access/README
index f605c240..0e16c0d8 100644
--- a/modules/pam_access/README
+++ b/modules/pam_access/README
@@ -10,7 +10,13 @@ names, internet addresses or network numbers, or on terminal line names, X
$DISPLAY values, or PAM service names in case of non-networked logins.
By default rules for access management are taken from config file /etc/security
-/access.conf if you don't specify another file.
+/access.conf if you don't specify another file. Then individual *.conf files
+from the /etc/security/access.d/ 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 accessfile
+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.).
@@ -66,49 +72,49 @@ access.conf.
User root should be allowed to get access via cron, X11 terminal :0, tty1, ...,
tty5, tty6.
-+ : root : crond :0 tty1 tty2 tty3 tty4 tty5 tty6
++:root:crond :0 tty1 tty2 tty3 tty4 tty5 tty6
User root should be allowed to get access from hosts which own the IPv4
addresses. This does not mean that the connection have to be a IPv4 one, a IPv6
connection from a host with one of this IPv4 addresses does work, too.
-+ : root : 192.168.200.1 192.168.200.4 192.168.200.9
++:root:192.168.200.1 192.168.200.4 192.168.200.9
-+ : root : 127.0.0.1
++:root:127.0.0.1
User root should get access from network 192.168.201. where the term will be
evaluated by string matching. But it might be better to use network/netmask
instead. The same meaning of 192.168.201. is 192.168.201.0/24 or 192.168.201.0/
255.255.255.0.
-+ : root : 192.168.201.
++:root:192.168.201.
User root should be able to have access from hosts foo1.bar.org and
foo2.bar.org (uses string matching also).
-+ : root : foo1.bar.org foo2.bar.org
++:root:foo1.bar.org foo2.bar.org
User root should be able to have access from domain foo.bar.org (uses string
matching also).
-+ : root : .foo.bar.org
++:root:.foo.bar.org
User root should be denied to get access from all other sources.
-- : root : ALL
+-:root:ALL
User foo and members of netgroup admins should be allowed to get access from
all sources. This will only work if netgroup service is available.
-+ : @admins foo : ALL
++:@admins foo:ALL
User john and foo should get access from IPv6 host address.
-+ : john foo : 2001:db8:0:101::1
++:john foo:2001:db8:0:101::1
User john should get access from IPv6 net/mask.
-+ : john : 2001:db8:0:101::/64
++:john:2001:db8:0:101::/64
Disallow console logins to all but the shutdown, sync and all other accounts,
which are a member of the wheel group.
@@ -117,5 +123,5 @@ which are a member of the wheel group.
All other users should be denied to get access from all sources.
-- : ALL : ALL
+-:ALL:ALL
diff --git a/modules/pam_access/access.conf b/modules/pam_access/access.conf
index 74c5fbe8..47b6b84c 100644
--- a/modules/pam_access/access.conf
+++ b/modules/pam_access/access.conf
@@ -18,7 +18,7 @@
# pam_access with X applications that provide PAM_TTY values that are
# the display variable like "host:0".]
#
-# permission : users : origins
+# permission:users:origins
#
# The first field should be a "+" (access granted) or "-" (access denied)
# character.
@@ -79,44 +79,44 @@
##############################################################################
#
# User "root" should be allowed to get access via cron .. tty5 tty6.
-#+ : root : cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6
+#+:root:cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6
#
# User "root" should be allowed to get access from hosts with ip addresses.
-#+ : root : 192.168.200.1 192.168.200.4 192.168.200.9
-#+ : root : 127.0.0.1
+#+:root:192.168.200.1 192.168.200.4 192.168.200.9
+#+:root:127.0.0.1
#
# User "root" should get access from network 192.168.201.
# This term will be evaluated by string matching.
# comment: It might be better to use network/netmask instead.
# The same is 192.168.201.0/24 or 192.168.201.0/255.255.255.0
-#+ : root : 192.168.201.
+#+:root:192.168.201.
#
# User "root" should be able to have access from domain.
# Uses string matching also.
-#+ : root : .foo.bar.org
+#+:root:.foo.bar.org
#
# User "root" should be denied to get access from all other sources.
-#- : root : ALL
+#-:root:ALL
#
# User "foo" and members of netgroup "nis_group" should be
# allowed to get access from all sources.
# This will only work if netgroup service is available.
-#+ : @nis_group foo : ALL
+#+:@nis_group foo:ALL
#
# User "john" should get access from ipv4 net/mask
-#+ : john : 127.0.0.0/24
+#+:john:127.0.0.0/24
#
# User "john" should get access from ipv4 as ipv6 net/mask
-#+ : john : ::ffff:127.0.0.0/127
+#+:john:::ffff:127.0.0.0/127
#
# User "john" should get access from ipv6 host address
-#+ : john : 2001:4ca0:0:101::1
+#+:john:2001:4ca0:0:101::1
#
# User "john" should get access from ipv6 host address (same as above)
-#+ : john : 2001:4ca0:0:101:0:0:0:1
+#+:john:2001:4ca0:0:101:0:0:0:1
#
# User "john" should get access from ipv6 net/mask
-#+ : john : 2001:4ca0:0:101::/64
+#+:john:2001:4ca0:0:101::/64
#
# All other users should be denied to get access from all sources.
-#- : ALL : ALL
+#-:ALL:ALL
diff --git a/modules/pam_access/access.conf.5 b/modules/pam_access/access.conf.5
index 5ef63053..8e7ea4cf 100644
--- a/modules/pam_access/access.conf.5
+++ b/modules/pam_access/access.conf.5
@@ -2,12 +2,12 @@
.\" Title: access.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 04/01/2016
+.\" Date: 05/18/2018
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM Manual
.\" Language: English
.\"
-.TH "ACCESS\&.CONF" "5" "04/01/2016" "Linux-PAM Manual" "Linux\-PAM Manual"
+.TH "ACCESS\&.CONF" "5" "05/18/2018" "Linux-PAM Manual" "Linux\-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -119,15 +119,15 @@ should be allowed to get access via
\fItty5\fR,
\fItty6\fR\&.
.PP
-+ : root : crond :0 tty1 tty2 tty3 tty4 tty5 tty6
++:root:crond :0 tty1 tty2 tty3 tty4 tty5 tty6
.PP
User
\fIroot\fR
should be allowed to get access from hosts which own the IPv4 addresses\&. This does not mean that the connection have to be a IPv4 one, a IPv6 connection from a host with one of this IPv4 addresses does work, too\&.
.PP
-+ : root : 192\&.168\&.200\&.1 192\&.168\&.200\&.4 192\&.168\&.200\&.9
++:root:192\&.168\&.200\&.1 192\&.168\&.200\&.4 192\&.168\&.200\&.9
.PP
-+ : root : 127\&.0\&.0\&.1
++:root:127\&.0\&.0\&.1
.PP
User
\fIroot\fR
@@ -140,7 +140,7 @@ is
or
\fI192\&.168\&.201\&.0/255\&.255\&.255\&.0\fR\&.
.PP
-+ : root : 192\&.168\&.201\&.
++:root:192\&.168\&.201\&.
.PP
User
\fIroot\fR
@@ -150,7 +150,7 @@ and
\fIfoo2\&.bar\&.org\fR
(uses string matching also)\&.
.PP
-+ : root : foo1\&.bar\&.org foo2\&.bar\&.org
++:root:foo1\&.bar\&.org foo2\&.bar\&.org
.PP
User
\fIroot\fR
@@ -158,13 +158,13 @@ should be able to have access from domain
\fIfoo\&.bar\&.org\fR
(uses string matching also)\&.
.PP
-+ : root : \&.foo\&.bar\&.org
++:root:\&.foo\&.bar\&.org
.PP
User
\fIroot\fR
should be denied to get access from all other sources\&.
.PP
-\- : root : ALL
+\-:root:ALL
.PP
User
\fIfoo\fR
@@ -172,7 +172,7 @@ and members of netgroup
\fIadmins\fR
should be allowed to get access from all sources\&. This will only work if netgroup service is available\&.
.PP
-+ : @admins foo : ALL
++:@admins foo:ALL
.PP
User
\fIjohn\fR
@@ -180,13 +180,13 @@ and
\fIfoo\fR
should get access from IPv6 host address\&.
.PP
-+ : john foo : 2001:db8:0:101::1
++:john foo:2001:db8:0:101::1
.PP
User
\fIjohn\fR
should get access from IPv6 net/mask\&.
.PP
-+ : john : 2001:db8:0:101::/64
++:john:2001:db8:0:101::/64
.PP
Disallow console logins to all but the shutdown, sync and all other accounts, which are a member of the wheel group\&.
.PP
@@ -194,7 +194,12 @@ Disallow console logins to all but the shutdown, sync and all other accounts, wh
.PP
All other users should be denied to get access from all sources\&.
.PP
-\- : ALL : ALL
+\-:ALL:ALL
+.SH "NOTES"
+.PP
+The default separators of list items in a field are space, \*(Aq,\*(Aq, and tabulator characters\&. Thus conveniently if spaces are put at the beginning and the end of the fields they are ignored\&. However if the list separator is changed with the
+\fIlistsep\fR
+option, the spaces will become part of the actual item and the line will be most probably ignored\&. For this reason, it is not recommended to put spaces around the \*(Aq:\*(Aq characters\&.
.SH "SEE ALSO"
.PP
\fBpam_access\fR(8),
diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml
index d686d92b..386346b9 100644
--- a/modules/pam_access/access.conf.5.xml
+++ b/modules/pam_access/access.conf.5.xml
@@ -139,7 +139,7 @@
<emphasis>tty1</emphasis>, ..., <emphasis>tty5</emphasis>,
<emphasis>tty6</emphasis>.
</para>
- <para>+ : root : crond :0 tty1 tty2 tty3 tty4 tty5 tty6</para>
+ <para>+:root:crond :0 tty1 tty2 tty3 tty4 tty5 tty6</para>
<para>
User <emphasis>root</emphasis> should be allowed to get access from
@@ -147,8 +147,8 @@
connection have to be a IPv4 one, a IPv6 connection from a host with
one of this IPv4 addresses does work, too.
</para>
- <para>+ : root : 192.168.200.1 192.168.200.4 192.168.200.9</para>
- <para>+ : root : 127.0.0.1</para>
+ <para>+:root:192.168.200.1 192.168.200.4 192.168.200.9</para>
+ <para>+:root:127.0.0.1</para>
<para>
User <emphasis>root</emphasis> should get access from network
@@ -158,44 +158,44 @@
<emphasis>192.168.201.0/24</emphasis> or
<emphasis>192.168.201.0/255.255.255.0</emphasis>.
</para>
- <para>+ : root : 192.168.201.</para>
+ <para>+:root:192.168.201.</para>
<para>
User <emphasis>root</emphasis> should be able to have access from hosts
<emphasis>foo1.bar.org</emphasis> and <emphasis>foo2.bar.org</emphasis>
(uses string matching also).
</para>
- <para>+ : root : foo1.bar.org foo2.bar.org</para>
+ <para>+:root:foo1.bar.org foo2.bar.org</para>
<para>
User <emphasis>root</emphasis> should be able to have access from
domain <emphasis>foo.bar.org</emphasis> (uses string matching also).
</para>
- <para>+ : root : .foo.bar.org</para>
+ <para>+:root:.foo.bar.org</para>
<para>
User <emphasis>root</emphasis> should be denied to get access
from all other sources.
</para>
- <para>- : root : ALL</para>
+ <para>-:root:ALL</para>
<para>
User <emphasis>foo</emphasis> and members of netgroup
<emphasis>admins</emphasis> should be allowed to get access
from all sources. This will only work if netgroup service is available.
</para>
- <para>+ : @admins foo : ALL</para>
+ <para>+:@admins foo:ALL</para>
<para>
User <emphasis>john</emphasis> and <emphasis>foo</emphasis>
should get access from IPv6 host address.
</para>
- <para>+ : john foo : 2001:db8:0:101::1</para>
+ <para>+:john foo:2001:db8:0:101::1</para>
<para>
User <emphasis>john</emphasis> should get access from IPv6 net/mask.
</para>
- <para>+ : john : 2001:db8:0:101::/64</para>
+ <para>+:john:2001:db8:0:101::/64</para>
<para>
Disallow console logins to all but the shutdown, sync and all
@@ -206,10 +206,22 @@
<para>
All other users should be denied to get access from all sources.
</para>
- <para>- : ALL : ALL</para>
+ <para>-:ALL:ALL</para>
</refsect1>
+ <refsect1 id="access.conf-notes">
+ <title>NOTES</title>
+ <para>
+ The default separators of list items in a field are space, ',', and tabulator
+ characters. Thus conveniently if spaces are put at the beginning and the end of
+ the fields they are ignored. However if the list separator is changed with the
+ <emphasis>listsep</emphasis> option, the spaces will become part of the actual
+ item and the line will be most probably ignored. For this reason, it is not
+ recommended to put spaces around the ':' characters.
+ </para>
+ </refsect1>
+
<refsect1 id="access.conf-see_also">
<title>SEE ALSO</title>
<para>
diff --git a/modules/pam_access/pam_access.8 b/modules/pam_access/pam_access.8
index 2a2a2c26..138c3c48 100644
--- a/modules/pam_access/pam_access.8
+++ b/modules/pam_access/pam_access.8
@@ -2,12 +2,12 @@
.\" Title: pam_access
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 04/01/2016
+.\" Date: 05/18/2018
.\" Manual: Linux-PAM Manual
.\" Source: Linux-PAM Manual
.\" Language: English
.\"
-.TH "PAM_ACCESS" "8" "04/01/2016" "Linux-PAM Manual" "Linux-PAM Manual"
+.TH "PAM_ACCESS" "8" "05/18/2018" "Linux-PAM Manual" "Linux-PAM Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -40,7 +40,13 @@ values, or PAM service names in case of non\-networked logins\&.
.PP
By default rules for access management are taken from config file
/etc/security/access\&.conf
-if you don\*(Aqt specify another file\&.
+if you don\*(Aqt specify another file\&. Then individual
+*\&.conf
+files from the
+/etc/security/access\&.d/
+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
+\fBaccessfile\fR
+option the files in the above directory are not parsed\&.
.PP
If Linux PAM is compiled with audit support the module will report when it denies access based on origin (host, tty, etc\&.)\&.
.SH "OPTIONS"
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 3ac1ad00..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;
}
@@ -516,7 +522,9 @@ user_match (pam_handle_t *pamh, char *tok, struct login_info *item)
/* Try to split on a pattern (@*[^@]+)(@+.*) */
for (at = tok; *at == '@'; ++at);
- if ((at = strchr(at, '@')) != NULL) {
+ if (tok[0] == '(' && tok[strlen(tok) - 1] == ')') {
+ return (group_match (pamh, tok, string, item->debug));
+ } else if ((at = strchr(at, '@')) != NULL) {
/* split user@host pattern */
if (item->hostname == NULL)
return NO;
@@ -541,9 +549,7 @@ user_match (pam_handle_t *pamh, char *tok, struct login_info *item)
hostname = item->hostname;
}
return (netgroup_match (pamh, tok + 1, hostname, string, item->debug));
- } else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')')
- return (group_match (pamh, tok, string, item->debug));
- else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
+ } else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */
return rv;
else if (item->only_new_group_syntax == NO &&
pam_modutil_user_in_group_nam_nam (pamh,
@@ -727,7 +733,7 @@ network_netmask_match (pam_handle_t *pamh,
{ /* netmask as integre value */
char *endptr = NULL;
netmask = strtol(netmask_ptr, &endptr, 0);
- if ((endptr == NULL) || (*endptr != '\0'))
+ if ((endptr == netmask_ptr) || (*endptr != '\0'))
{ /* invalid netmask value */
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);