Continue improving the new configuration parser, particularly error

reporting: error messages relating to policy files now include line
numbers, and the parser will warn about invalid facility names.

Also fix an off-by-one bug in the option handling code.


git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@241 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
Dag-Erling Smørgrav 2003-05-26 15:31:28 +00:00
parent 0fe6f41f7c
commit 6c68711fe1
5 changed files with 79 additions and 50 deletions

View File

@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $P4: //depot/projects/openpam/include/security/openpam.h#22 $ * $P4: //depot/projects/openpam/include/security/openpam.h#23 $
*/ */
#ifndef _SECURITY_OPENPAM_H_INCLUDED #ifndef _SECURITY_OPENPAM_H_INCLUDED
@ -126,6 +126,7 @@ pam_vprompt(pam_handle_t *_pamh,
#ifdef FOPEN_MAX #ifdef FOPEN_MAX
char * char *
openpam_readline(FILE *_f, openpam_readline(FILE *_f,
int *_lineno,
size_t *_lenp); size_t *_lenp);
#endif #endif

View File

@ -31,10 +31,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $P4: //depot/projects/openpam/lib/openpam_configure.c#8 $ * $P4: //depot/projects/openpam/lib/openpam_configure.c#9 $
*/ */
#include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -44,6 +43,21 @@
#include "openpam_impl.h" #include "openpam_impl.h"
const char *_pam_facility_name[PAM_NUM_FACILITIES] = {
[PAM_ACCOUNT] = "account",
[PAM_AUTH] = "auth",
[PAM_PASSWORD] = "password",
[PAM_SESSION] = "session",
};
const char *_pam_control_flag_name[PAM_NUM_CONTROL_FLAGS] = {
[PAM_BINDING] = "binding",
[PAM_OPTIONAL] = "optional",
[PAM_REQUIRED] = "required",
[PAM_REQUISITE] = "requisite",
[PAM_SUFFICIENT] = "sufficient",
};
static int openpam_load_chain(pam_chain_t **, const char *, const char *); static int openpam_load_chain(pam_chain_t **, const char *, const char *);
/* /*
@ -67,10 +81,10 @@ next_word(const char *str)
{ {
/* skip current word */ /* skip current word */
while (*str && !isspace(*str)) while (*str && *str != ' ')
++str; ++str;
/* skip whitespace */ /* skip whitespace */
while (isspace(*str)) while (*str == ' ')
++str; ++str;
return (str); return (str);
} }
@ -84,13 +98,26 @@ dup_word(const char *str)
const char *end; const char *end;
char *word; char *word;
for (end = str; *end && !isspace(*end); ++end) for (end = str; *end && *end != ' '; ++end)
/* nothing */ ; /* nothing */ ;
if (asprintf(&word, "%.*s", (int)(end - str), str) < 0) if (asprintf(&word, "%.*s", (int)(end - str), str) < 0)
return (NULL); return (NULL);
return (word); return (word);
} }
/*
* Return the length of the first word in a string.
*/
static int
wordlen(const char *str)
{
int i;
for (i = 0; str[i] && str[i] != ' '; ++i)
/* nothing */ ;
return (i);
}
typedef enum { pam_conf_style, pam_d_style } openpam_style_t; typedef enum { pam_conf_style, pam_d_style } openpam_style_t;
/* /*
@ -105,19 +132,19 @@ openpam_read_chain(pam_chain_t **chain,
{ {
pam_chain_t *this, **next; pam_chain_t *this, **next;
const char *p, *q; const char *p, *q;
int count, i, ret; int count, i, lineno, ret;
char *line, *name; char *line, *name;
FILE *f; FILE *f;
if ((f = fopen(filename, "r")) == NULL) { if ((f = fopen(filename, "r")) == NULL) {
openpam_log(errno == ENOENT ? PAM_LOG_NOTICE : PAM_LOG_ERROR, openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
"%s: %m", filename); "%s: %m", filename);
return (0); return (0);
} }
next = chain; next = chain;
this = *next = NULL; this = *next = NULL;
count = 0; count = lineno = 0;
while ((line = openpam_readline(f, NULL)) != NULL) { while ((line = openpam_readline(f, &lineno, NULL)) != NULL) {
p = line; p = line;
/* match service name */ /* match service name */
@ -130,6 +157,14 @@ openpam_read_chain(pam_chain_t **chain,
} }
/* match facility name */ /* match facility name */
for (i = 0; i < PAM_NUM_FACILITIES; ++i)
if (match_word(p, _pam_facility_name[i]))
break;
if (i == PAM_NUM_FACILITIES) {
openpam_log(PAM_LOG_NOTICE,
"%s(%d): invalid facility '%.*s' (ignored)",
filename, lineno, wordlen(p), p);
}
if (!match_word(p, facility)) { if (!match_word(p, facility)) {
FREE(line); FREE(line);
continue; continue;
@ -141,8 +176,8 @@ openpam_read_chain(pam_chain_t **chain,
p = next_word(p); p = next_word(p);
if (*next_word(p) != '\0') if (*next_word(p) != '\0')
openpam_log(PAM_LOG_NOTICE, openpam_log(PAM_LOG_NOTICE,
"%s: garbage at end of 'include' line", "%s(%d): garbage at end of 'include' line",
filename); filename, lineno);
if ((name = dup_word(p)) == NULL) if ((name = dup_word(p)) == NULL)
goto syserr; goto syserr;
ret = openpam_load_chain(next, name, facility); ret = openpam_load_chain(next, name, facility);
@ -162,30 +197,23 @@ openpam_read_chain(pam_chain_t **chain,
goto syserr; goto syserr;
/* control flag */ /* control flag */
if (match_word(p, "required")) { for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i)
this->flag = PAM_REQUIRED; if (match_word(p, _pam_control_flag_name[i]))
} else if (match_word(p, "requisite")) { break;
this->flag = PAM_REQUISITE; if (i == PAM_NUM_CONTROL_FLAGS) {
} else if (match_word(p, "sufficient")) {
this->flag = PAM_SUFFICIENT;
} else if (match_word(p, "optional")) {
this->flag = PAM_OPTIONAL;
} else if (match_word(p, "binding")) {
this->flag = PAM_BINDING;
} else {
q = next_word(p);
openpam_log(PAM_LOG_ERROR, openpam_log(PAM_LOG_ERROR,
"%s: invalid control flag '%.*s'", "%s(%d): invalid control flag '%.*s'",
filename, (int)(q - p), p); filename, lineno, wordlen(p), p);
goto fail; goto fail;
} }
this->flag = i;
/* module name */ /* module name */
p = next_word(p); p = next_word(p);
q = next_word(p);
if (*p == '\0') { if (*p == '\0') {
openpam_log(PAM_LOG_ERROR, openpam_log(PAM_LOG_ERROR,
"%s: missing module name", filename); "%s(%d): missing module name",
filename, lineno);
goto fail; goto fail;
} }
if ((name = dup_word(p)) == NULL) if ((name = dup_word(p)) == NULL)
@ -196,6 +224,7 @@ openpam_read_chain(pam_chain_t **chain,
goto fail; goto fail;
/* module options */ /* module options */
p = q = next_word(p);
while (*q != '\0') { while (*q != '\0') {
++this->optc; ++this->optc;
q = next_word(q); q = next_word(q);
@ -204,16 +233,16 @@ openpam_read_chain(pam_chain_t **chain,
if (this->optv == NULL) if (this->optv == NULL)
goto syserr; goto syserr;
for (i = 0; i < this->optc; ++i) { for (i = 0; i < this->optc; ++i) {
p = next_word(p);
if ((this->optv[i] = dup_word(p)) == NULL) if ((this->optv[i] = dup_word(p)) == NULL)
goto syserr; goto syserr;
p = next_word(p);
} }
/* hook it up */ /* hook it up */
*next = this; *next = this;
next = &this->next; next = &this->next;
this = NULL; this = NULL;
++count; ++count;
/* next please... */ /* next please... */
FREE(line); FREE(line);
@ -273,13 +302,6 @@ openpam_load_chain(pam_chain_t **chain,
return (0); return (0);
} }
const char *_pam_chain_name[PAM_NUM_CHAINS] = {
[PAM_AUTH] = "auth",
[PAM_ACCOUNT] = "account",
[PAM_SESSION] = "session",
[PAM_PASSWORD] = "password"
};
/* /*
* OpenPAM internal * OpenPAM internal
* *
@ -292,12 +314,12 @@ openpam_configure(pam_handle_t *pamh,
{ {
int i, ret; int i, ret;
for (i = 0; i < PAM_NUM_CHAINS; ++i) { for (i = 0; i < PAM_NUM_FACILITIES; ++i) {
ret = openpam_load_chain(&pamh->chains[i], ret = openpam_load_chain(&pamh->chains[i],
service, _pam_chain_name[i]); service, _pam_facility_name[i]);
if (ret == 0) if (ret == 0)
ret = openpam_load_chain(&pamh->chains[i], ret = openpam_load_chain(&pamh->chains[i],
PAM_OTHER, _pam_chain_name[i]); PAM_OTHER, _pam_facility_name[i]);
if (ret < 0) { if (ret < 0) {
openpam_clear_chains(pamh->chains); openpam_clear_chains(pamh->chains);
return (PAM_SYSTEM_ERR); return (PAM_SYSTEM_ERR);

View File

@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $P4: //depot/projects/openpam/lib/openpam_impl.h#25 $ * $P4: //depot/projects/openpam/lib/openpam_impl.h#26 $
*/ */
#ifndef _OPENPAM_IMPL_H_INCLUDED #ifndef _OPENPAM_IMPL_H_INCLUDED
@ -49,21 +49,21 @@ extern int _openpam_debug;
/* /*
* Control flags * Control flags
*/ */
#define PAM_BINDING 0
#define PAM_REQUIRED 1 #define PAM_REQUIRED 1
#define PAM_REQUISITE 2 #define PAM_REQUISITE 2
#define PAM_SUFFICIENT 3 #define PAM_SUFFICIENT 3
#define PAM_OPTIONAL 4 #define PAM_OPTIONAL 4
#define PAM_BINDING 5 #define PAM_NUM_CONTROL_FLAGS 5
#define PAM_NUM_CONTROLFLAGS 6
/* /*
* Chains * Facilities
*/ */
#define PAM_AUTH 0 #define PAM_AUTH 0
#define PAM_ACCOUNT 1 #define PAM_ACCOUNT 1
#define PAM_SESSION 2 #define PAM_SESSION 2
#define PAM_PASSWORD 3 #define PAM_PASSWORD 3
#define PAM_NUM_CHAINS 4 #define PAM_NUM_FACILITIES 4
typedef struct pam_chain pam_chain_t; typedef struct pam_chain pam_chain_t;
struct pam_chain { struct pam_chain {
@ -86,7 +86,7 @@ struct pam_handle {
char *service; char *service;
/* chains */ /* chains */
pam_chain_t *chains[PAM_NUM_CHAINS]; pam_chain_t *chains[PAM_NUM_FACILITIES];
pam_chain_t *current; pam_chain_t *current;
int primitive; int primitive;

View File

@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $P4: //depot/projects/openpam/lib/openpam_load.c#17 $ * $P4: //depot/projects/openpam/lib/openpam_load.c#18 $
*/ */
#include <dlfcn.h> #include <dlfcn.h>
@ -170,7 +170,7 @@ openpam_clear_chains(pam_chain_t *policy[])
{ {
int i; int i;
for (i = 0; i < PAM_NUM_CHAINS; ++i) for (i = 0; i < PAM_NUM_FACILITIES; ++i)
openpam_destroy_chain(policy[i]); openpam_destroy_chain(policy[i]);
} }

View File

@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $P4: //depot/projects/openpam/lib/openpam_readline.c#1 $ * $P4: //depot/projects/openpam/lib/openpam_readline.c#2 $
*/ */
#include <ctype.h> #include <ctype.h>
@ -50,7 +50,7 @@
*/ */
char * char *
openpam_readline(FILE *f, size_t *lenp) openpam_readline(FILE *f, int *lineno, size_t *lenp)
{ {
char *line; char *line;
size_t len, size; size_t len, size;
@ -92,6 +92,9 @@ openpam_readline(FILE *f, size_t *lenp)
} }
/* eol */ /* eol */
if (ch == '\n') { if (ch == '\n') {
if (lineno != NULL)
++*lineno;
/* remove trailing whitespace */ /* remove trailing whitespace */
while (len > 0 && isspace(line[len - 1])) while (len > 0 && isspace(line[len - 1]))
--len; --len;
@ -140,6 +143,9 @@ openpam_readline(FILE *f, size_t *lenp)
* If a line ends in a backslash, the backslash is stripped and the next * If a line ends in a backslash, the backslash is stripped and the next
* line is appended. * line is appended.
* *
* If =lineno is not =NULL, the integer variable it points to is
* incremented every time a newline character is read.
*
* If =lenp is not =NULL, the length of the line (not including the * If =lenp is not =NULL, the length of the line (not including the
* terminating NUL character) is stored in the variable it points to. * terminating NUL character) is stored in the variable it points to.
* *