summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Schubert <schubi@suse.de>2021-12-09 15:19:29 +0100
committerDmitry V. Levin <ldv@altlinux.org>2022-01-25 14:24:26 +0000
commitc11b0f5d8f9f6abcc76594af9e3b5e647b19f61f (patch)
treea5c4bb2b95ee796fc85719715d8662235d37965b
parent4d96b59360a57a7a96443e6c34d2cfd13ea3f5e3 (diff)
downloadlinux-pam-git-c11b0f5d8f9f6abcc76594af9e3b5e647b19f61f.tar.gz
pam_group: use vendor specific group.conf as fallback
Use the vendor directory defined by --enable-vendordir=DIR configure option as fallback for the distribution provided default config file if there is no configuration in /etc. * modules/pam_group/pam_group.c: Include <errno.h>. [VENDOR_SCONFIGDIR] (VENDOR_PAM_GROUP_CONF): New macro. (read_field): Add conf_filename argument, use it instead of PAM_GROUP_CONF. (check_account) <conf_filename>: New variable, initialize it to PAM_GROUP_CONF, pass it to read_field(). [VENDOR_PAM_GROUP_CONF]: Assign VENDOR_PAM_GROUP_CONF to conf_filename when PAM_GROUP_CONF file does not exist. * modules/pam_group/pam_group.8.xml: Describe it. Co-authored-by: Dmitry V. Levin <ldv@altlinux.org> Resolves: https://github.com/linux-pam/linux-pam/pull/412
-rw-r--r--modules/pam_group/pam_group.8.xml4
-rw-r--r--modules/pam_group/pam_group.c45
2 files changed, 35 insertions, 14 deletions
diff --git a/modules/pam_group/pam_group.8.xml b/modules/pam_group/pam_group.8.xml
index 2c1c9058..e4a59dfd 100644
--- a/modules/pam_group/pam_group.8.xml
+++ b/modules/pam_group/pam_group.8.xml
@@ -38,6 +38,10 @@
By default rules for group memberships are taken from config file
<filename>/etc/security/group.conf</filename>.
</para>
+ <para condition="with_vendordir">
+ If <filename>/etc/security/group.conf</filename> does not exist,
+ <filename>%vendordir%/security/group.conf</filename> is used.
+ </para>
<para>
This module's usefulness relies on the file-systems
accessible to the user. The point being that once granted the
diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c
index 4e1fd648..c49358a1 100644
--- a/modules/pam_group/pam_group.c
+++ b/modules/pam_group/pam_group.c
@@ -16,6 +16,7 @@
#include <time.h>
#include <syslog.h>
#include <string.h>
+#include <errno.h>
#include <grp.h>
#include <sys/types.h>
@@ -24,6 +25,9 @@
#include <netdb.h>
#define PAM_GROUP_CONF SCONFIGDIR "/group.conf"
+#ifdef VENDOR_SCONFIGDIR
+# define VENDOR_PAM_GROUP_CONF VENDOR_SCONFIGDIR "/group.conf"
+#endif
#define PAM_GROUP_BUFLEN 1000
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
@@ -71,7 +75,8 @@ trim_spaces(char *buf, char *from)
#define STATE_EOF 3 /* end of file or error */
static int
-read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state,
+ const char *conf_filename)
{
char *to;
char *src;
@@ -90,9 +95,9 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
}
*from = 0;
*state = STATE_NL;
- fd = open(PAM_GROUP_CONF, O_RDONLY);
+ fd = open(conf_filename, O_RDONLY);
if (fd < 0) {
- pam_syslog(pamh, LOG_ERR, "error opening %s: %m", PAM_GROUP_CONF);
+ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", conf_filename);
_pam_drop(*buf);
*state = STATE_EOF;
return -1;
@@ -107,7 +112,7 @@ read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
while (fd != -1 && to - *buf < PAM_GROUP_BUFLEN) {
i = pam_modutil_read(fd, to, PAM_GROUP_BUFLEN - (to - *buf));
if (i < 0) {
- pam_syslog(pamh, LOG_ERR, "error reading %s: %m", PAM_GROUP_CONF);
+ pam_syslog(pamh, LOG_ERR, "error reading %s: %m", conf_filename);
close(fd);
memset(*buf, 0, PAM_GROUP_BUFLEN);
_pam_drop(*buf);
@@ -574,6 +579,18 @@ static int check_account(pam_handle_t *pamh, const char *service,
int retval=PAM_SUCCESS;
gid_t *grps;
int no_grps;
+ const char *conf_filename = PAM_GROUP_CONF;
+
+#ifdef VENDOR_PAM_GROUP_CONF
+ /*
+ * Check whether PAM_GROUP_CONF file is available.
+ * If it does not exist, fall back to VENDOR_PAM_GROUP_CONF file.
+ */
+ struct stat stat_buffer;
+ if (stat(conf_filename, &stat_buffer) != 0 && errno == ENOENT) {
+ conf_filename = VENDOR_PAM_GROUP_CONF;
+ }
+#endif
/*
* first we get the current list of groups - the application
@@ -612,7 +629,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the service name field */
- fd = read_field(pamh, fd, &buffer, &from, &state);
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
if (!buffer || !buffer[0]) {
/* empty line .. ? */
continue;
@@ -622,7 +639,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", conf_filename, count);
continue;
}
@@ -631,10 +648,10 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the terminal name field */
- fd = read_field(pamh, fd, &buffer, &from, &state);
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", conf_filename, count);
continue;
}
good &= logic_field(pamh,tty, buffer, count, is_same);
@@ -642,10 +659,10 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the username field */
- fd = read_field(pamh, fd, &buffer, &from, &state);
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", conf_filename, count);
continue;
}
/* If buffer starts with @, we are using netgroups */
@@ -664,20 +681,20 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the time field */
- fd = read_field(pamh, fd, &buffer, &from, &state);
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: malformed rule #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", conf_filename, count);
continue;
}
good &= logic_field(pamh,&here_and_now, buffer, count, check_time);
D(("with time: %s", good ? "passes":"fails" ));
- fd = read_field(pamh, fd, &buffer, &from, &state);
+ fd = read_field(pamh, fd, &buffer, &from, &state, conf_filename);
if (state == STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: poorly terminated rule #%d", PAM_GROUP_CONF, count);
+ "%s: poorly terminated rule #%d", conf_filename, count);
continue;
}