aboutsummaryrefslogtreecommitdiff
path: root/libpam/pam_handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpam/pam_handlers.c')
-rw-r--r--libpam/pam_handlers.c226
1 files changed, 74 insertions, 152 deletions
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index 1f1917b5..7fd6ce84 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -9,6 +9,7 @@
#include "pam_private.h"
#include "pam_inline.h"
+#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -17,21 +18,20 @@
#include <fcntl.h>
#include <unistd.h>
-#define BUF_SIZE 1024
+#include "pam_line.h"
+
#define MODULE_CHUNK 4
#define UNKNOWN_MODULE "<*unknown module*>"
#ifndef _PAM_ISA
#define _PAM_ISA "."
#endif
-static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
-
static void _pam_free_handlers_aux(struct handler **hp);
static int _pam_add_handler(pam_handle_t *pamh
, int must_fail, int other, int stack_level, int type
, int *actions, const char *mod_path
- , int argc, char **argv, int argvlen);
+ , int argc, char **argv, size_t argvlen);
/* Values for module type */
@@ -44,6 +44,7 @@ static int _pam_add_handler(pam_handle_t *pamh
static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
, const char *service /* specific file */
, int module_type /* specific type */
+ , int include_level /* level of include */
, int stack_level /* level of substack */
#ifdef PAM_READ_BOTH_CONFS
, int not_other
@@ -53,18 +54,22 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
, const char *known_service /* specific file */
, int requested_module_type /* specific type */
+ , int include_level /* level of include */
, int stack_level /* level of substack */
#ifdef PAM_READ_BOTH_CONFS
, int not_other
#endif /* PAM_READ_BOTH_CONFS */
)
{
- char buf[BUF_SIZE];
+ struct pam_line_buffer buffer;
int x; /* read a line from the FILE *f ? */
+
+ _pam_line_buffer_init(&buffer);
/*
* read a line from the configuration (FILE *) f
*/
- while ((x = _pam_assemble_line(f, buf, BUF_SIZE)) > 0) {
+ while ((x = _pam_line_assemble(f, &buffer, ' ')) > 0) {
+ char *buf = buffer.assembled;
char *tok, *nexttok=NULL;
const char *this_service;
const char *mod_path;
@@ -74,15 +79,15 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
int handler_type = PAM_HT_MODULE; /* regular handler from a module */
int argc;
char **argv;
- int argvlen;
+ size_t argvlen;
- D(("_pam_init_handler: LINE: %s", buf));
+ D(("LINE: %s", buf));
if (known_service != NULL) {
nexttok = buf;
/* No service field: all lines are for the known service. */
this_service = known_service;
} else {
- this_service = tok = _pam_StrTok(buf, " \n\t", &nexttok);
+ this_service = tok = _pam_tokenize(buf, &nexttok);
}
#ifdef PAM_READ_BOTH_CONFS
@@ -98,13 +103,12 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
int substack = 0;
/* This is a service we are looking for */
- D(("_pam_init_handlers: Found PAM config entry for: %s"
- , this_service));
+ D(("Found PAM config entry for: %s", this_service));
- tok = _pam_StrTok(NULL, " \n\t", &nexttok);
+ tok = _pam_tokenize(NULL, &nexttok);
if (tok == NULL) {
/* module type does not exist */
- D(("_pam_init_handlers: empty module type for %s", this_service));
+ D(("empty module type for %s", this_service));
pam_syslog(pamh, LOG_ERR,
"(%s) empty module type", this_service);
module_type = (requested_module_type != PAM_T_ANY) ?
@@ -125,7 +129,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
module_type = PAM_T_PASS;
} else {
/* Illegal module type */
- D(("_pam_init_handlers: bad module type: %s", tok));
+ D(("bad module type: %s", tok));
pam_syslog(pamh, LOG_ERR, "(%s) illegal module type: %s",
this_service, tok);
module_type = (requested_module_type != PAM_T_ANY) ?
@@ -133,7 +137,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
}
}
- D(("Using %s config entry: %s", handler_type?"BAD ":"", tok));
+ D(("Using %sconfig entry: %s", handler_type?"BAD ":"", tok));
if (requested_module_type != PAM_T_ANY &&
module_type != requested_module_type) {
D(("Skipping config entry: %s (requested=%d, found=%d)",
@@ -148,10 +152,10 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
for (i=0; i<_PAM_RETURN_VALUES;
actions[i++] = _PAM_ACTION_UNDEF);
}
- tok = _pam_StrTok(NULL, " \n\t", &nexttok);
+ tok = _pam_tokenize(NULL, &nexttok);
if (tok == NULL) {
/* no module name given */
- D(("_pam_init_handlers: no control flag supplied"));
+ D(("no control flag supplied"));
pam_syslog(pamh, LOG_ERR,
"(%s) no control flag supplied", this_service);
_pam_set_default_control(actions, _PAM_ACTION_BAD);
@@ -193,7 +197,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
_pam_set_default_control(actions, _PAM_ACTION_BAD);
}
- tok = _pam_StrTok(NULL, " \n\t", &nexttok);
+ tok = _pam_tokenize(NULL, &nexttok);
if (pam_include) {
if (substack) {
res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
@@ -206,7 +210,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
}
}
if (_pam_load_conf_file(pamh, tok, this_service, module_type,
- stack_level + substack
+ include_level + 1, stack_level + substack
#ifdef PAM_READ_BOTH_CONFS
, !other
#endif /* PAM_READ_BOTH_CONFS */
@@ -221,7 +225,7 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
D(("mod_path = %s",mod_path));
} else {
/* no module name given */
- D(("_pam_init_handlers: no module name supplied"));
+ D(("no module name supplied"));
pam_syslog(pamh, LOG_ERR,
"(%s) no module name supplied", this_service);
mod_path = NULL;
@@ -233,10 +237,20 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
if (nexttok != NULL) {
D(("list: %s",nexttok));
argvlen = _pam_mkargv(nexttok, &argv, &argc);
- D(("argvlen = %d",argvlen));
+ D(("argvlen = %zu",argvlen));
+ if (argvlen == 0) {
+ /* memory allocation failed */
+ D(("failed to allocate argument vector"));
+ pam_syslog(pamh, LOG_ERR,
+ "(%s) argument vector allocation failed",
+ this_service);
+ mod_path = NULL;
+ handler_type = PAM_HT_MUST_FAIL;
+ }
} else { /* there are no arguments so fix by hand */
- D(("_pam_init_handlers: empty argument list"));
- argvlen = argc = 0;
+ D(("empty argument list"));
+ argvlen = 0;
+ argc = 0;
argv = NULL;
}
@@ -340,6 +354,7 @@ _pam_open_config_file(pam_handle_t *pamh
static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
, const char *service /* specific file */
, int module_type /* specific type */
+ , int include_level /* level of include */
, int stack_level /* level of substack */
#ifdef PAM_READ_BOTH_CONFS
, int not_other
@@ -350,11 +365,11 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
char *path = NULL;
int retval = PAM_ABORT;
- D(("_pam_load_conf_file called"));
+ D(("called."));
- if (stack_level >= PAM_SUBSTACK_MAX_LEVEL) {
- D(("maximum level of substacks reached"));
- pam_syslog(pamh, LOG_ERR, "maximum level of substacks reached");
+ if (include_level >= PAM_SUBSTACK_MAX_LEVEL) {
+ D(("maximum level of inclusions reached"));
+ pam_syslog(pamh, LOG_ERR, "maximum level of inclusions reached");
return PAM_ABORT;
}
@@ -365,7 +380,7 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
}
if (_pam_open_config_file(pamh, config_name, &path, &f) == PAM_SUCCESS) {
- retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level
+ retval = _pam_parse_conf_file(pamh, f, service, module_type, include_level, stack_level
#ifdef PAM_READ_BOTH_CONFS
, not_other
#endif /* PAM_READ_BOTH_CONFS */
@@ -392,15 +407,15 @@ int _pam_init_handlers(pam_handle_t *pamh)
FILE *f;
int retval;
- D(("_pam_init_handlers called"));
- IF_NO_PAMH("_pam_init_handlers",pamh,PAM_SYSTEM_ERR);
+ D(("called."));
+ IF_NO_PAMH(pamh,PAM_SYSTEM_ERR);
/* Return immediately if everything is already loaded */
if (pamh->handlers.handlers_loaded) {
return PAM_SUCCESS;
}
- D(("_pam_init_handlers: initializing"));
+ D(("initializing"));
/* First clean the service structure */
@@ -462,7 +477,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
if (_pam_open_config_file(pamh, pamh->service_name, &path, &f) == PAM_SUCCESS) {
retval = _pam_parse_conf_file(pamh, f, pamh->service_name,
- PAM_T_ANY, 0
+ PAM_T_ANY, 0, 0
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
@@ -485,7 +500,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
if (pamh->confdir == NULL
&& (f = fopen(PAM_CONFIG,"r")) != NULL) {
- retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 1);
+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 0, 1);
fclose(f);
} else
#endif /* PAM_READ_BOTH_CONFS */
@@ -502,7 +517,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
if (_pam_open_config_file(pamh, PAM_DEFAULT_SERVICE, &path, &f) == PAM_SUCCESS) {
/* would test magic here? */
retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE,
- PAM_T_ANY, 0
+ PAM_T_ANY, 0, 0
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
@@ -520,7 +535,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
_pam_drop(path);
fclose(f);
} else {
- D(("unable to open %s", PAM_DEFAULT_SERVICE));
+ D(("unable to open configuration for %s", PAM_DEFAULT_SERVICE));
pam_syslog(pamh, LOG_ERR,
"_pam_init_handlers: no default config %s",
PAM_DEFAULT_SERVICE);
@@ -536,7 +551,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
return PAM_ABORT;
}
- retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0
+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 0
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
@@ -555,94 +570,10 @@ int _pam_init_handlers(pam_handle_t *pamh)
pamh->handlers.handlers_loaded = 1;
- D(("_pam_init_handlers exiting"));
+ D(("exiting"));
return PAM_SUCCESS;
}
-/*
- * This is where we read a line of the PAM config file. The line may be
- * preceded by lines of comments and also extended with "\\\n"
- */
-
-static int _pam_assemble_line(FILE *f, char *buffer, int buf_len)
-{
- char *p = buffer;
- char *endp = buffer + buf_len;
- char *s, *os;
- int used = 0;
-
- /* loop broken with a 'break' when a non-'\\n' ended line is read */
-
- D(("called."));
- for (;;) {
- if (p >= endp) {
- /* Overflow */
- D(("_pam_assemble_line: overflow"));
- return -1;
- }
- if (fgets(p, endp - p, f) == NULL) {
- if (used) {
- /* Incomplete read */
- return -1;
- } else {
- /* EOF */
- return 0;
- }
- }
-
- /* skip leading spaces --- line may be blank */
-
- s = p + strspn(p, " \n\t");
- if (*s && (*s != '#')) {
- os = s;
-
- /*
- * we are only interested in characters before the first '#'
- * character
- */
-
- while (*s && *s != '#')
- ++s;
- if (*s == '#') {
- *s = '\0';
- used += strlen(os);
- break; /* the line has been read */
- }
-
- s = os;
-
- /*
- * Check for backslash by scanning back from the end of
- * the entered line, the '\n' has been included since
- * normally a line is terminated with this
- * character. fgets() should only return one though!
- */
-
- s += strlen(s);
- while (s > os && ((*--s == ' ') || (*s == '\t')
- || (*s == '\n')));
-
- /* check if it ends with a backslash */
- if (*s == '\\') {
- *s++ = ' '; /* replace backslash with ' ' */
- *s = '\0'; /* truncate the line here */
- used += strlen(os);
- p = s; /* there is more ... */
- } else {
- /* End of the line! */
- used += strlen(os);
- break; /* this is the complete line */
- }
-
- } else {
- /* Nothing in this line */
- /* Don't move p */
- }
- }
-
- return used;
-}
-
static char *
extract_modulename(const char *mod_path)
{
@@ -677,7 +608,7 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type)
int success;
struct loaded_module *mod;
- D(("_pam_load_module: loading module `%s'", mod_path));
+ D(("loading module `%s'", mod_path));
mod = pamh->handlers.module;
@@ -708,39 +639,30 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type)
/* Be pessimistic... */
success = PAM_ABORT;
- D(("_pam_load_module: _pam_dlopen(%s)", mod_path));
+ D(("_pam_dlopen(%s)", mod_path));
mod->dl_handle = _pam_dlopen(mod_path);
- D(("_pam_load_module: _pam_dlopen'ed"));
- D(("_pam_load_module: dlopen'ed"));
+ D(("_pam_dlopen'ed"));
+ D(("dlopen'ed"));
if (mod->dl_handle == NULL) {
const char *isa = strstr(mod_path, "$ISA");
size_t isa_len = strlen("$ISA");
if (isa != NULL) {
- size_t pam_isa_len = strlen(_PAM_ISA);
- char *mod_full_isa_path =
- malloc(strlen(mod_path) - isa_len + pam_isa_len + 1);
-
- if (mod_full_isa_path == NULL) {
- D(("_pam_load_module: couldn't get memory for mod_path"));
+ char *mod_full_isa_path = NULL;
+ if (strlen(mod_path) >= INT_MAX ||
+ asprintf(&mod_full_isa_path, "%.*s%s%s",
+ (int)(isa - mod_path), mod_path, _PAM_ISA, isa + isa_len) < 0) {
+ D(("couldn't get memory for mod_path"));
pam_syslog(pamh, LOG_CRIT, "no memory for module path");
success = PAM_ABORT;
} else {
- char *p = mod_full_isa_path;
-
- memcpy(p, mod_path, isa - mod_path);
- p += isa - mod_path;
- memcpy(p, _PAM_ISA, pam_isa_len);
- p += pam_isa_len;
- strcpy(p, isa + isa_len);
-
mod->dl_handle = _pam_dlopen(mod_full_isa_path);
_pam_drop(mod_full_isa_path);
}
}
}
if (mod->dl_handle == NULL) {
- D(("_pam_load_module: _pam_dlopen(%s) failed", mod_path));
+ D(("_pam_dlopen(%s) failed", mod_path));
if (handler_type != PAM_HT_SILENT_MODULE)
pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s): %s", mod_path,
_pam_dlerror());
@@ -764,7 +686,7 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type)
/* indicate its name - later we will search for it by this */
if ((mod->name = _pam_strdup(mod_path)) == NULL) {
- D(("_pam_load_module: couldn't get memory for mod_path"));
+ D(("couldn't get memory for mod_path"));
pam_syslog(pamh, LOG_CRIT, "no memory for module path");
success = PAM_ABORT;
}
@@ -776,10 +698,10 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type)
return success == PAM_SUCCESS ? mod : NULL;
}
-int _pam_add_handler(pam_handle_t *pamh
- , int handler_type, int other, int stack_level, int type
- , int *actions, const char *mod_path
- , int argc, char **argv, int argvlen)
+static int _pam_add_handler(pam_handle_t *pamh
+ , int handler_type, int other, int stack_level
+ , int type, int *actions, const char *mod_path
+ , int argc, char **argv, size_t argvlen)
{
struct loaded_module *mod = NULL;
struct handler **handler_p;
@@ -791,9 +713,9 @@ int _pam_add_handler(pam_handle_t *pamh
int mod_type = PAM_MT_FAULTY_MOD;
D(("called."));
- IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
+ IF_NO_PAMH(pamh,PAM_SYSTEM_ERR);
- D(("_pam_add_handler: adding type %d, handler_type %d, module `%s'",
+ D(("adding type %d, handler_type %d, module `%s'",
type, handler_type, mod_path));
if ((handler_type == PAM_HT_MODULE || handler_type == PAM_HT_SILENT_MODULE) &&
@@ -857,14 +779,14 @@ int _pam_add_handler(pam_handle_t *pamh
break;
default:
/* Illegal module type */
- D(("_pam_add_handler: illegal module type %d", type));
+ D(("illegal module type %d", type));
return PAM_ABORT;
}
/* are the modules reliable? */
if (mod_type != PAM_MT_DYNAMIC_MOD &&
mod_type != PAM_MT_FAULTY_MOD) {
- D(("_pam_add_handlers: illegal module library type; %d", mod_type));
+ D(("illegal module library type; %d", mod_type));
pam_syslog(pamh, LOG_ERR,
"internal error: module library type not known: %s;%d",
sym, mod_type);
@@ -938,7 +860,7 @@ int _pam_add_handler(pam_handle_t *pamh
return PAM_ABORT;
}
- D(("_pam_add_handler: returning successfully"));
+ D(("returning successfully"));
return PAM_SUCCESS;
}
@@ -949,14 +871,14 @@ int _pam_free_handlers(pam_handle_t *pamh)
struct loaded_module *mod;
D(("called."));
- IF_NO_PAMH("_pam_free_handlers",pamh,PAM_SYSTEM_ERR);
+ IF_NO_PAMH(pamh,PAM_SYSTEM_ERR);
mod = pamh->handlers.module;
/* Close all loaded modules */
while (pamh->handlers.modules_used) {
- D(("_pam_free_handlers: dlclose(%s)", mod->name));
+ D(("dlclose(%s)", mod->name));
free(mod->name);
if (mod->type == PAM_MT_DYNAMIC_MOD) {
_pam_dlclose(mod->dl_handle);