diff options
author | Thorsten Kukuk <kukuk@thkukuk.de> | 2015-03-25 15:00:38 +0100 |
---|---|---|
committer | Thorsten Kukuk <kukuk@thkukuk.de> | 2015-03-25 15:00:38 +0100 |
commit | 10b83ef224a5e9c3e2663b3f08dd17090acc58ab (patch) | |
tree | 82a9a446b061cb90384bc195478e1383c83a53ee /libpam/pam_handlers.c | |
parent | 73bdfac8c091492f466342feb8f2f5daa2f4c39b (diff) | |
download | pam-10b83ef224a5e9c3e2663b3f08dd17090acc58ab.tar.gz pam-10b83ef224a5e9c3e2663b3f08dd17090acc58ab.tar.bz2 pam-10b83ef224a5e9c3e2663b3f08dd17090acc58ab.zip |
Support alternative "vendor configuration" files as fallback to /etc
(Ticket#34, patch from ay Sievers <kay@vrfy.org>)
* doc/man/pam.8.xml: document additonal config directory
* libpam/pam_handlers.c: add /usr/lib/pam.d as config file fallback directory
* libpam/pam_private.h: adjust defines
Diffstat (limited to 'libpam/pam_handlers.c')
-rw-r--r-- | libpam/pam_handlers.c | 124 |
1 files changed, 82 insertions, 42 deletions
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c index df3a1d91..bc3fd9d8 100644 --- a/libpam/pam_handlers.c +++ b/libpam/pam_handlers.c @@ -274,6 +274,66 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f return ( (x < 0) ? PAM_ABORT:PAM_SUCCESS ); } +static int +_pam_open_config_file(pam_handle_t *pamh + , const char *service + , char **path + , FILE **file) +{ + char *p; + FILE *f; + int err = 0; + + /* Absolute path */ + if (service[0] == '/') { + p = _pam_strdup(service); + if (p == NULL) { + pam_syslog(pamh, LOG_CRIT, "strdup failed"); + return PAM_BUF_ERR; + } + + f = fopen(service, "r"); + if (f != NULL) { + *path = p; + *file = f; + return PAM_SUCCESS; + } + + _pam_drop(p); + 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) { + *path = p; + *file = f; + return PAM_SUCCESS; + } + _pam_drop(p); + + return PAM_ABORT; +} + static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name , const char *service /* specific file */ , int module_type /* specific type */ @@ -284,7 +344,7 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name ) { FILE *f; - char *config_path = NULL; + char *path = NULL; int retval = PAM_ABORT; D(("_pam_load_conf_file called")); @@ -297,39 +357,29 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name if (config_name == NULL) { D(("no config file supplied")); - pam_syslog(pamh, LOG_ERR, "(%s) no config file supplied", service); + pam_syslog(pamh, LOG_ERR, "(%s) no config name supplied", service); return PAM_ABORT; } - if (config_name[0] != '/') { - if (asprintf (&config_path, PAM_CONFIG_DF, config_name) < 0) { - pam_syslog(pamh, LOG_CRIT, "asprintf failed"); - return PAM_BUF_ERR; - } - config_name = config_path; - } - - D(("opening %s", config_name)); - f = fopen(config_name, "r"); - if (f != NULL) { + if (_pam_open_config_file(pamh, config_name, &path, &f) == PAM_SUCCESS) { retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level #ifdef PAM_READ_BOTH_CONFS , not_other #endif /* PAM_READ_BOTH_CONFS */ ); - fclose(f); if (retval != PAM_SUCCESS) pam_syslog(pamh, LOG_ERR, "_pam_load_conf_file: error reading %s: %s", - config_name, pam_strerror(pamh, retval)); + path, pam_strerror(pamh, retval)); + _pam_drop(path); + fclose(f); } else { D(("unable to open %s", config_name)); pam_syslog(pamh, LOG_ERR, - "_pam_load_conf_file: unable to open %s", + "_pam_load_conf_file: unable to open config for %s", config_name); } - _pam_drop(config_path); return retval; } @@ -396,39 +446,31 @@ int _pam_init_handlers(pam_handle_t *pamh) struct stat test_d; /* Is there a PAM_CONFIG_D directory? */ - if ( stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) { - char *filename; + 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))) { + char *path = NULL; int read_something=0; - D(("searching " PAM_CONFIG_D " for config files")); - if (asprintf(&filename, PAM_CONFIG_DF, pamh->service_name) < 0) { - pam_syslog(pamh, LOG_ERR, - "_pam_init_handlers: no memory; service %s", - pamh->service_name); - return PAM_BUF_ERR; - } - D(("opening %s", filename)); - f = fopen(filename, "r"); - if (f != NULL) { - /* would test magic here? */ + if (_pam_open_config_file(pamh, pamh->service_name, &path, &f) == PAM_SUCCESS) { retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY, 0 #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ ); - fclose(f); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: error reading %s", - filename); + path); pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: [%s]", pam_strerror(pamh, retval)); } else { read_something = 1; } + _pam_drop(path); + fclose(f); } else { - D(("unable to open %s", filename)); + D(("unable to open configuration for %s", pamh->service_name)); #ifdef PAM_READ_BOTH_CONFS D(("checking %s", PAM_CONFIG)); @@ -443,14 +485,11 @@ int _pam_init_handlers(pam_handle_t *pamh) * use "other" */ } - _pam_drop(filename); if (retval == PAM_SUCCESS) { - /* now parse the PAM_DEFAULT_SERVICE_FILE */ + /* now parse the PAM_DEFAULT_SERVICE */ - D(("opening %s", PAM_DEFAULT_SERVICE_FILE)); - f = fopen(PAM_DEFAULT_SERVICE_FILE, "r"); - if (f != NULL) { + if (_pam_open_config_file(pamh, PAM_DEFAULT_SERVICE, &path, &f) == PAM_SUCCESS) { /* would test magic here? */ retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE, PAM_T_ANY, 0 @@ -458,22 +497,23 @@ int _pam_init_handlers(pam_handle_t *pamh) , 0 #endif /* PAM_READ_BOTH_CONFS */ ); - fclose(f); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: error reading %s", - PAM_DEFAULT_SERVICE_FILE); + path); pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: [%s]", pam_strerror(pamh, retval)); } else { read_something = 1; } + _pam_drop(path); + fclose(f); } else { - D(("unable to open %s", PAM_DEFAULT_SERVICE_FILE)); + D(("unable to open %s", PAM_DEFAULT_SERVICE)); pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: no default config %s", - PAM_DEFAULT_SERVICE_FILE); + PAM_DEFAULT_SERVICE); } if (!read_something) { /* nothing read successfully */ retval = PAM_ABORT; |