Incorporate patches from Dmitry V. Levin which improve the policy

loader, reducing the number of times each file is read.  Also fix
a few minor nits (such as making facility names and control flags
case insensitive like they are in Solaris).


git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@243 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
Dag-Erling Smørgrav 2003-06-01 14:23:25 +00:00
parent 3326a91846
commit 044448812b
2 changed files with 60 additions and 51 deletions

View File

@ -31,9 +31,10 @@
* 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#9 $ * $P4: //depot/projects/openpam/lib/openpam_configure.c#10 $
*/ */
#include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -58,7 +59,7 @@ const char *_pam_control_flag_name[PAM_NUM_CONTROL_FLAGS] = {
[PAM_SUFFICIENT] = "sufficient", [PAM_SUFFICIENT] = "sufficient",
}; };
static int openpam_load_chain(pam_chain_t **, const char *, const char *); static int openpam_load_chain(pam_handle_t *, const char *, pam_facility_t);
/* /*
* Matches a word against the first one in a string. * Matches a word against the first one in a string.
@ -68,7 +69,7 @@ static int
match_word(const char *str, const char *word) match_word(const char *str, const char *word)
{ {
while (*str && *str == *word) while (*str && tolower(*str) == tolower(*word))
++str, ++word; ++str, ++word;
return (*str == ' ' && *word == '\0'); return (*str == ' ' && *word == '\0');
} }
@ -121,18 +122,20 @@ wordlen(const char *str)
typedef enum { pam_conf_style, pam_d_style } openpam_style_t; typedef enum { pam_conf_style, pam_d_style } openpam_style_t;
/* /*
* Extracts a given chain from a policy file. * Extracts given chains from a policy file.
*/ */
static int static int
openpam_read_chain(pam_chain_t **chain, openpam_read_chain(pam_handle_t *pamh,
const char *service, const char *service,
const char *facility, pam_facility_t facility,
const char *filename, const char *filename,
openpam_style_t style) openpam_style_t style)
{ {
pam_chain_t *this, **next; pam_chain_t *this, **next;
const char *p, *q; const char *p, *q;
int count, i, lineno, ret; int count, i, lineno, ret;
pam_facility_t fclt;
pam_control_t ctlf;
char *line, *name; char *line, *name;
FILE *f; FILE *f;
@ -141,8 +144,7 @@ openpam_read_chain(pam_chain_t **chain,
"%s: %m", filename); "%s: %m", filename);
return (0); return (0);
} }
next = chain; this = NULL;
this = *next = NULL;
count = lineno = 0; count = lineno = 0;
while ((line = openpam_readline(f, &lineno, NULL)) != NULL) { while ((line = openpam_readline(f, &lineno, NULL)) != NULL) {
p = line; p = line;
@ -157,15 +159,16 @@ openpam_read_chain(pam_chain_t **chain,
} }
/* match facility name */ /* match facility name */
for (i = 0; i < PAM_NUM_FACILITIES; ++i) for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt)
if (match_word(p, _pam_facility_name[i])) if (match_word(p, _pam_facility_name[fclt]))
break; break;
if (i == PAM_NUM_FACILITIES) { if (fclt == PAM_NUM_FACILITIES) {
openpam_log(PAM_LOG_NOTICE, openpam_log(PAM_LOG_NOTICE,
"%s(%d): invalid facility '%.*s' (ignored)", "%s(%d): invalid facility '%.*s' (ignored)",
filename, lineno, wordlen(p), p); filename, lineno, wordlen(p), p);
goto fail;
} }
if (!match_word(p, facility)) { if (facility != fclt && facility != PAM_FACILITY_ANY) {
FREE(line); FREE(line);
continue; continue;
} }
@ -180,15 +183,13 @@ openpam_read_chain(pam_chain_t **chain,
filename, lineno); 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(pamh, name, fclt);
fprintf(stderr, "include %s returned %d\n", name, ret);
FREE(name); FREE(name);
while (*next != NULL) {
next = &(*next)->next;
++count;
}
FREE(line);
if (ret < 0) if (ret < 0)
goto fail; goto fail;
count += ret;
FREE(line);
continue; continue;
} }
@ -197,16 +198,16 @@ openpam_read_chain(pam_chain_t **chain,
goto syserr; goto syserr;
/* control flag */ /* control flag */
for (i = 0; i < PAM_NUM_CONTROL_FLAGS; ++i) for (ctlf = 0; ctlf < PAM_NUM_CONTROL_FLAGS; ++ctlf)
if (match_word(p, _pam_control_flag_name[i])) if (match_word(p, _pam_control_flag_name[ctlf]))
break; break;
if (i == PAM_NUM_CONTROL_FLAGS) { if (ctlf == PAM_NUM_CONTROL_FLAGS) {
openpam_log(PAM_LOG_ERROR, openpam_log(PAM_LOG_ERROR,
"%s(%d): invalid control flag '%.*s'", "%s(%d): invalid control flag '%.*s'",
filename, lineno, wordlen(p), p); filename, lineno, wordlen(p), p);
goto fail; goto fail;
} }
this->flag = i; this->flag = ctlf;
/* module name */ /* module name */
p = next_word(p); p = next_word(p);
@ -239,8 +240,10 @@ openpam_read_chain(pam_chain_t **chain,
} }
/* hook it up */ /* hook it up */
for (next = &pamh->chains[fclt]; *next != NULL;
next = &(*next)->next)
/* nothing */ ;
*next = this; *next = this;
next = &this->next;
this = NULL; this = NULL;
++count; ++count;
@ -269,13 +272,13 @@ static const char *openpam_policy_path[] = {
}; };
/* /*
* Locates the policy file for a given service and reads the given chain * Locates the policy file for a given service and reads the given chains
* from it. * from it.
*/ */
static int static int
openpam_load_chain(pam_chain_t **chain, openpam_load_chain(pam_handle_t *pamh,
const char *service, const char *service,
const char *facility) pam_facility_t facility)
{ {
const char **path; const char **path;
char *filename; char *filename;
@ -289,11 +292,11 @@ openpam_load_chain(pam_chain_t **chain,
openpam_log(PAM_LOG_ERROR, "asprintf(): %m"); openpam_log(PAM_LOG_ERROR, "asprintf(): %m");
return (-PAM_BUF_ERR); return (-PAM_BUF_ERR);
} }
r = openpam_read_chain(chain, service, facility, r = openpam_read_chain(pamh, service, facility,
filename, pam_d_style); filename, pam_d_style);
FREE(filename); FREE(filename);
} else { } else {
r = openpam_read_chain(chain, service, facility, r = openpam_read_chain(pamh, service, facility,
*path, pam_conf_style); *path, pam_conf_style);
} }
if (r != 0) if (r != 0)
@ -312,20 +315,21 @@ int
openpam_configure(pam_handle_t *pamh, openpam_configure(pam_handle_t *pamh,
const char *service) const char *service)
{ {
int i, ret; pam_facility_t fclt;
for (i = 0; i < PAM_NUM_FACILITIES; ++i) { if (openpam_load_chain(pamh, service, PAM_FACILITY_ANY) < 0)
ret = openpam_load_chain(&pamh->chains[i], goto load_err;
service, _pam_facility_name[i]);
if (ret == 0) for (fclt = 0; fclt < PAM_NUM_FACILITIES; ++fclt) {
ret = openpam_load_chain(&pamh->chains[i], if (pamh->chains[fclt] != NULL)
PAM_OTHER, _pam_facility_name[i]); continue;
if (ret < 0) { if (openpam_load_chain(pamh, PAM_OTHER, fclt) < 0)
openpam_clear_chains(pamh->chains); goto load_err;
return (PAM_SYSTEM_ERR);
}
} }
return (PAM_SUCCESS); return (PAM_SUCCESS);
load_err:
openpam_clear_chains(pamh->chains);
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#26 $ * $P4: //depot/projects/openpam/lib/openpam_impl.h#27 $
*/ */
#ifndef _OPENPAM_IMPL_H_INCLUDED #ifndef _OPENPAM_IMPL_H_INCLUDED
@ -49,21 +49,26 @@ extern int _openpam_debug;
/* /*
* Control flags * Control flags
*/ */
#define PAM_BINDING 0 typedef enum {
#define PAM_REQUIRED 1 PAM_BINDING,
#define PAM_REQUISITE 2 PAM_REQUIRED,
#define PAM_SUFFICIENT 3 PAM_REQUISITE,
#define PAM_OPTIONAL 4 PAM_SUFFICIENT,
#define PAM_NUM_CONTROL_FLAGS 5 PAM_OPTIONAL,
PAM_NUM_CONTROL_FLAGS
} pam_control_t;
/* /*
* Facilities * Facilities
*/ */
#define PAM_AUTH 0 typedef enum {
#define PAM_ACCOUNT 1 PAM_FACILITY_ANY = -1,
#define PAM_SESSION 2 PAM_AUTH = 0,
#define PAM_PASSWORD 3 PAM_ACCOUNT,
#define PAM_NUM_FACILITIES 4 PAM_SESSION,
PAM_PASSWORD,
PAM_NUM_FACILITIES
} pam_facility_t;
typedef struct pam_chain pam_chain_t; typedef struct pam_chain pam_chain_t;
struct pam_chain { struct pam_chain {