diff options
author | Thorsten Kukuk <5908016+thkukuk@users.noreply.github.com> | 2019-09-16 17:17:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-16 17:17:49 +0200 |
commit | 65d6735c5949ec233df9813f734e918a93fa36cf (patch) | |
tree | c147e1f9ab27479abb3e2be94a2969aad6d87b68 /libpam | |
parent | 3a3e70739834cd5cbd17469907ef718c81ae40c0 (diff) | |
download | pam-65d6735c5949ec233df9813f734e918a93fa36cf.tar.gz pam-65d6735c5949ec233df9813f734e918a93fa36cf.tar.bz2 pam-65d6735c5949ec233df9813f734e918a93fa36cf.zip |
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.am | 8 | ||||
-rw-r--r-- | libpam/pam_handlers.c | 47 | ||||
-rw-r--r-- | libpam/pam_modutil_searchkey.c | 37 | ||||
-rw-r--r-- | libpam/pam_private.h | 5 |
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 */ |