diff options
author | Sam Hartman <hartmans@debian.org> | 2024-12-02 09:55:34 -0700 |
---|---|---|
committer | Sam Hartman <hartmans@debian.org> | 2024-12-02 09:55:34 -0700 |
commit | 4f3cfaf827bfa42a239c255092a128a3a02198bf (patch) | |
tree | eac7f023f043739b79b2a51bd68c3006acb12964 /libpam/pam_handlers.c | |
parent | 6408d4b1baff9a7e58fd66e1d1c0871be0823777 (diff) | |
parent | 7c9fb6472dcfae34ddbf4fbc9ecfafae2cf173c3 (diff) | |
download | pam-4f3cfaf827bfa42a239c255092a128a3a02198bf.tar.gz pam-4f3cfaf827bfa42a239c255092a128a3a02198bf.tar.bz2 pam-4f3cfaf827bfa42a239c255092a128a3a02198bf.zip |
Update upstream source from tag 'upstream/1.7.0'
Update to upstream version '1.7.0'
with Debian dir 0b3cd490884352e14273caeca2f05c6a525499fa
Diffstat (limited to 'libpam/pam_handlers.c')
-rw-r--r-- | libpam/pam_handlers.c | 226 |
1 files changed, 74 insertions, 152 deletions
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c index 1f1917b5..7fd6ce84 100644 --- a/libpam/pam_handlers.c +++ b/libpam/pam_handlers.c @@ -9,6 +9,7 @@ #include "pam_private.h" #include "pam_inline.h" +#include <limits.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -17,21 +18,20 @@ #include <fcntl.h> #include <unistd.h> -#define BUF_SIZE 1024 +#include "pam_line.h" + #define MODULE_CHUNK 4 #define UNKNOWN_MODULE "<*unknown module*>" #ifndef _PAM_ISA #define _PAM_ISA "." #endif -static int _pam_assemble_line(FILE *f, char *buf, int buf_len); - static void _pam_free_handlers_aux(struct handler **hp); static int _pam_add_handler(pam_handle_t *pamh , int must_fail, int other, int stack_level, int type , int *actions, const char *mod_path - , int argc, char **argv, int argvlen); + , int argc, char **argv, size_t argvlen); /* Values for module type */ @@ -44,6 +44,7 @@ static int _pam_add_handler(pam_handle_t *pamh static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name , const char *service /* specific file */ , int module_type /* specific type */ + , int include_level /* level of include */ , int stack_level /* level of substack */ #ifdef PAM_READ_BOTH_CONFS , int not_other @@ -53,18 +54,22 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f , const char *known_service /* specific file */ , int requested_module_type /* specific type */ + , int include_level /* level of include */ , int stack_level /* level of substack */ #ifdef PAM_READ_BOTH_CONFS , int not_other #endif /* PAM_READ_BOTH_CONFS */ ) { - char buf[BUF_SIZE]; + struct pam_line_buffer buffer; int x; /* read a line from the FILE *f ? */ + + _pam_line_buffer_init(&buffer); /* * read a line from the configuration (FILE *) f */ - while ((x = _pam_assemble_line(f, buf, BUF_SIZE)) > 0) { + while ((x = _pam_line_assemble(f, &buffer, ' ')) > 0) { + char *buf = buffer.assembled; char *tok, *nexttok=NULL; const char *this_service; const char *mod_path; @@ -74,15 +79,15 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f int handler_type = PAM_HT_MODULE; /* regular handler from a module */ int argc; char **argv; - int argvlen; + size_t argvlen; - D(("_pam_init_handler: LINE: %s", buf)); + D(("LINE: %s", buf)); if (known_service != NULL) { nexttok = buf; /* No service field: all lines are for the known service. */ this_service = known_service; } else { - this_service = tok = _pam_StrTok(buf, " \n\t", &nexttok); + this_service = tok = _pam_tokenize(buf, &nexttok); } #ifdef PAM_READ_BOTH_CONFS @@ -98,13 +103,12 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f int substack = 0; /* This is a service we are looking for */ - D(("_pam_init_handlers: Found PAM config entry for: %s" - , this_service)); + D(("Found PAM config entry for: %s", this_service)); - tok = _pam_StrTok(NULL, " \n\t", &nexttok); + tok = _pam_tokenize(NULL, &nexttok); if (tok == NULL) { /* module type does not exist */ - D(("_pam_init_handlers: empty module type for %s", this_service)); + D(("empty module type for %s", this_service)); pam_syslog(pamh, LOG_ERR, "(%s) empty module type", this_service); module_type = (requested_module_type != PAM_T_ANY) ? @@ -125,7 +129,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f module_type = PAM_T_PASS; } else { /* Illegal module type */ - D(("_pam_init_handlers: bad module type: %s", tok)); + D(("bad module type: %s", tok)); pam_syslog(pamh, LOG_ERR, "(%s) illegal module type: %s", this_service, tok); module_type = (requested_module_type != PAM_T_ANY) ? @@ -133,7 +137,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */ } } - D(("Using %s config entry: %s", handler_type?"BAD ":"", tok)); + D(("Using %sconfig entry: %s", handler_type?"BAD ":"", tok)); if (requested_module_type != PAM_T_ANY && module_type != requested_module_type) { D(("Skipping config entry: %s (requested=%d, found=%d)", @@ -148,10 +152,10 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f for (i=0; i<_PAM_RETURN_VALUES; actions[i++] = _PAM_ACTION_UNDEF); } - tok = _pam_StrTok(NULL, " \n\t", &nexttok); + tok = _pam_tokenize(NULL, &nexttok); if (tok == NULL) { /* no module name given */ - D(("_pam_init_handlers: no control flag supplied")); + D(("no control flag supplied")); pam_syslog(pamh, LOG_ERR, "(%s) no control flag supplied", this_service); _pam_set_default_control(actions, _PAM_ACTION_BAD); @@ -193,7 +197,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f _pam_set_default_control(actions, _PAM_ACTION_BAD); } - tok = _pam_StrTok(NULL, " \n\t", &nexttok); + tok = _pam_tokenize(NULL, &nexttok); if (pam_include) { if (substack) { res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other, @@ -206,7 +210,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f } } if (_pam_load_conf_file(pamh, tok, this_service, module_type, - stack_level + substack + include_level + 1, stack_level + substack #ifdef PAM_READ_BOTH_CONFS , !other #endif /* PAM_READ_BOTH_CONFS */ @@ -221,7 +225,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f D(("mod_path = %s",mod_path)); } else { /* no module name given */ - D(("_pam_init_handlers: no module name supplied")); + D(("no module name supplied")); pam_syslog(pamh, LOG_ERR, "(%s) no module name supplied", this_service); mod_path = NULL; @@ -233,10 +237,20 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f if (nexttok != NULL) { D(("list: %s",nexttok)); argvlen = _pam_mkargv(nexttok, &argv, &argc); - D(("argvlen = %d",argvlen)); + D(("argvlen = %zu",argvlen)); + if (argvlen == 0) { + /* memory allocation failed */ + D(("failed to allocate argument vector")); + pam_syslog(pamh, LOG_ERR, + "(%s) argument vector allocation failed", + this_service); + mod_path = NULL; + handler_type = PAM_HT_MUST_FAIL; + } } else { /* there are no arguments so fix by hand */ - D(("_pam_init_handlers: empty argument list")); - argvlen = argc = 0; + D(("empty argument list")); + argvlen = 0; + argc = 0; argv = NULL; } @@ -340,6 +354,7 @@ _pam_open_config_file(pam_handle_t *pamh static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name , const char *service /* specific file */ , int module_type /* specific type */ + , int include_level /* level of include */ , int stack_level /* level of substack */ #ifdef PAM_READ_BOTH_CONFS , int not_other @@ -350,11 +365,11 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name char *path = NULL; int retval = PAM_ABORT; - D(("_pam_load_conf_file called")); + D(("called.")); - if (stack_level >= PAM_SUBSTACK_MAX_LEVEL) { - D(("maximum level of substacks reached")); - pam_syslog(pamh, LOG_ERR, "maximum level of substacks reached"); + if (include_level >= PAM_SUBSTACK_MAX_LEVEL) { + D(("maximum level of inclusions reached")); + pam_syslog(pamh, LOG_ERR, "maximum level of inclusions reached"); return PAM_ABORT; } @@ -365,7 +380,7 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name } if (_pam_open_config_file(pamh, config_name, &path, &f) == PAM_SUCCESS) { - retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level + retval = _pam_parse_conf_file(pamh, f, service, module_type, include_level, stack_level #ifdef PAM_READ_BOTH_CONFS , not_other #endif /* PAM_READ_BOTH_CONFS */ @@ -392,15 +407,15 @@ int _pam_init_handlers(pam_handle_t *pamh) FILE *f; int retval; - D(("_pam_init_handlers called")); - IF_NO_PAMH("_pam_init_handlers",pamh,PAM_SYSTEM_ERR); + D(("called.")); + IF_NO_PAMH(pamh,PAM_SYSTEM_ERR); /* Return immediately if everything is already loaded */ if (pamh->handlers.handlers_loaded) { return PAM_SUCCESS; } - D(("_pam_init_handlers: initializing")); + D(("initializing")); /* First clean the service structure */ @@ -462,7 +477,7 @@ int _pam_init_handlers(pam_handle_t *pamh) 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 + PAM_T_ANY, 0, 0 #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ @@ -485,7 +500,7 @@ int _pam_init_handlers(pam_handle_t *pamh) if (pamh->confdir == NULL && (f = fopen(PAM_CONFIG,"r")) != NULL) { - retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 1); + retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 0, 1); fclose(f); } else #endif /* PAM_READ_BOTH_CONFS */ @@ -502,7 +517,7 @@ int _pam_init_handlers(pam_handle_t *pamh) 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 + PAM_T_ANY, 0, 0 #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ @@ -520,7 +535,7 @@ int _pam_init_handlers(pam_handle_t *pamh) _pam_drop(path); fclose(f); } else { - D(("unable to open %s", PAM_DEFAULT_SERVICE)); + D(("unable to open configuration for %s", PAM_DEFAULT_SERVICE)); pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: no default config %s", PAM_DEFAULT_SERVICE); @@ -536,7 +551,7 @@ int _pam_init_handlers(pam_handle_t *pamh) return PAM_ABORT; } - retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0 + retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 0 #ifdef PAM_READ_BOTH_CONFS , 0 #endif /* PAM_READ_BOTH_CONFS */ @@ -555,94 +570,10 @@ int _pam_init_handlers(pam_handle_t *pamh) pamh->handlers.handlers_loaded = 1; - D(("_pam_init_handlers exiting")); + D(("exiting")); return PAM_SUCCESS; } -/* - * This is where we read a line of the PAM config file. The line may be - * preceded by lines of comments and also extended with "\\\n" - */ - -static int _pam_assemble_line(FILE *f, char *buffer, int buf_len) -{ - char *p = buffer; - char *endp = buffer + buf_len; - char *s, *os; - int used = 0; - - /* loop broken with a 'break' when a non-'\\n' ended line is read */ - - D(("called.")); - for (;;) { - if (p >= endp) { - /* Overflow */ - D(("_pam_assemble_line: overflow")); - return -1; - } - if (fgets(p, endp - p, f) == NULL) { - if (used) { - /* Incomplete read */ - return -1; - } else { - /* EOF */ - return 0; - } - } - - /* skip leading spaces --- line may be blank */ - - s = p + strspn(p, " \n\t"); - if (*s && (*s != '#')) { - os = s; - - /* - * we are only interested in characters before the first '#' - * character - */ - - while (*s && *s != '#') - ++s; - if (*s == '#') { - *s = '\0'; - used += strlen(os); - break; /* the line has been read */ - } - - s = os; - - /* - * Check for backslash by scanning back from the end of - * the entered line, the '\n' has been included since - * normally a line is terminated with this - * character. fgets() should only return one though! - */ - - s += strlen(s); - while (s > os && ((*--s == ' ') || (*s == '\t') - || (*s == '\n'))); - - /* check if it ends with a backslash */ - if (*s == '\\') { - *s++ = ' '; /* replace backslash with ' ' */ - *s = '\0'; /* truncate the line here */ - used += strlen(os); - p = s; /* there is more ... */ - } else { - /* End of the line! */ - used += strlen(os); - break; /* this is the complete line */ - } - - } else { - /* Nothing in this line */ - /* Don't move p */ - } - } - - return used; -} - static char * extract_modulename(const char *mod_path) { @@ -677,7 +608,7 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type) int success; struct loaded_module *mod; - D(("_pam_load_module: loading module `%s'", mod_path)); + D(("loading module `%s'", mod_path)); mod = pamh->handlers.module; @@ -708,39 +639,30 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type) /* Be pessimistic... */ success = PAM_ABORT; - D(("_pam_load_module: _pam_dlopen(%s)", mod_path)); + D(("_pam_dlopen(%s)", mod_path)); mod->dl_handle = _pam_dlopen(mod_path); - D(("_pam_load_module: _pam_dlopen'ed")); - D(("_pam_load_module: dlopen'ed")); + D(("_pam_dlopen'ed")); + D(("dlopen'ed")); if (mod->dl_handle == NULL) { const char *isa = strstr(mod_path, "$ISA"); size_t isa_len = strlen("$ISA"); if (isa != NULL) { - size_t pam_isa_len = strlen(_PAM_ISA); - char *mod_full_isa_path = - malloc(strlen(mod_path) - isa_len + pam_isa_len + 1); - - if (mod_full_isa_path == NULL) { - D(("_pam_load_module: couldn't get memory for mod_path")); + char *mod_full_isa_path = NULL; + if (strlen(mod_path) >= INT_MAX || + asprintf(&mod_full_isa_path, "%.*s%s%s", + (int)(isa - mod_path), mod_path, _PAM_ISA, isa + isa_len) < 0) { + D(("couldn't get memory for mod_path")); pam_syslog(pamh, LOG_CRIT, "no memory for module path"); success = PAM_ABORT; } else { - char *p = mod_full_isa_path; - - memcpy(p, mod_path, isa - mod_path); - p += isa - mod_path; - memcpy(p, _PAM_ISA, pam_isa_len); - p += pam_isa_len; - strcpy(p, isa + isa_len); - mod->dl_handle = _pam_dlopen(mod_full_isa_path); _pam_drop(mod_full_isa_path); } } } if (mod->dl_handle == NULL) { - D(("_pam_load_module: _pam_dlopen(%s) failed", mod_path)); + D(("_pam_dlopen(%s) failed", mod_path)); if (handler_type != PAM_HT_SILENT_MODULE) pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s): %s", mod_path, _pam_dlerror()); @@ -764,7 +686,7 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type) /* indicate its name - later we will search for it by this */ if ((mod->name = _pam_strdup(mod_path)) == NULL) { - D(("_pam_load_module: couldn't get memory for mod_path")); + D(("couldn't get memory for mod_path")); pam_syslog(pamh, LOG_CRIT, "no memory for module path"); success = PAM_ABORT; } @@ -776,10 +698,10 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type) return success == PAM_SUCCESS ? mod : NULL; } -int _pam_add_handler(pam_handle_t *pamh - , int handler_type, int other, int stack_level, int type - , int *actions, const char *mod_path - , int argc, char **argv, int argvlen) +static int _pam_add_handler(pam_handle_t *pamh + , int handler_type, int other, int stack_level + , int type, int *actions, const char *mod_path + , int argc, char **argv, size_t argvlen) { struct loaded_module *mod = NULL; struct handler **handler_p; @@ -791,9 +713,9 @@ int _pam_add_handler(pam_handle_t *pamh int mod_type = PAM_MT_FAULTY_MOD; D(("called.")); - IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH(pamh,PAM_SYSTEM_ERR); - D(("_pam_add_handler: adding type %d, handler_type %d, module `%s'", + D(("adding type %d, handler_type %d, module `%s'", type, handler_type, mod_path)); if ((handler_type == PAM_HT_MODULE || handler_type == PAM_HT_SILENT_MODULE) && @@ -857,14 +779,14 @@ int _pam_add_handler(pam_handle_t *pamh break; default: /* Illegal module type */ - D(("_pam_add_handler: illegal module type %d", type)); + D(("illegal module type %d", type)); return PAM_ABORT; } /* are the modules reliable? */ if (mod_type != PAM_MT_DYNAMIC_MOD && mod_type != PAM_MT_FAULTY_MOD) { - D(("_pam_add_handlers: illegal module library type; %d", mod_type)); + D(("illegal module library type; %d", mod_type)); pam_syslog(pamh, LOG_ERR, "internal error: module library type not known: %s;%d", sym, mod_type); @@ -938,7 +860,7 @@ int _pam_add_handler(pam_handle_t *pamh return PAM_ABORT; } - D(("_pam_add_handler: returning successfully")); + D(("returning successfully")); return PAM_SUCCESS; } @@ -949,14 +871,14 @@ int _pam_free_handlers(pam_handle_t *pamh) struct loaded_module *mod; D(("called.")); - IF_NO_PAMH("_pam_free_handlers",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH(pamh,PAM_SYSTEM_ERR); mod = pamh->handlers.module; /* Close all loaded modules */ while (pamh->handlers.modules_used) { - D(("_pam_free_handlers: dlclose(%s)", mod->name)); + D(("dlclose(%s)", mod->name)); free(mod->name); if (mod->type == PAM_MT_DYNAMIC_MOD) { _pam_dlclose(mod->dl_handle); |