Revert large parts of r478. I had forgotten that the module arguments

are actually passed to each service function in the classic (argc,
argv) form.  The only place where the compiler could have caught this
used a type cast, and it did not show up in testing either because all
of the modules I tested use openpam_get_option(3) instead of
manipulating argv directly.

The cleaned-up policy parsing code remains in place, but options are
once more stored as strings, pretty much the way they appear in the
policy file, except that quotes are stripped.


git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@482 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
Dag-Erling Smørgrav 2011-11-03 16:33:02 +00:00
parent c16faba34e
commit 6835696a2a
4 changed files with 48 additions and 54 deletions

View File

@ -269,23 +269,17 @@ parse_filename(char **line, char **filename)
/*
* Parse an option.
*
* Returns a pointer to a dynamically allocated pam_opt_t with the name
* and value of the next module option, or NULL if the end of the string
* was reached or a disallowed non-whitespace character was encountered.
*
* An option consists of an option name optionally followed by an equal
* sign and an option value.
*
* The structure and strings are allocated as a single object, so a single
* free(3) call is sufficient to release the allocated memory.
* Returns a dynamically allocated string containing the next module
* option, or NULL if the end of the string was reached or a disallowed
* non-whitespace character was encountered.
*
* If parse_option() is successful, it updates *line to point one
* character past the end of the option. If it reaches the end of the
* string, it updates *line to point to the terminating NUL character. In
* all other cases, it leaves *line unmodified.
*
* If parse_option() fails to allocate memory for the option structure, it
* will return NULL and set errno to a non-zero value.
* If parse_option() fails to allocate memory, it will return NULL and set
* errno to a non-zero value.
*
* Allowed characters for option names are all characters in the POSIX
* portable filename character set. Allowed characters for option values
@ -294,13 +288,12 @@ parse_filename(char **line, char **filename)
* characters and whichever quote character was not used are allowed.
* Note that the entire value must be quoted, not just part of it.
*/
static pam_opt_t *
static char *
parse_option(char **line)
{
char *nb, *ne, *vb, *ve;
unsigned char q = 0;
pam_opt_t *opt;
size_t size;
char *option;
errno = 0;
for (nb = *line; *nb && is_lws(*nb); ++nb)
@ -331,17 +324,14 @@ parse_option(char **line)
} else {
vb = ve = ne;
}
size = sizeof *opt;
size += ne - nb + 1;
size += ve - vb + 1;
if ((opt = malloc(size)) == NULL)
if ((option = malloc((ne - nb) + 1 + (ve - vb) + 1)) == NULL)
return (NULL);
opt->name = (char *)opt + sizeof *opt;
strlcpy(opt->name, nb, ne - nb + 1);
opt->value = opt->name + (ne - nb) + 1;
strlcpy(opt->value, vb, ve - vb + 1);
strncpy(option, nb, ne - nb);
option[ne - nb] = '=';
strncpy(option + (ne - nb), vb, ve - vb);
option[(ne - nb) + 1 + (ve - vb) + 1] = '\0';
*line = q ? ve + 1 : ve;
return (opt);
return (option);
}
/*
@ -380,8 +370,8 @@ openpam_parse_chain(pam_handle_t *pamh,
int count, lineno;
pam_facility_t fclt;
pam_control_t ctlf;
pam_opt_t *opt;
char *line, *str, *name;
char *option, **optv;
int len, ret;
FILE *f;
@ -470,12 +460,17 @@ openpam_parse_chain(pam_handle_t *pamh,
this->flag = ctlf;
/* get module options */
/* XXX quick and dirty, may waste a few hundred bytes */
if ((this->optv = malloc(sizeof *opt * strlen(line))) == NULL)
goto syserr;
while ((opt = parse_option(&line)) != NULL)
this->optv[this->optc++] = opt;
this->optv[this->optc] = NULL;
this->optv = NULL;
this->optc = 0;
while ((option = parse_option(&line)) != NULL) {
optv = realloc(this->optv,
(this->optc + 2) * sizeof *optv);
if (optv == NULL)
goto syserr;
this->optv = optv;
this->optv[this->optc++] = option;
this->optv[this->optc] = NULL;
}
if (*line != '\0') {
openpam_log(PAM_LOG_ERROR,
"%s(%d): syntax error in module options",

View File

@ -59,15 +59,22 @@ openpam_get_option(pam_handle_t *pamh,
const char *option)
{
pam_chain_t *cur;
size_t len;
int i;
ENTERS(option);
if (pamh == NULL || pamh->current == NULL || option == NULL)
RETURNS(NULL);
cur = pamh->current;
for (i = 0; i < cur->optc; ++i)
if (strcmp(cur->optv[i]->name, option) == 0)
RETURNS(cur->optv[i]->value);
len = strlen(option);
for (i = 0; i < cur->optc; ++i) {
if (strncmp(cur->optv[i], option, len) == 0) {
if (cur->optv[i][len] == '\0')
RETURNS(&cur->optv[i][len]);
else if (cur->optv[i][len] == '=')
RETURNS(&cur->optv[i][len + 1]);
}
}
RETURNS(NULL);
}

View File

@ -71,19 +71,12 @@ typedef enum {
PAM_NUM_FACILITIES
} pam_facility_t;
typedef struct pam_opt pam_opt_t;
struct pam_opt {
char *name;
char *value;
char str[];
};
typedef struct pam_chain pam_chain_t;
struct pam_chain {
pam_module_t *module;
int flag;
int optc;
pam_opt_t **optv;
char **optv;
pam_chain_t *next;
};

View File

@ -62,16 +62,22 @@ openpam_set_option(pam_handle_t *pamh,
const char *value)
{
pam_chain_t *cur;
pam_opt_t *opt, **optv;
int i, ol, vl;
char *opt, **optv;
size_t len;
int i;
ENTERS(option);
if (pamh == NULL || pamh->current == NULL || option == NULL)
RETURNC(PAM_SYSTEM_ERR);
cur = pamh->current;
for (i = 0; i < cur->optc; ++i)
if (strcmp(cur->optv[i]->name, option) == 0)
for (len = 0; option[len] != '\0'; ++len)
if (option[len] == '=')
break;
for (i = 0; i < cur->optc; ++i) {
if (strncmp(cur->optv[i], option, len) == 0 &&
(cur->optv[i][len] == '\0' || cur->optv[i][len] == '='))
break;
}
if (value == NULL) {
/* remove */
if (i == cur->optc)
@ -79,20 +85,13 @@ openpam_set_option(pam_handle_t *pamh,
for (free(cur->optv[i]); i < cur->optc; ++i)
cur->optv[i] = cur->optv[i + 1];
cur->optv[i] = NULL;
cur->optc--;
RETURNC(PAM_SUCCESS);
}
ol = strlen(option) + 1;
vl = strlen(value) + 1;
if ((opt = malloc(sizeof *opt + ol + vl)) == NULL)
if (asprintf(&opt, "%.*s=%s", (int)len, option, value) < 0)
RETURNC(PAM_BUF_ERR);
opt->name = (char *)opt + sizeof *opt;
strlcpy(opt->name, option, ol);
opt->value = opt->name + ol;
strlcpy(opt->value, value, vl);
if (i == cur->optc) {
/* add */
optv = realloc(cur->optv, sizeof *optv * (cur->optc + 2));
optv = realloc(cur->optv, sizeof(char *) * (cur->optc + 2));
if (optv == NULL) {
FREE(opt);
RETURNC(PAM_BUF_ERR);