diff options
Diffstat (limited to 'Linux-PAM/libpam/pam_handlers.c')
-rw-r--r-- | Linux-PAM/libpam/pam_handlers.c | 161 |
1 files changed, 144 insertions, 17 deletions
diff --git a/Linux-PAM/libpam/pam_handlers.c b/Linux-PAM/libpam/pam_handlers.c index d00f1842..ed03eda8 100644 --- a/Linux-PAM/libpam/pam_handlers.c +++ b/Linux-PAM/libpam/pam_handlers.c @@ -4,10 +4,12 @@ * created by Marc Ewing. * Currently maintained by Andrew G. Morgan <morgan@kernel.org> * - * $Id: pam_handlers.c,v 1.1.1.2 2002/09/15 20:08:37 hartmans Exp $ + * $Id: pam_handlers.c,v 1.12 2005/02/07 08:18:53 kukuk Exp $ * */ +#include "pam_private.h" + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -24,8 +26,6 @@ # endif /* PAM_SHL */ #endif /* PAM_DYNAMIC */ -#include "pam_private.h" - /* If not required, define as nothing */ #ifndef SHLIB_SYM_PREFIX # define SHLIB_SYM_PREFIX "" @@ -34,6 +34,9 @@ #define BUF_SIZE 1024 #define MODULE_CHUNK 4 #define UNKNOWN_MODULE_PATH "<*unknown module path*>" +#ifndef _PAM_ISA +#define _PAM_ISA "." +#endif static int _pam_assemble_line(FILE *f, char *buf, int buf_len); @@ -46,13 +49,23 @@ static int _pam_add_handler(pam_handle_t *pamh /* Values for module type */ +#define PAM_T_ANY 0 #define PAM_T_AUTH 1 #define PAM_T_SESS 2 #define PAM_T_ACCT 4 #define PAM_T_PASS 8 +static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name + , const char *service /* specific file */ + , int module_type /* specific type */ +#ifdef PAM_READ_BOTH_CONFS + , int not_other +#endif /* PAM_READ_BOTH_CONFS */ + ); + static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f , const char *known_service /* specific file */ + , int requested_module_type /* specific type */ #ifdef PAM_READ_BOTH_CONFS , int not_other #endif /* PAM_READ_BOTH_CONFS */ @@ -93,12 +106,21 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f /* accept "service name" or PAM_DEFAULT_SERVICE modules */ if (!_pam_strCMP(this_service, pamh->service_name) || other) { + int pam_include = 0; + /* This is a service we are looking for */ D(("_pam_init_handlers: Found PAM config entry for: %s" , this_service)); tok = _pam_StrTok(NULL, " \n\t", &nexttok); - if (!_pam_strCMP("auth", tok)) { + if (tok == NULL) { + /* module type does not exist */ + D(("_pam_init_handlers: empty module type for %s", this_service)); + _pam_system_log(LOG_ERR, "(%s) empty module type", this_service); + module_type = (requested_module_type != PAM_T_ANY) ? + requested_module_type : PAM_T_AUTH; /* most sensitive */ + must_fail = 1; /* install as normal but fail when dispatched */ + } else if (!_pam_strCMP("auth", tok)) { module_type = PAM_T_AUTH; } else if (!_pam_strCMP("session", tok)) { module_type = PAM_T_SESS; @@ -111,10 +133,17 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f D(("_pam_init_handlers: bad module type: %s", tok)); _pam_system_log(LOG_ERR, "(%s) illegal module type: %s", this_service, tok); - module_type = PAM_T_AUTH; /* most sensitive */ + module_type = (requested_module_type != PAM_T_ANY) ? + requested_module_type : PAM_T_AUTH; /* most sensitive */ must_fail = 1; /* install as normal but fail when dispatched */ } D(("Using %s config entry: %s", must_fail?"BAD ":"", tok)); + if (requested_module_type != PAM_T_ANY && + module_type != requested_module_type) { + D(("Skipping config entry: %s (requested=%d, found=%d)", + tok, requested_module_type, module_type)); + continue; + } /* reset the actions to .._UNDEF's -- this is so that we can work out which entries are not yet set (for default). */ @@ -124,7 +153,14 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f actions[i++] = _PAM_ACTION_UNDEF); } tok = _pam_StrTok(NULL, " \n\t", &nexttok); - if (!_pam_strCMP("required", tok)) { + if (tok == NULL) { + /* no module name given */ + D(("_pam_init_handlers: no control flag supplied")); + _pam_system_log(LOG_ERR, + "(%s) no control flag supplied", this_service); + _pam_set_default_control(actions, _PAM_ACTION_BAD); + must_fail = 1; + } else if (!_pam_strCMP("required", tok)) { D(("*PAM_F_REQUIRED*")); actions[PAM_SUCCESS] = _PAM_ACTION_OK; actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK; @@ -146,6 +182,9 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f actions[PAM_SUCCESS] = _PAM_ACTION_DONE; actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_DONE; _pam_set_default_control(actions, _PAM_ACTION_IGNORE); + } else if (!_pam_strCMP("include", tok)) { + D(("*PAM_F_INCLUDE*")); + pam_include = 1; } else { D(("will need to parse %s", tok)); _pam_parse_control(actions, tok); @@ -154,7 +193,18 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f } tok = _pam_StrTok(NULL, " \n\t", &nexttok); - if (tok != NULL) { + if (pam_include) { + if (_pam_load_conf_file(pamh, tok, this_service, module_type +#ifdef PAM_READ_BOTH_CONFS + , !other +#endif /* PAM_READ_BOTH_CONFS */ + ) == PAM_SUCCESS) + continue; + _pam_set_default_control(actions, _PAM_ACTION_BAD); + mod_path = NULL; + must_fail = 1; + nexttok = NULL; + } else if (tok != NULL) { mod_path = tok; D(("mod_path = %s",mod_path)); } else { @@ -213,6 +263,58 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f return ( (x < 0) ? PAM_ABORT:PAM_SUCCESS ); } +static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name + , const char *service /* specific file */ + , int module_type /* specific type */ +#ifdef PAM_READ_BOTH_CONFS + , int not_other +#endif /* PAM_READ_BOTH_CONFS */ + ) +{ + FILE *f; + char *config_path = NULL; + int retval = PAM_ABORT; + + D(("_pam_load_conf_file called")); + + if (config_name == NULL) { + D(("no config file supplied")); + _pam_system_log(LOG_ERR, "(%s) no config file supplied", service); + return PAM_ABORT; + } + + if (config_name[0] != '/') { + if (asprintf (&config_path, PAM_CONFIG_DF, config_name) < 0) { + _pam_system_log(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) { + retval = _pam_parse_conf_file(pamh, f, service, module_type +#ifdef PAM_READ_BOTH_CONFS + , not_other +#endif /* PAM_READ_BOTH_CONFS */ + ); + fclose(f); + if (retval != PAM_SUCCESS) + _pam_system_log(LOG_ERR, + "_pam_load_conf_file: error reading %s: %s", + config_name, pam_strerror(pamh, retval)); + } else { + D(("unable to open %s", config_name)); + _pam_system_log(LOG_ERR, + "_pam_load_conf_file: unable to open %s", + config_name); + } + + _pam_drop(config_path); + return retval; +} + /* Parse config file, allocate handler structures, dlopen() */ int _pam_init_handlers(pam_handle_t *pamh) { @@ -228,7 +330,7 @@ int _pam_init_handlers(pam_handle_t *pamh) } D(("_pam_init_handlers: initializing")); - + /* First clean the service structure */ _pam_free_handlers(pamh); @@ -273,7 +375,7 @@ 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; @@ -293,7 +395,7 @@ int _pam_init_handlers(pam_handle_t *pamh) f = fopen(filename, "r"); if (f != NULL) { /* would test magic here? */ - retval = _pam_parse_conf_file(pamh, f, pamh->service_name + retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ @@ -314,7 +416,7 @@ int _pam_init_handlers(pam_handle_t *pamh) D(("checking %s", PAM_CONFIG)); if ((f = fopen(PAM_CONFIG,"r")) != NULL) { - retval = _pam_parse_conf_file(pamh, f, NULL, 1); + retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 1); fclose(f); } else #endif /* PAM_READ_BOTH_CONFS */ @@ -335,6 +437,7 @@ int _pam_init_handlers(pam_handle_t *pamh) /* would test magic here? */ retval = _pam_parse_conf_file(pamh, f , PAM_DEFAULT_SERVICE + , PAM_T_ANY #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ @@ -367,7 +470,7 @@ int _pam_init_handlers(pam_handle_t *pamh) return PAM_ABORT; } - retval = _pam_parse_conf_file(pamh, f, NULL + retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ @@ -489,7 +592,7 @@ int _pam_add_handler(pam_handle_t *pamh #ifdef PAM_SHL const char *_sym, *_sym2; #endif - char *mod_full_path=NULL; + char *mod_full_path=NULL, *mod_full_isa_path=NULL, *isa=NULL; servicefn func, func2; int success; @@ -554,6 +657,30 @@ int _pam_add_handler(pam_handle_t *pamh # endif /* PAM_SHL */ D(("_pam_add_handler: dlopen'ed")); if (mod->dl_handle == NULL) { + if (strstr(mod_path, "$ISA")) { + mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1); + if (mod_full_isa_path == NULL) { + D(("_pam_handler: couldn't get memory for mod_path")); + _pam_system_log(LOG_ERR, "no memory for module path"); + success = PAM_ABORT; + } else { + strcpy(mod_full_isa_path, mod_path); + isa = strstr(mod_full_isa_path, "$ISA"); + if (isa) { + memmove(isa + strlen(_PAM_ISA), isa + 4, strlen(isa + 4) + 1); + memmove(isa, _PAM_ISA, strlen(_PAM_ISA)); + } + mod->dl_handle = +# ifdef PAM_SHL + shl_load(mod_full_isa_path, BIND_IMMEDIATE, 0L); +# else /* PAM_SHL */ + dlopen(mod_full_isa_path, RTLD_NOW); +# endif /* PAM_SHL */ + _pam_drop(mod_full_isa_path); + } + } + } + if (mod->dl_handle == NULL) { D(("_pam_add_handler: dlopen(%s) failed", mod_path)); _pam_system_log(LOG_ERR, "unable to dlopen(%s)", mod_path); # ifndef PAM_SHL @@ -600,7 +727,7 @@ int _pam_add_handler(pam_handle_t *pamh /* indicate its name - later we will search for it by this */ if ((mod->name = _pam_strdup(mod_path)) == NULL) { D(("_pam_handler: couldn't get memory for mod_path")); - _pam_system_log(LOG_ERR, "no memory for module path", mod_path); + _pam_system_log(LOG_ERR, "no memory for module path"); success = PAM_ABORT; } @@ -696,7 +823,7 @@ int _pam_add_handler(pam_handle_t *pamh } /* now identify this module's functions - for non-faulty modules */ - + #ifdef PAM_DYNAMIC if ((mod->type == PAM_MT_DYNAMIC_MOD) && # ifdef PAM_SHL @@ -823,7 +950,7 @@ int _pam_free_handlers(pam_handle_t *pamh) } /* Free all the handlers */ - + _pam_free_handlers_aux(&(pamh->handlers.conf.authenticate)); _pam_free_handlers_aux(&(pamh->handlers.conf.setcred)); _pam_free_handlers_aux(&(pamh->handlers.conf.acct_mgmt)); @@ -863,7 +990,7 @@ void _pam_start_handlers(pam_handle_t *pamh) pamh->handlers.module = NULL; /* initialize the .conf and .other entries */ - + pamh->handlers.conf.authenticate = NULL; pamh->handlers.conf.setcred = NULL; pamh->handlers.conf.acct_mgmt = NULL; |