Overhaul the configuration parser. This adds support for continuation
lines and policy inclusion. git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@240 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
f8a8bd8714
commit
0fe6f41f7c
3
MANIFEST
3
MANIFEST
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# $P4: //depot/projects/openpam/MANIFEST#14 $
|
# $P4: //depot/projects/openpam/MANIFEST#15 $
|
||||||
#
|
#
|
||||||
CREDITS
|
CREDITS
|
||||||
HISTORY
|
HISTORY
|
||||||
|
@ -78,6 +78,7 @@ lib/openpam_impl.h
|
||||||
lib/openpam_load.c
|
lib/openpam_load.c
|
||||||
lib/openpam_log.c
|
lib/openpam_log.c
|
||||||
lib/openpam_nullconv.c
|
lib/openpam_nullconv.c
|
||||||
|
lib/openpam_readline.c
|
||||||
lib/openpam_restore_cred.c
|
lib/openpam_restore_cred.c
|
||||||
lib/openpam_set_option.c
|
lib/openpam_set_option.c
|
||||||
lib/openpam_static.c
|
lib/openpam_static.c
|
||||||
|
|
|
@ -32,7 +32,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/doc/man/Makefile#11 $
|
# $P4: //depot/projects/openpam/doc/man/Makefile#12 $
|
||||||
#
|
#
|
||||||
|
|
||||||
GENDOC = ${.CURDIR}/../../misc/gendoc.pl
|
GENDOC = ${.CURDIR}/../../misc/gendoc.pl
|
||||||
|
@ -73,6 +73,7 @@ OMAN += openpam_free_data.3
|
||||||
OMAN += openpam_get_option.3
|
OMAN += openpam_get_option.3
|
||||||
OMAN += openpam_log.3
|
OMAN += openpam_log.3
|
||||||
OMAN += openpam_nullconv.3
|
OMAN += openpam_nullconv.3
|
||||||
|
OMAN += openpam_readline.3
|
||||||
OMAN += openpam_restore_cred.3
|
OMAN += openpam_restore_cred.3
|
||||||
OMAN += openpam_set_option.3
|
OMAN += openpam_set_option.3
|
||||||
OMAN += openpam_ttyconv.3
|
OMAN += openpam_ttyconv.3
|
||||||
|
|
|
@ -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#21 $
|
* $P4: //depot/projects/openpam/include/security/openpam.h#22 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SECURITY_OPENPAM_H_INCLUDED
|
#ifndef _SECURITY_OPENPAM_H_INCLUDED
|
||||||
|
@ -118,6 +118,17 @@ pam_vprompt(pam_handle_t *_pamh,
|
||||||
const char *_fmt,
|
const char *_fmt,
|
||||||
va_list _ap);
|
va_list _ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read cooked lines.
|
||||||
|
* Checking for FOPEN_MAX is a fairly reliable way to detect the presence
|
||||||
|
* of <stdio.h>
|
||||||
|
*/
|
||||||
|
#ifdef FOPEN_MAX
|
||||||
|
char *
|
||||||
|
openpam_readline(FILE *_f,
|
||||||
|
size_t *_lenp);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Log levels
|
* Log levels
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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/Makefile#19 $
|
# $P4: //depot/projects/openpam/lib/Makefile#20 $
|
||||||
#
|
#
|
||||||
|
|
||||||
LIB = pam
|
LIB = pam
|
||||||
|
@ -57,6 +57,7 @@ SRCS += openpam_get_option.c
|
||||||
SRCS += openpam_load.c
|
SRCS += openpam_load.c
|
||||||
SRCS += openpam_log.c
|
SRCS += openpam_log.c
|
||||||
SRCS += openpam_nullconv.c
|
SRCS += openpam_nullconv.c
|
||||||
|
SRCS += openpam_readline.c
|
||||||
SRCS += openpam_restore_cred.c
|
SRCS += openpam_restore_cred.c
|
||||||
SRCS += openpam_set_option.c
|
SRCS += openpam_set_option.c
|
||||||
SRCS += openpam_static.c
|
SRCS += openpam_static.c
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2002 Networks Associates Technology, Inc.
|
* Copyright (c) 2001-2003 Networks Associates Technology, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This software was developed for the FreeBSD Project by ThinkSec AS and
|
* This software was developed for the FreeBSD Project by ThinkSec AS and
|
||||||
|
@ -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_configure.c#7 $
|
* $P4: //depot/projects/openpam/lib/openpam_configure.c#8 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -44,169 +44,191 @@
|
||||||
|
|
||||||
#include "openpam_impl.h"
|
#include "openpam_impl.h"
|
||||||
|
|
||||||
#define PAM_CONF_STYLE 0
|
static int openpam_load_chain(pam_chain_t **, const char *, const char *);
|
||||||
#define PAM_D_STYLE 1
|
|
||||||
#define MAX_LINE_LEN 1024
|
|
||||||
#define MAX_OPTIONS 256
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Matches a word against the first one in a string.
|
||||||
|
* Returns non-zero if they match.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
openpam_read_policy_file(pam_chain_t *policy[],
|
match_word(const char *str, const char *word)
|
||||||
const char *service,
|
|
||||||
const char *filename,
|
|
||||||
int style)
|
|
||||||
{
|
{
|
||||||
char buf[MAX_LINE_LEN], *p, *q;
|
|
||||||
const char *optv[MAX_OPTIONS + 1];
|
while (*str && *str == *word)
|
||||||
int ch, chain, flag, line, optc, n, r;
|
++str, ++word;
|
||||||
size_t len;
|
return (*str == ' ' && *word == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a pointer to the next word (or the final NUL) in a string.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
next_word(const char *str)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* skip current word */
|
||||||
|
while (*str && !isspace(*str))
|
||||||
|
++str;
|
||||||
|
/* skip whitespace */
|
||||||
|
while (isspace(*str))
|
||||||
|
++str;
|
||||||
|
return (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return a malloc()ed copy of the first word in a string.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
dup_word(const char *str)
|
||||||
|
{
|
||||||
|
const char *end;
|
||||||
|
char *word;
|
||||||
|
|
||||||
|
for (end = str; *end && !isspace(*end); ++end)
|
||||||
|
/* nothing */ ;
|
||||||
|
if (asprintf(&word, "%.*s", (int)(end - str), str) < 0)
|
||||||
|
return (NULL);
|
||||||
|
return (word);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum { pam_conf_style, pam_d_style } openpam_style_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extracts a given chain from a policy file.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
openpam_read_chain(pam_chain_t **chain,
|
||||||
|
const char *service,
|
||||||
|
const char *facility,
|
||||||
|
const char *filename,
|
||||||
|
openpam_style_t style)
|
||||||
|
{
|
||||||
|
pam_chain_t *this, **next;
|
||||||
|
const char *p, *q;
|
||||||
|
int count, i, ret;
|
||||||
|
char *line, *name;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
if ((f = fopen(filename, "r")) == NULL) {
|
if ((f = fopen(filename, "r")) == NULL) {
|
||||||
openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
|
openpam_log(errno == ENOENT ? PAM_LOG_NOTICE : PAM_LOG_ERROR,
|
||||||
"%s: %m", filename);
|
"%s: %m", filename);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
openpam_log(PAM_LOG_DEBUG, "looking for '%s' in %s",
|
next = chain;
|
||||||
service, filename);
|
this = *next = NULL;
|
||||||
|
count = 0;
|
||||||
|
while ((line = openpam_readline(f, NULL)) != NULL) {
|
||||||
|
p = line;
|
||||||
|
|
||||||
for (line = 1; fgets(buf, MAX_LINE_LEN, f) != NULL; ++line) {
|
/* match service name */
|
||||||
if ((len = strlen(buf)) == 0)
|
if (style == pam_conf_style) {
|
||||||
continue;
|
if (!match_word(p, service)) {
|
||||||
|
FREE(line);
|
||||||
/* check for overflow */
|
|
||||||
if (buf[--len] != '\n' && !feof(f)) {
|
|
||||||
openpam_log(PAM_LOG_ERROR, "%s: line %d too long",
|
|
||||||
filename, line);
|
|
||||||
openpam_log(PAM_LOG_ERROR, "%s: ignoring line %d",
|
|
||||||
filename, line);
|
|
||||||
while ((ch = fgetc(f)) != EOF)
|
|
||||||
if (ch == '\n')
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strip comments and trailing whitespace */
|
|
||||||
if ((p = strchr(buf, '#')) != NULL)
|
|
||||||
len = p - buf ? p - buf - 1 : p - buf;
|
|
||||||
while (len > 0 && isspace(buf[len - 1]))
|
|
||||||
--len;
|
|
||||||
if (len == 0)
|
|
||||||
continue;
|
|
||||||
buf[len] = '\0';
|
|
||||||
p = q = buf;
|
|
||||||
|
|
||||||
/* check service name */
|
|
||||||
if (style == PAM_CONF_STYLE) {
|
|
||||||
for (q = p = buf; *q != '\0' && !isspace(*q); ++q)
|
|
||||||
/* nothing */;
|
|
||||||
if (*q == '\0')
|
|
||||||
goto syntax_error;
|
|
||||||
*q++ = '\0';
|
|
||||||
if (strcmp(p, service) != 0)
|
|
||||||
continue;
|
continue;
|
||||||
openpam_log(PAM_LOG_DEBUG, "%s: line %d matches '%s'",
|
}
|
||||||
filename, line, service);
|
p = next_word(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* match facility name */
|
||||||
|
if (!match_word(p, facility)) {
|
||||||
|
FREE(line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p = next_word(p);
|
||||||
|
|
||||||
/* get module type */
|
/* include other chain */
|
||||||
for (p = q; isspace(*p); ++p)
|
if (match_word(p, "include")) {
|
||||||
/* nothing */;
|
p = next_word(p);
|
||||||
for (q = p; *q != '\0' && !isspace(*q); ++q)
|
if (*next_word(p) != '\0')
|
||||||
/* nothing */;
|
openpam_log(PAM_LOG_NOTICE,
|
||||||
if (q == p || *q == '\0')
|
"%s: garbage at end of 'include' line",
|
||||||
goto syntax_error;
|
filename);
|
||||||
*q++ = '\0';
|
if ((name = dup_word(p)) == NULL)
|
||||||
if (strcmp(p, "auth") == 0) {
|
goto syserr;
|
||||||
chain = PAM_AUTH;
|
ret = openpam_load_chain(next, name, facility);
|
||||||
} else if (strcmp(p, "account") == 0) {
|
FREE(name);
|
||||||
chain = PAM_ACCOUNT;
|
while (*next != NULL) {
|
||||||
} else if (strcmp(p, "session") == 0) {
|
next = &(*next)->next;
|
||||||
chain = PAM_SESSION;
|
++count;
|
||||||
} else if (strcmp(p, "password") == 0) {
|
}
|
||||||
chain = PAM_PASSWORD;
|
FREE(line);
|
||||||
} else {
|
if (ret < 0)
|
||||||
openpam_log(PAM_LOG_ERROR,
|
goto fail;
|
||||||
"%s: invalid module type on line %d: '%s'",
|
|
||||||
filename, line, p);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get control flag */
|
/* allocate new entry */
|
||||||
for (p = q; isspace(*p); ++p)
|
if ((this = calloc(1, sizeof *this)) == NULL)
|
||||||
/* nothing */;
|
goto syserr;
|
||||||
for (q = p; *q != '\0' && !isspace(*q); ++q)
|
|
||||||
/* nothing */;
|
/* control flag */
|
||||||
if (q == p || *q == '\0')
|
if (match_word(p, "required")) {
|
||||||
goto syntax_error;
|
this->flag = PAM_REQUIRED;
|
||||||
*q++ = '\0';
|
} else if (match_word(p, "requisite")) {
|
||||||
if (strcmp(p, "required") == 0) {
|
this->flag = PAM_REQUISITE;
|
||||||
flag = PAM_REQUIRED;
|
} else if (match_word(p, "sufficient")) {
|
||||||
} else if (strcmp(p, "requisite") == 0) {
|
this->flag = PAM_SUFFICIENT;
|
||||||
flag = PAM_REQUISITE;
|
} else if (match_word(p, "optional")) {
|
||||||
} else if (strcmp(p, "sufficient") == 0) {
|
this->flag = PAM_OPTIONAL;
|
||||||
flag = PAM_SUFFICIENT;
|
} else if (match_word(p, "binding")) {
|
||||||
} else if (strcmp(p, "optional") == 0) {
|
this->flag = PAM_BINDING;
|
||||||
flag = PAM_OPTIONAL;
|
|
||||||
} else if (strcmp(p, "binding") == 0) {
|
|
||||||
flag = PAM_BINDING;
|
|
||||||
} else {
|
} else {
|
||||||
|
q = next_word(p);
|
||||||
openpam_log(PAM_LOG_ERROR,
|
openpam_log(PAM_LOG_ERROR,
|
||||||
"%s: invalid control flag on line %d: '%s'",
|
"%s: invalid control flag '%.*s'",
|
||||||
filename, line, p);
|
filename, (int)(q - p), p);
|
||||||
continue;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get module name */
|
/* module name */
|
||||||
for (p = q; isspace(*p); ++p)
|
p = next_word(p);
|
||||||
/* nothing */;
|
q = next_word(p);
|
||||||
for (q = p; *q != '\0' && !isspace(*q); ++q)
|
if (*p == '\0') {
|
||||||
/* nothing */;
|
|
||||||
if (q == p)
|
|
||||||
goto syntax_error;
|
|
||||||
|
|
||||||
/* get options */
|
|
||||||
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,
|
openpam_log(PAM_LOG_ERROR,
|
||||||
"%s: too many options on line %d",
|
"%s: missing module name", filename);
|
||||||
filename, line);
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((name = dup_word(p)) == NULL)
|
||||||
|
goto syserr;
|
||||||
|
this->module = openpam_load_module(name);
|
||||||
|
FREE(name);
|
||||||
|
if (this->module == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* module options */
|
||||||
|
while (*q != '\0') {
|
||||||
|
++this->optc;
|
||||||
|
q = next_word(q);
|
||||||
|
}
|
||||||
|
this->optv = calloc(this->optc + 1, sizeof(char *));
|
||||||
|
if (this->optv == NULL)
|
||||||
|
goto syserr;
|
||||||
|
for (i = 0; i < this->optc; ++i) {
|
||||||
|
p = next_word(p);
|
||||||
|
if ((this->optv[i] = dup_word(p)) == NULL)
|
||||||
|
goto syserr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* hook it up */
|
||||||
* Finally, add the module at the end of the
|
*next = this;
|
||||||
* appropriate chain and bump the counter.
|
next = &this->next;
|
||||||
*/
|
this = NULL;
|
||||||
r = openpam_add_module(policy, chain, flag, p, optc, optv);
|
++count;
|
||||||
if (r != PAM_SUCCESS)
|
|
||||||
return (-r);
|
/* next please... */
|
||||||
++n;
|
FREE(line);
|
||||||
continue;
|
|
||||||
syntax_error:
|
|
||||||
openpam_log(PAM_LOG_ERROR, "%s: syntax error on line %d",
|
|
||||||
filename, line);
|
|
||||||
openpam_log(PAM_LOG_DEBUG, "%s: line %d: [%s]",
|
|
||||||
filename, line, q);
|
|
||||||
openpam_log(PAM_LOG_ERROR, "%s: ignoring line %d",
|
|
||||||
filename, line);
|
|
||||||
}
|
}
|
||||||
|
if (!feof(f))
|
||||||
if (ferror(f))
|
goto syserr;
|
||||||
openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
|
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return (n);
|
return (count);
|
||||||
|
syserr:
|
||||||
|
openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
|
||||||
|
fail:
|
||||||
|
FREE(this);
|
||||||
|
FREE(line);
|
||||||
|
fclose(f);
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *openpam_policy_path[] = {
|
static const char *openpam_policy_path[] = {
|
||||||
|
@ -217,9 +239,14 @@ static const char *openpam_policy_path[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locates the policy file for a given service and reads the given chain
|
||||||
|
* from it.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
openpam_load_policy(pam_chain_t *policy[],
|
openpam_load_chain(pam_chain_t **chain,
|
||||||
const char *service)
|
const char *service,
|
||||||
|
const char *facility)
|
||||||
{
|
{
|
||||||
const char **path;
|
const char **path;
|
||||||
char *filename;
|
char *filename;
|
||||||
|
@ -229,27 +256,30 @@ openpam_load_policy(pam_chain_t *policy[],
|
||||||
for (path = openpam_policy_path; *path != NULL; ++path) {
|
for (path = openpam_policy_path; *path != NULL; ++path) {
|
||||||
len = strlen(*path);
|
len = strlen(*path);
|
||||||
if ((*path)[len - 1] == '/') {
|
if ((*path)[len - 1] == '/') {
|
||||||
filename = malloc(len + strlen(service) + 1);
|
if (asprintf(&filename, "%s%s", *path, service) < 0) {
|
||||||
if (filename == NULL) {
|
openpam_log(PAM_LOG_ERROR, "asprintf(): %m");
|
||||||
openpam_log(PAM_LOG_ERROR, "malloc(): %m");
|
|
||||||
return (-PAM_BUF_ERR);
|
return (-PAM_BUF_ERR);
|
||||||
}
|
}
|
||||||
strcpy(filename, *path);
|
r = openpam_read_chain(chain, service, facility,
|
||||||
strcat(filename, service);
|
filename, pam_d_style);
|
||||||
r = openpam_read_policy_file(policy,
|
|
||||||
service, filename, PAM_D_STYLE);
|
|
||||||
FREE(filename);
|
FREE(filename);
|
||||||
} else {
|
} else {
|
||||||
r = openpam_read_policy_file(policy,
|
r = openpam_read_chain(chain, service, facility,
|
||||||
service, *path, PAM_CONF_STYLE);
|
*path, pam_conf_style);
|
||||||
}
|
}
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
*
|
*
|
||||||
|
@ -260,34 +290,20 @@ int
|
||||||
openpam_configure(pam_handle_t *pamh,
|
openpam_configure(pam_handle_t *pamh,
|
||||||
const char *service)
|
const char *service)
|
||||||
{
|
{
|
||||||
pam_chain_t *other[PAM_NUM_CHAINS] = { 0 };
|
int i, ret;
|
||||||
int i, n, r;
|
|
||||||
|
|
||||||
/* try own configuration first */
|
for (i = 0; i < PAM_NUM_CHAINS; ++i) {
|
||||||
r = openpam_load_policy(pamh->chains, service);
|
ret = openpam_load_chain(&pamh->chains[i],
|
||||||
if (r < 0)
|
service, _pam_chain_name[i]);
|
||||||
return (-r);
|
if (ret == 0)
|
||||||
for (i = n = 0; i < PAM_NUM_CHAINS; ++i) {
|
ret = openpam_load_chain(&pamh->chains[i],
|
||||||
if (pamh->chains[i] != NULL)
|
PAM_OTHER, _pam_chain_name[i]);
|
||||||
++n;
|
if (ret < 0) {
|
||||||
}
|
openpam_clear_chains(pamh->chains);
|
||||||
if (n == PAM_NUM_CHAINS)
|
return (PAM_SYSTEM_ERR);
|
||||||
return (PAM_SUCCESS);
|
|
||||||
|
|
||||||
/* fill in the blanks with "other" */
|
|
||||||
openpam_load_policy(other, PAM_OTHER);
|
|
||||||
if (r < 0)
|
|
||||||
return (-r);
|
|
||||||
for (i = n = 0; i < PAM_NUM_CHAINS; ++i) {
|
|
||||||
if (pamh->chains[i] == NULL) {
|
|
||||||
pamh->chains[i] = other[i];
|
|
||||||
other[i] = NULL;
|
|
||||||
}
|
}
|
||||||
if (pamh->chains[i] != NULL)
|
|
||||||
++n;
|
|
||||||
}
|
}
|
||||||
openpam_clear_chains(other);
|
return (PAM_SUCCESS);
|
||||||
return (n > 0 ? PAM_SUCCESS : PAM_SYSTEM_ERR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -295,5 +311,4 @@ openpam_configure(pam_handle_t *pamh,
|
||||||
*
|
*
|
||||||
* Error codes:
|
* Error codes:
|
||||||
* PAM_SYSTEM_ERR
|
* PAM_SYSTEM_ERR
|
||||||
* PAM_BUF_ERR
|
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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#24 $
|
* $P4: //depot/projects/openpam/lib/openpam_impl.h#25 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _OPENPAM_IMPL_H_INCLUDED
|
#ifndef _OPENPAM_IMPL_H_INCLUDED
|
||||||
|
@ -112,17 +112,16 @@ struct pam_saved_cred {
|
||||||
|
|
||||||
#define PAM_OTHER "other"
|
#define PAM_OTHER "other"
|
||||||
|
|
||||||
int openpam_configure(pam_handle_t *, const char *);
|
int openpam_configure(pam_handle_t *, const char *);
|
||||||
int openpam_dispatch(pam_handle_t *, int, int);
|
int openpam_dispatch(pam_handle_t *, int, int);
|
||||||
int openpam_findenv(pam_handle_t *, const char *, size_t);
|
int openpam_findenv(pam_handle_t *, const char *, size_t);
|
||||||
int openpam_add_module(pam_chain_t **, int, int,
|
pam_module_t *openpam_load_module(const char *);
|
||||||
const char *, int, const char **);
|
void openpam_clear_chains(pam_chain_t **);
|
||||||
void openpam_clear_chains(pam_chain_t **);
|
|
||||||
|
|
||||||
#ifdef OPENPAM_STATIC_MODULES
|
#ifdef OPENPAM_STATIC_MODULES
|
||||||
pam_module_t *openpam_static(const char *);
|
pam_module_t *openpam_static(const char *);
|
||||||
#endif
|
#endif
|
||||||
pam_module_t *openpam_dynamic(const char *);
|
pam_module_t *openpam_dynamic(const char *);
|
||||||
|
|
||||||
#define FREE(p) do { free((p)); (p) = NULL; } while (0)
|
#define FREE(p) do { free((p)); (p) = NULL; } while (0)
|
||||||
|
|
||||||
|
|
|
@ -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#16 $
|
* $P4: //depot/projects/openpam/lib/openpam_load.c#17 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
@ -67,7 +67,7 @@ static pam_module_t *modules;
|
||||||
* found modules to speed up the process.
|
* found modules to speed up the process.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static pam_module_t *
|
pam_module_t *
|
||||||
openpam_load_module(const char *path)
|
openpam_load_module(const char *path)
|
||||||
{
|
{
|
||||||
pam_module_t *module;
|
pam_module_t *module;
|
||||||
|
@ -160,48 +160,6 @@ openpam_destroy_chain(pam_chain_t *chain)
|
||||||
FREE(chain);
|
FREE(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a module to a chain.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
openpam_add_module(pam_chain_t *policy[],
|
|
||||||
int chain,
|
|
||||||
int flag,
|
|
||||||
const char *modpath,
|
|
||||||
int optc,
|
|
||||||
const char *optv[])
|
|
||||||
{
|
|
||||||
pam_chain_t *new, *iterator;
|
|
||||||
|
|
||||||
if ((new = calloc(1, sizeof *new)) == NULL)
|
|
||||||
goto buf_err;
|
|
||||||
if ((new->optv = malloc(sizeof(char *) * (optc + 1))) == NULL)
|
|
||||||
goto buf_err;
|
|
||||||
while (optc--)
|
|
||||||
if ((new->optv[new->optc++] = strdup(*optv++)) == NULL)
|
|
||||||
goto buf_err;
|
|
||||||
new->optv[new->optc] = NULL;
|
|
||||||
new->flag = flag;
|
|
||||||
if ((new->module = openpam_load_module(modpath)) == NULL) {
|
|
||||||
openpam_destroy_chain(new);
|
|
||||||
return (PAM_OPEN_ERR);
|
|
||||||
}
|
|
||||||
if ((iterator = policy[chain]) != NULL) {
|
|
||||||
while (iterator->next != NULL)
|
|
||||||
iterator = iterator->next;
|
|
||||||
iterator->next = new;
|
|
||||||
} else {
|
|
||||||
policy[chain] = new;
|
|
||||||
}
|
|
||||||
return (PAM_SUCCESS);
|
|
||||||
|
|
||||||
buf_err:
|
|
||||||
openpam_log(PAM_LOG_ERROR, "%m");
|
|
||||||
openpam_destroy_chain(new);
|
|
||||||
return (PAM_BUF_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the chains and release the modules
|
* Clear the chains and release the modules
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2003 Networks Associates Technology, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software was developed for the FreeBSD Project by ThinkSec AS and
|
||||||
|
* Network Associates Laboratories, the Security Research Division of
|
||||||
|
* Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||||
|
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $P4: //depot/projects/openpam/lib/openpam_readline.c#1 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <security/pam_appl.h>
|
||||||
|
#include "openpam_impl.h"
|
||||||
|
|
||||||
|
#define MIN_LINE_LENGTH 128
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OpenPAM extension
|
||||||
|
*
|
||||||
|
* Read a line from a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
openpam_readline(FILE *f, size_t *lenp)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
size_t len, size;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if ((line = malloc(MIN_LINE_LENGTH)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
size = MIN_LINE_LENGTH;
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
#define line_putch(ch) do { \
|
||||||
|
if (len >= size - 1) { \
|
||||||
|
char *tmp = realloc(line, size *= 2); \
|
||||||
|
if (tmp == NULL) \
|
||||||
|
goto fail; \
|
||||||
|
line = tmp; \
|
||||||
|
} \
|
||||||
|
line[len++] = ch; \
|
||||||
|
line[len] = '\0'; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
ch = fgetc(f);
|
||||||
|
/* strip comment */
|
||||||
|
if (ch == '#') {
|
||||||
|
do {
|
||||||
|
ch = fgetc(f);
|
||||||
|
} while (ch != EOF && ch != '\n');
|
||||||
|
}
|
||||||
|
/* eof */
|
||||||
|
if (ch == EOF) {
|
||||||
|
/* remove trailing whitespace */
|
||||||
|
while (len > 0 && isspace(line[len - 1]))
|
||||||
|
--len;
|
||||||
|
line[len] = '\0';
|
||||||
|
if (len == 0)
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* eol */
|
||||||
|
if (ch == '\n') {
|
||||||
|
/* remove trailing whitespace */
|
||||||
|
while (len > 0 && isspace(line[len - 1]))
|
||||||
|
--len;
|
||||||
|
line[len] = '\0';
|
||||||
|
/* skip blank lines */
|
||||||
|
if (len == 0)
|
||||||
|
continue;
|
||||||
|
/* continuation */
|
||||||
|
if (line[len - 1] == '\\') {
|
||||||
|
line[--len] = '\0';
|
||||||
|
/* fall through to whitespace case */
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* whitespace */
|
||||||
|
if (isspace(ch)) {
|
||||||
|
/* ignore leading whitespace */
|
||||||
|
/* collapse linear whitespace */
|
||||||
|
if (len > 0 && line[len - 1] != ' ')
|
||||||
|
line_putch(' ');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* anything else */
|
||||||
|
line_putch(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lenp != NULL)
|
||||||
|
*lenp = len;
|
||||||
|
return (line);
|
||||||
|
fail:
|
||||||
|
FREE(line);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The =openpam_readline function reads a line from a file, and returns it
|
||||||
|
* in a NUL-terminated buffer allocated with =malloc.
|
||||||
|
*
|
||||||
|
* The =openpam_readline function performs a certain amount of processing
|
||||||
|
* on the data it reads.
|
||||||
|
* Comments (introduced by a hash sign) are stripped, as is leading and
|
||||||
|
* trailing whitespace.
|
||||||
|
* Any amount of linear whitespace is collapsed to a single space.
|
||||||
|
* Blank lines are ignored.
|
||||||
|
* If a line ends in a backslash, the backslash is stripped and the next
|
||||||
|
* line is appended.
|
||||||
|
*
|
||||||
|
* If =lenp is not =NULL, the length of the line (not including the
|
||||||
|
* terminating NUL character) is stored in the variable it points to.
|
||||||
|
*
|
||||||
|
* The caller is responsible for releasing the returned buffer by passing
|
||||||
|
* it to =free.
|
||||||
|
*/
|
Loading…
Reference in New Issue