diff --git a/lib/openpam_dispatch.c b/lib/openpam_dispatch.c index 525e41d..f6d57b7 100644 --- a/lib/openpam_dispatch.c +++ b/lib/openpam_dispatch.c @@ -62,11 +62,10 @@ openpam_dispatch(pam_handle_t *pamh, return (PAM_SYSTEM_ERR); /* prevent recursion */ - if (pamh->dispatching) { + if (pamh->current != NULL) { openpam_log(PAM_LOG_ERROR, "indirect recursion"); - return (PAM_SYSTEM_ERR); + return (PAM_ABORT); } - pamh->dispatching = 1; /* pick a chain */ switch (primitive) { @@ -85,7 +84,6 @@ openpam_dispatch(pam_handle_t *pamh, module = pamh->chains[PAM_PASSWORD]; break; default: - pamh->dispatching = 0; return (PAM_SYSTEM_ERR); } @@ -98,10 +96,12 @@ openpam_dispatch(pam_handle_t *pamh, if (module->primitive[primitive] == NULL) { openpam_log(PAM_LOG_ERROR, "%s: no %s()", module->modpath, _pam_sm_func_name[primitive]); - pamh->dispatching = 0; r = PAM_SYMBOL_ERR; } else { - r = (module->primitive[primitive])(pamh, flags); + pamh->current = module; + r = (module->primitive[primitive])(pamh, flags, + module->optc, (const char **)module->optv); + pamh->current = NULL; openpam_log(PAM_LOG_DEBUG, "%s: %s(): %s", module->modpath, _pam_sm_func_name[primitive], pam_strerror(pamh, r)); @@ -147,7 +147,6 @@ openpam_dispatch(pam_handle_t *pamh, } } - pamh->dispatching = 0; return (fail ? err : PAM_SUCCESS); } diff --git a/lib/openpam_impl.h b/lib/openpam_impl.h index 2c13e58..a346fbc 100644 --- a/lib/openpam_impl.h +++ b/lib/openpam_impl.h @@ -67,13 +67,14 @@ extern const char *_pam_sm_func_name[PAM_NUM_PRIMITIVES]; -typedef int (*pam_func_t)(pam_handle_t *, int); +typedef int (*pam_func_t)(pam_handle_t *, int, int, const char **); typedef struct pam_chain pam_chain_t; struct pam_chain { int flag; char *modpath; - /* XXX options */ + int optc; + char **optv; pam_chain_t *next; void *dlh; pam_func_t primitive[PAM_NUM_PRIMITIVES]; @@ -91,10 +92,10 @@ struct pam_data { struct pam_handle { char *service; - int dispatching; /* chains */ pam_chain_t *chains[PAM_NUM_CHAINS]; + pam_chain_t *current; /* items and data */ void *item[PAM_NUM_ITEMS]; @@ -111,7 +112,7 @@ struct pam_handle { int openpam_dispatch(pam_handle_t *, int, int); int openpam_findenv(pam_handle_t *, const char *, size_t); int openpam_add_module(pam_handle_t *, int, int, - const char *, const char *); + const char *, int, const char **); void openpam_clear_chains(pam_handle_t *); #endif diff --git a/lib/openpam_load.c b/lib/openpam_load.c index 4ecf60b..9a4eedd 100644 --- a/lib/openpam_load.c +++ b/lib/openpam_load.c @@ -51,26 +51,40 @@ const char *_pam_sm_func_name[PAM_NUM_PRIMITIVES] = { "pam_sm_setcred" }; +static void +openpam_destroy_module(pam_chain_t *module) +{ + if (module->dlh != NULL) + dlclose(module->dlh); + while (module->optc--) + free(module->optv[module->optc]); + free(module->optv); + free(module->modpath); + free(module); +} + int openpam_add_module(pam_handle_t *pamh, int chain, int flag, const char *modpath, - const char *options /* XXX */ __unused) + int optc, + const char *optv[]) { pam_chain_t *module, *iterator; int i; /* fill in configuration data */ - if ((module = malloc(sizeof(*module))) == NULL) { - openpam_log(PAM_LOG_ERROR, "malloc(): %m"); - return (PAM_BUF_ERR); - } - if ((module->modpath = strdup(modpath)) == NULL) { - openpam_log(PAM_LOG_ERROR, "strdup(): %m"); - free(module); - return (PAM_BUF_ERR); - } + if ((module = calloc(1, sizeof(*module))) == NULL) + goto buf_err; + if ((module->modpath = strdup(modpath)) == NULL) + goto buf_err; + if ((module->optv = malloc(sizeof(char *) * (optc + 1))) == NULL) + goto buf_err; + while (optc--) + if ((module->optv[module->optc++] = strdup(*optv++)) == NULL) + goto buf_err; + module->optv[module->optc] = NULL; module->flag = flag; module->next = NULL; @@ -87,8 +101,7 @@ openpam_add_module(pam_handle_t *pamh, */ if ((module->dlh = dlopen(modpath, RTLD_NOW)) == NULL) { openpam_log(PAM_LOG_ERROR, "dlopen(): %s", dlerror()); - free(module->modpath); - free(module); + openpam_destroy_module(module); return (PAM_OPEN_ERR); } for (i = 0; i < PAM_NUM_PRIMITIVES; ++i) @@ -103,6 +116,11 @@ openpam_add_module(pam_handle_t *pamh, pamh->chains[chain] = module; } return (PAM_SUCCESS); + + buf_err: + openpam_log(PAM_LOG_ERROR, "%m"); + openpam_destroy_module(module); + return (PAM_BUF_ERR); } /* @@ -119,10 +137,7 @@ openpam_clear_chains(pam_handle_t *pamh) while (pamh->chains[i] != NULL) { module = pamh->chains[i]; pamh->chains[i] = module->next; - /* XXX free options */ - dlclose(module->dlh); - free(module->modpath); - free(module); + openpam_destroy_module(module); } } } diff --git a/lib/pam_start.c b/lib/pam_start.c index d2f9e79..0b0f99e 100644 --- a/lib/pam_start.c +++ b/lib/pam_start.c @@ -89,6 +89,7 @@ pam_start(const char *service, #define PAM_CONF_STYLE 0 #define PAM_D_STYLE 1 #define MAX_LINE_LEN 1024 +#define MAX_OPTIONS 256 static int _pam_read_policy_file(pam_handle_t *pamh, @@ -97,7 +98,8 @@ _pam_read_policy_file(pam_handle_t *pamh, int style) { char buf[MAX_LINE_LEN], *p, *q; - int ch, chain, flag, line, n, r; + const char *optv[MAX_OPTIONS + 1]; + int ch, chain, flag, line, optc, n, r; size_t len; FILE *f; @@ -206,18 +208,28 @@ _pam_read_policy_file(pam_handle_t *pamh, goto syntax_error; /* get options */ - if (*q != '\0') { - *q++ = 0; + for (optc = 0; *q != '\0' && optc < MAX_OPTIONS; ++optc) { + *q++ = '\0'; while (isspace(*q)) ++q; + optv[optc] = q; + while (*q != '\0' && !isspace(*q)) + ++q; + } + optv[optc] = NULL; + if (*q != '\0') { + *q = '\0'; + openpam_log(PAM_LOG_ERROR, + "%s: too many options on line %d", + filename, line); } /* * Finally, add the module at the end of the * appropriate chain and bump the counter. */ - if ((r = openpam_add_module(pamh, chain, flag, p, q)) != - PAM_SUCCESS) + r = openpam_add_module(pamh, chain, flag, p, optc, optv); + if (r != PAM_SUCCESS) return (-r); ++n; continue;