summaryrefslogtreecommitdiff
path: root/libpam
diff options
context:
space:
mode:
authorThorsten Kukuk <5908016+thkukuk@users.noreply.github.com>2019-09-16 17:17:49 +0200
committerGitHub <noreply@github.com>2019-09-16 17:17:49 +0200
commit65d6735c5949ec233df9813f734e918a93fa36cf (patch)
treec147e1f9ab27479abb3e2be94a2969aad6d87b68 /libpam
parent3a3e70739834cd5cbd17469907ef718c81ae40c0 (diff)
Add support for a vendor directory and libeconf (#136)
With this, it is possible for Linux distributors to store their supplied default configuration files somewhere below /usr, while /etc only contains the changes made by the user. The new option --enable-vendordir defines where Linux-PAM should additional look for pam.d/*, login.defs and securetty if this files are not in /etc. libeconf is a key/value configuration file reading library, which handles the split of configuration files in different locations and merges them transparently for the application.
Diffstat (limited to 'libpam')
-rw-r--r--libpam/Makefile.am8
-rw-r--r--libpam/pam_handlers.c47
-rw-r--r--libpam/pam_modutil_searchkey.c37
-rw-r--r--libpam/pam_private.h5
4 files changed, 70 insertions, 27 deletions
diff --git a/libpam/Makefile.am b/libpam/Makefile.am
index 875031ed..ba57b98e 100644
--- a/libpam/Makefile.am
+++ b/libpam/Makefile.am
@@ -3,10 +3,14 @@
#
AM_CFLAGS = -DDEFAULT_MODULE_PATH=\"$(SECUREDIR)/\" -DLIBPAM_COMPILE \
- -I$(srcdir)/include $(LIBPRELUDE_CFLAGS) -DPAM_VERSION=\"$(VERSION)\"
+ -I$(srcdir)/include $(LIBPRELUDE_CFLAGS) $(ECONF_CFLAGS) \
+ -DPAM_VERSION=\"$(VERSION)\" -DSYSCONFDIR=\"$(sysconfdir)\"
if HAVE_LIBSELINUX
AM_CFLAGS += -D"WITH_SELINUX"
endif
+if HAVE_VENDORDIR
+ AM_CFLAGS += -DVENDORDIR=\"$(VENDORDIR)\"
+endif
CLEANFILES = *~
@@ -21,7 +25,7 @@ noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
pam_modutil_private.h
libpam_la_LDFLAGS = -no-undefined -version-info 84:2:84
-libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@
+libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@
if HAVE_VERSIONING
libpam_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libpam.map
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index 106ef7c2..8e513da3 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -280,9 +280,14 @@ _pam_open_config_file(pam_handle_t *pamh
, char **path
, FILE **file)
{
+ const char *pamd_dirs[] = { PAM_CONFIG_DF, PAM_CONFIG_DIST_DF
+#ifdef VENDORDIR
+ , PAM_CONFIG_DIST2_DF
+#endif
+ };
char *p;
FILE *f;
- int err = 0;
+ size_t i;
/* Absolute path */
if (service[0] == '/') {
@@ -303,33 +308,20 @@ _pam_open_config_file(pam_handle_t *pamh
return PAM_ABORT;
}
- /* Local Machine Configuration /etc/pam.d/ */
- if (asprintf (&p, PAM_CONFIG_DF, service) < 0) {
- pam_syslog(pamh, LOG_CRIT, "asprintf failed");
- return PAM_BUF_ERR;
- }
- D(("opening %s", p));
- f = fopen(p, "r");
- if (f != NULL) {
- *path = p;
- *file = f;
- return PAM_SUCCESS;
- }
-
- /* System Configuration /usr/lib/pam.d/ */
- _pam_drop(p);
- if (asprintf (&p, PAM_CONFIG_DIST_DF, service) < 0) {
- pam_syslog(pamh, LOG_CRIT, "asprintf failed");
- return PAM_BUF_ERR;
- }
- D(("opening %s", p));
- f = fopen(p, "r");
- if (f != NULL) {
+ for (i = 0; i < sizeof (pamd_dirs)/sizeof (char *); i++) {
+ if (asprintf (&p, pamd_dirs[i], service) < 0) {
+ pam_syslog(pamh, LOG_CRIT, "asprintf failed");
+ return PAM_BUF_ERR;
+ }
+ D(("opening %s", p));
+ f = fopen(p, "r");
+ if (f != NULL) {
*path = p;
*file = f;
return PAM_SUCCESS;
+ }
+ _pam_drop(p);
}
- _pam_drop(p);
return PAM_ABORT;
}
@@ -447,7 +439,12 @@ int _pam_init_handlers(pam_handle_t *pamh)
/* Is there a PAM_CONFIG_D directory? */
if ((stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode)) ||
- (stat(PAM_CONFIG_DIST_D, &test_d) == 0 && S_ISDIR(test_d.st_mode))) {
+ (stat(PAM_CONFIG_DIST_D, &test_d) == 0 && S_ISDIR(test_d.st_mode))
+#ifdef PAM_CONFIG_DIST2_D
+ || (stat(PAM_CONFIG_DIST2_D, &test_d) == 0
+ && S_ISDIR(test_d.st_mode))
+#endif
+ ) {
char *path = NULL;
int read_something=0;
diff --git a/libpam/pam_modutil_searchkey.c b/libpam/pam_modutil_searchkey.c
index 338b44fd..4e565974 100644
--- a/libpam/pam_modutil_searchkey.c
+++ b/libpam/pam_modutil_searchkey.c
@@ -13,9 +13,41 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
+#ifdef USE_ECONF
+#include <libeconf.h>
+#endif
#define BUF_SIZE 8192
+#ifdef USE_ECONF
+#define LOGIN_DEFS "/etc/login.defs"
+
+#ifndef VENDORDIR
+#define VENDORDIR NULL
+#endif
+
+static char *
+econf_search_key (const char *name, const char *suffix, const char *key)
+{
+ econf_file *key_file = NULL;
+ char *val;
+
+ if (econf_readDirs (&key_file, VENDORDIR, SYSCONFDIR, name, suffix,
+ " \t", "#"))
+ return NULL;
+
+ if (econf_getStringValue (key_file, NULL, key, &val)) {
+ econf_free (key_file);
+ return NULL;
+ }
+
+ econf_free (key_file);
+
+ return val;
+}
+
+#endif
+
/* lookup a value for key in login.defs file or similar key value format */
char *
pam_modutil_search_key(pam_handle_t *pamh UNUSED,
@@ -27,6 +59,11 @@ pam_modutil_search_key(pam_handle_t *pamh UNUSED,
size_t buflen = 0;
char *retval = NULL;
+#ifdef USE_ECONF
+ if (strcmp (file_name, LOGIN_DEFS) == 0)
+ return econf_search_key ("login", ".defs", key);
+#endif
+
fp = fopen(file_name, "r");
if (NULL == fp)
return NULL;
diff --git a/libpam/pam_private.h b/libpam/pam_private.h
index 58a26f58..8cb77528 100644
--- a/libpam/pam_private.h
+++ b/libpam/pam_private.h
@@ -29,6 +29,11 @@
#define PAM_CONFIG_DF "/etc/pam.d/%s"
#define PAM_CONFIG_DIST_D "/usr/lib/pam.d"
#define PAM_CONFIG_DIST_DF "/usr/lib/pam.d/%s"
+#ifdef VENDORDIR
+#define PAM_CONFIG_DIST2_D VENDORDIR"/pam.d"
+#define PAM_CONFIG_DIST2_DF VENDORDIR"/pam.d/%s"
+#endif
+
#define PAM_DEFAULT_SERVICE "other" /* lower case */