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
This commit is contained in:
Dag-Erling Smørgrav 2002-02-04 15:00:16 +00:00
parent 073edc1836
commit 2e2a611647
4 changed files with 59 additions and 32 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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;