aboutsummaryrefslogtreecommitdiff
path: root/Linux-PAM/libpam/pam_handlers.c
diff options
context:
space:
mode:
authorSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 12:47:05 -0800
committerSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 12:47:05 -0800
commit4c51da22e068907adb7857d50f5109a467c94d7c (patch)
treebecf5fbae5dfcbe8896355f59042dc8eaefa7f37 /Linux-PAM/libpam/pam_handlers.c
parentefd31890b5ed496a5a00c08a262da240e66a4ddc (diff)
parentab9e8ba11f464fc083fc65a0bc695d60ebc86f3e (diff)
downloadpam-4c51da22e068907adb7857d50f5109a467c94d7c.tar.gz
pam-4c51da22e068907adb7857d50f5109a467c94d7c.tar.bz2
pam-4c51da22e068907adb7857d50f5109a467c94d7c.zip
New upstream version 0.79
Diffstat (limited to 'Linux-PAM/libpam/pam_handlers.c')
-rw-r--r--Linux-PAM/libpam/pam_handlers.c161
1 files changed, 144 insertions, 17 deletions
diff --git a/Linux-PAM/libpam/pam_handlers.c b/Linux-PAM/libpam/pam_handlers.c
index d00f1842..ed03eda8 100644
--- a/Linux-PAM/libpam/pam_handlers.c
+++ b/Linux-PAM/libpam/pam_handlers.c
@@ -4,10 +4,12 @@
* created by Marc Ewing.
* Currently maintained by Andrew G. Morgan <morgan@kernel.org>
*
- * $Id: pam_handlers.c,v 1.1.1.2 2002/09/15 20:08:37 hartmans Exp $
+ * $Id: pam_handlers.c,v 1.12 2005/02/07 08:18:53 kukuk Exp $
*
*/
+#include "pam_private.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -24,8 +26,6 @@
# endif /* PAM_SHL */
#endif /* PAM_DYNAMIC */
-#include "pam_private.h"
-
/* If not required, define as nothing */
#ifndef SHLIB_SYM_PREFIX
# define SHLIB_SYM_PREFIX ""
@@ -34,6 +34,9 @@
#define BUF_SIZE 1024
#define MODULE_CHUNK 4
#define UNKNOWN_MODULE_PATH "<*unknown module path*>"
+#ifndef _PAM_ISA
+#define _PAM_ISA "."
+#endif
static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
@@ -46,13 +49,23 @@ static int _pam_add_handler(pam_handle_t *pamh
/* Values for module type */
+#define PAM_T_ANY 0
#define PAM_T_AUTH 1
#define PAM_T_SESS 2
#define PAM_T_ACCT 4
#define PAM_T_PASS 8
+static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
+ , const char *service /* specific file */
+ , int module_type /* specific type */
+#ifdef PAM_READ_BOTH_CONFS
+ , int not_other
+#endif /* PAM_READ_BOTH_CONFS */
+ );
+
static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
, const char *known_service /* specific file */
+ , int requested_module_type /* specific type */
#ifdef PAM_READ_BOTH_CONFS
, int not_other
#endif /* PAM_READ_BOTH_CONFS */
@@ -93,12 +106,21 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
/* accept "service name" or PAM_DEFAULT_SERVICE modules */
if (!_pam_strCMP(this_service, pamh->service_name) || other) {
+ int pam_include = 0;
+
/* This is a service we are looking for */
D(("_pam_init_handlers: Found PAM config entry for: %s"
, this_service));
tok = _pam_StrTok(NULL, " \n\t", &nexttok);
- if (!_pam_strCMP("auth", tok)) {
+ if (tok == NULL) {
+ /* module type does not exist */
+ D(("_pam_init_handlers: empty module type for %s", this_service));
+ _pam_system_log(LOG_ERR, "(%s) empty module type", this_service);
+ module_type = (requested_module_type != PAM_T_ANY) ?
+ requested_module_type : PAM_T_AUTH; /* most sensitive */
+ must_fail = 1; /* install as normal but fail when dispatched */
+ } else if (!_pam_strCMP("auth", tok)) {
module_type = PAM_T_AUTH;
} else if (!_pam_strCMP("session", tok)) {
module_type = PAM_T_SESS;
@@ -111,10 +133,17 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
D(("_pam_init_handlers: bad module type: %s", tok));
_pam_system_log(LOG_ERR, "(%s) illegal module type: %s",
this_service, tok);
- module_type = PAM_T_AUTH; /* most sensitive */
+ module_type = (requested_module_type != PAM_T_ANY) ?
+ requested_module_type : PAM_T_AUTH; /* most sensitive */
must_fail = 1; /* install as normal but fail when dispatched */
}
D(("Using %s config entry: %s", must_fail?"BAD ":"", tok));
+ if (requested_module_type != PAM_T_ANY &&
+ module_type != requested_module_type) {
+ D(("Skipping config entry: %s (requested=%d, found=%d)",
+ tok, requested_module_type, module_type));
+ continue;
+ }
/* reset the actions to .._UNDEF's -- this is so that
we can work out which entries are not yet set (for default). */
@@ -124,7 +153,14 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
actions[i++] = _PAM_ACTION_UNDEF);
}
tok = _pam_StrTok(NULL, " \n\t", &nexttok);
- if (!_pam_strCMP("required", tok)) {
+ if (tok == NULL) {
+ /* no module name given */
+ D(("_pam_init_handlers: no control flag supplied"));
+ _pam_system_log(LOG_ERR,
+ "(%s) no control flag supplied", this_service);
+ _pam_set_default_control(actions, _PAM_ACTION_BAD);
+ must_fail = 1;
+ } else if (!_pam_strCMP("required", tok)) {
D(("*PAM_F_REQUIRED*"));
actions[PAM_SUCCESS] = _PAM_ACTION_OK;
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
@@ -146,6 +182,9 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
actions[PAM_SUCCESS] = _PAM_ACTION_DONE;
actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_DONE;
_pam_set_default_control(actions, _PAM_ACTION_IGNORE);
+ } else if (!_pam_strCMP("include", tok)) {
+ D(("*PAM_F_INCLUDE*"));
+ pam_include = 1;
} else {
D(("will need to parse %s", tok));
_pam_parse_control(actions, tok);
@@ -154,7 +193,18 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
}
tok = _pam_StrTok(NULL, " \n\t", &nexttok);
- if (tok != NULL) {
+ if (pam_include) {
+ if (_pam_load_conf_file(pamh, tok, this_service, module_type
+#ifdef PAM_READ_BOTH_CONFS
+ , !other
+#endif /* PAM_READ_BOTH_CONFS */
+ ) == PAM_SUCCESS)
+ continue;
+ _pam_set_default_control(actions, _PAM_ACTION_BAD);
+ mod_path = NULL;
+ must_fail = 1;
+ nexttok = NULL;
+ } else if (tok != NULL) {
mod_path = tok;
D(("mod_path = %s",mod_path));
} else {
@@ -213,6 +263,58 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
return ( (x < 0) ? PAM_ABORT:PAM_SUCCESS );
}
+static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
+ , const char *service /* specific file */
+ , int module_type /* specific type */
+#ifdef PAM_READ_BOTH_CONFS
+ , int not_other
+#endif /* PAM_READ_BOTH_CONFS */
+ )
+{
+ FILE *f;
+ char *config_path = NULL;
+ int retval = PAM_ABORT;
+
+ D(("_pam_load_conf_file called"));
+
+ if (config_name == NULL) {
+ D(("no config file supplied"));
+ _pam_system_log(LOG_ERR, "(%s) no config file supplied", service);
+ return PAM_ABORT;
+ }
+
+ if (config_name[0] != '/') {
+ if (asprintf (&config_path, PAM_CONFIG_DF, config_name) < 0) {
+ _pam_system_log(LOG_CRIT, "asprintf failed");
+ return PAM_BUF_ERR;
+ }
+ config_name = config_path;
+ }
+
+ D(("opening %s", config_name));
+ f = fopen(config_name, "r");
+ if (f != NULL) {
+ retval = _pam_parse_conf_file(pamh, f, service, module_type
+#ifdef PAM_READ_BOTH_CONFS
+ , not_other
+#endif /* PAM_READ_BOTH_CONFS */
+ );
+ fclose(f);
+ if (retval != PAM_SUCCESS)
+ _pam_system_log(LOG_ERR,
+ "_pam_load_conf_file: error reading %s: %s",
+ config_name, pam_strerror(pamh, retval));
+ } else {
+ D(("unable to open %s", config_name));
+ _pam_system_log(LOG_ERR,
+ "_pam_load_conf_file: unable to open %s",
+ config_name);
+ }
+
+ _pam_drop(config_path);
+ return retval;
+}
+
/* Parse config file, allocate handler structures, dlopen() */
int _pam_init_handlers(pam_handle_t *pamh)
{
@@ -228,7 +330,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
}
D(("_pam_init_handlers: initializing"));
-
+
/* First clean the service structure */
_pam_free_handlers(pamh);
@@ -273,7 +375,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
*/
{
struct stat test_d;
-
+
/* Is there a PAM_CONFIG_D directory? */
if ( stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) {
char *filename;
@@ -293,7 +395,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
f = fopen(filename, "r");
if (f != NULL) {
/* would test magic here? */
- retval = _pam_parse_conf_file(pamh, f, pamh->service_name
+ retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
@@ -314,7 +416,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
D(("checking %s", PAM_CONFIG));
if ((f = fopen(PAM_CONFIG,"r")) != NULL) {
- retval = _pam_parse_conf_file(pamh, f, NULL, 1);
+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 1);
fclose(f);
} else
#endif /* PAM_READ_BOTH_CONFS */
@@ -335,6 +437,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
/* would test magic here? */
retval = _pam_parse_conf_file(pamh, f
, PAM_DEFAULT_SERVICE
+ , PAM_T_ANY
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
@@ -367,7 +470,7 @@ int _pam_init_handlers(pam_handle_t *pamh)
return PAM_ABORT;
}
- retval = _pam_parse_conf_file(pamh, f, NULL
+ retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
@@ -489,7 +592,7 @@ int _pam_add_handler(pam_handle_t *pamh
#ifdef PAM_SHL
const char *_sym, *_sym2;
#endif
- char *mod_full_path=NULL;
+ char *mod_full_path=NULL, *mod_full_isa_path=NULL, *isa=NULL;
servicefn func, func2;
int success;
@@ -554,6 +657,30 @@ int _pam_add_handler(pam_handle_t *pamh
# endif /* PAM_SHL */
D(("_pam_add_handler: dlopen'ed"));
if (mod->dl_handle == NULL) {
+ if (strstr(mod_path, "$ISA")) {
+ mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1);
+ if (mod_full_isa_path == NULL) {
+ D(("_pam_handler: couldn't get memory for mod_path"));
+ _pam_system_log(LOG_ERR, "no memory for module path");
+ success = PAM_ABORT;
+ } else {
+ strcpy(mod_full_isa_path, mod_path);
+ isa = strstr(mod_full_isa_path, "$ISA");
+ if (isa) {
+ memmove(isa + strlen(_PAM_ISA), isa + 4, strlen(isa + 4) + 1);
+ memmove(isa, _PAM_ISA, strlen(_PAM_ISA));
+ }
+ mod->dl_handle =
+# ifdef PAM_SHL
+ shl_load(mod_full_isa_path, BIND_IMMEDIATE, 0L);
+# else /* PAM_SHL */
+ dlopen(mod_full_isa_path, RTLD_NOW);
+# endif /* PAM_SHL */
+ _pam_drop(mod_full_isa_path);
+ }
+ }
+ }
+ if (mod->dl_handle == NULL) {
D(("_pam_add_handler: dlopen(%s) failed", mod_path));
_pam_system_log(LOG_ERR, "unable to dlopen(%s)", mod_path);
# ifndef PAM_SHL
@@ -600,7 +727,7 @@ int _pam_add_handler(pam_handle_t *pamh
/* indicate its name - later we will search for it by this */
if ((mod->name = _pam_strdup(mod_path)) == NULL) {
D(("_pam_handler: couldn't get memory for mod_path"));
- _pam_system_log(LOG_ERR, "no memory for module path", mod_path);
+ _pam_system_log(LOG_ERR, "no memory for module path");
success = PAM_ABORT;
}
@@ -696,7 +823,7 @@ int _pam_add_handler(pam_handle_t *pamh
}
/* now identify this module's functions - for non-faulty modules */
-
+
#ifdef PAM_DYNAMIC
if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
# ifdef PAM_SHL
@@ -823,7 +950,7 @@ int _pam_free_handlers(pam_handle_t *pamh)
}
/* Free all the handlers */
-
+
_pam_free_handlers_aux(&(pamh->handlers.conf.authenticate));
_pam_free_handlers_aux(&(pamh->handlers.conf.setcred));
_pam_free_handlers_aux(&(pamh->handlers.conf.acct_mgmt));
@@ -863,7 +990,7 @@ void _pam_start_handlers(pam_handle_t *pamh)
pamh->handlers.module = NULL;
/* initialize the .conf and .other entries */
-
+
pamh->handlers.conf.authenticate = NULL;
pamh->handlers.conf.setcred = NULL;
pamh->handlers.conf.acct_mgmt = NULL;