From 2e2a611647b550639d9230957e839857b79b7f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 4 Feb 2002 15:00:16 +0000 Subject: [PATCH] Store options, and pass them to modules. Replace the "dispatching" flag with a pam_chain_t pointer. It is set to point at the currently executing module right before calling the module, and cleared right after the module returns. Note that this isn't intended to prevent reentrancy in multi-threaded applications, but simply to prevent modules from using the application interface. When recursion is detected, return PAM_ABORT rather than PAM_SYSTEM_ERR, since this is a programmatical error rather than a runtime one. Sponsored by: DARPA, NAI Labs git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@25 185d5e19-27fe-0310-9dcf-9bff6b9f3609 --- lib/openpam_dispatch.c | 13 ++++++------ lib/openpam_impl.h | 9 ++++---- lib/openpam_load.c | 47 ++++++++++++++++++++++++++++-------------- lib/pam_start.c | 22 +++++++++++++++----- 4 files changed, 59 insertions(+), 32 deletions(-) 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;