Clean up the dynamic module loading code, and add support for the
module path which was added in r695. git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@662 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
2b8f7a6154
commit
567ecaa2af
|
@ -39,9 +39,11 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -70,6 +72,7 @@ try_dlopen(const char *modfn)
|
|||
void *dlh;
|
||||
int fd;
|
||||
|
||||
openpam_log(PAM_LOG_LIBDEBUG, "dlopen(%s)", modfn);
|
||||
if ((fd = open(modfn, O_RDONLY)) < 0)
|
||||
return (NULL);
|
||||
if (OPENPAM_FEATURE(VERIFY_MODULE_FILE) &&
|
||||
|
@ -93,6 +96,7 @@ try_dlopen(const char *modfn)
|
|||
int check_module_file;
|
||||
void *dlh;
|
||||
|
||||
openpam_log(PAM_LOG_LIBDEBUG, "dlopen(%s)", modfn);
|
||||
openpam_get_feature(OPENPAM_VERIFY_MODULE_FILE,
|
||||
&check_module_file);
|
||||
if (check_module_file &&
|
||||
|
@ -108,50 +112,26 @@ try_dlopen(const char *modfn)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* OpenPAM internal
|
||||
*
|
||||
* Locate a dynamically linked module
|
||||
* Try to load a module from the suggested location.
|
||||
*/
|
||||
|
||||
pam_module_t *
|
||||
openpam_dynamic(const char *path)
|
||||
static pam_module_t *
|
||||
try_module(const char *modpath)
|
||||
{
|
||||
const pam_module_t *dlmodule;
|
||||
pam_module_t *module;
|
||||
const char *prefix;
|
||||
char *vpath;
|
||||
void *dlh;
|
||||
int i, serrno;
|
||||
|
||||
dlh = NULL;
|
||||
|
||||
/* Prepend the standard prefix if not an absolute pathname. */
|
||||
if (path[0] != '/')
|
||||
prefix = OPENPAM_MODULES_DIR;
|
||||
else
|
||||
prefix = "";
|
||||
|
||||
/* try versioned module first, then unversioned module */
|
||||
if (asprintf(&vpath, "%s%s.%d", prefix, path, LIB_MAJ) < 0)
|
||||
if ((module = calloc(1, sizeof *module)) == NULL ||
|
||||
(module->path = strdup(modpath)) == NULL ||
|
||||
(module->dlh = try_dlopen(modpath)) == NULL)
|
||||
goto err;
|
||||
if ((dlh = try_dlopen(vpath)) == NULL && errno == ENOENT) {
|
||||
*strrchr(vpath, '.') = '\0';
|
||||
dlh = try_dlopen(vpath);
|
||||
}
|
||||
if (dlh == NULL)
|
||||
goto err;
|
||||
if ((module = calloc(1, sizeof *module)) == NULL)
|
||||
goto buf_err;
|
||||
if ((module->path = strdup(path)) == NULL)
|
||||
goto buf_err;
|
||||
module->dlh = dlh;
|
||||
dlmodule = dlsym(dlh, "_pam_module");
|
||||
dlmodule = dlsym(module->dlh, "_pam_module");
|
||||
for (i = 0; i < PAM_NUM_PRIMITIVES; ++i) {
|
||||
if (dlmodule) {
|
||||
module->func[i] = dlmodule->func[i];
|
||||
} else {
|
||||
module->func[i] =
|
||||
(pam_func_t)dlfunc(dlh, pam_sm_func_name[i]);
|
||||
module->func[i] = (pam_func_t)dlfunc(module->dlh,
|
||||
pam_sm_func_name[i]);
|
||||
/*
|
||||
* This openpam_log() call is a major source of
|
||||
* log spam, and the cases that matter are caught
|
||||
|
@ -164,24 +144,84 @@ openpam_dynamic(const char *path)
|
|||
#if 0
|
||||
if (module->func[i] == NULL)
|
||||
openpam_log(PAM_LOG_LIBDEBUG, "%s: %s(): %s",
|
||||
path, pam_sm_func_name[i], dlerror());
|
||||
modpath, pam_sm_func_name[i], dlerror());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
FREE(vpath);
|
||||
return (module);
|
||||
buf_err:
|
||||
serrno = errno;
|
||||
if (dlh != NULL)
|
||||
dlclose(dlh);
|
||||
FREE(module);
|
||||
errno = serrno;
|
||||
err:
|
||||
serrno = errno;
|
||||
if (errno != 0)
|
||||
openpam_log(PAM_LOG_ERROR, "%s: %m", vpath);
|
||||
FREE(vpath);
|
||||
if (module != NULL) {
|
||||
if (module->dlh != NULL)
|
||||
dlclose(module->dlh);
|
||||
if (module->path != NULL)
|
||||
FREE(module->path);
|
||||
FREE(module);
|
||||
}
|
||||
errno = serrno;
|
||||
if (serrno != 0 && serrno != ENOENT)
|
||||
openpam_log(PAM_LOG_ERROR, "%s: %m", modpath);
|
||||
errno = serrno;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OpenPAM internal
|
||||
*
|
||||
* Locate a dynamically linked module
|
||||
*/
|
||||
|
||||
pam_module_t *
|
||||
openpam_dynamic(const char *modname)
|
||||
{
|
||||
pam_module_t *module;
|
||||
char modpath[PATH_MAX];
|
||||
const char **path;
|
||||
int dot, len;
|
||||
|
||||
/*
|
||||
* Simple case: module name contains path separator(s)
|
||||
*/
|
||||
if (strchr(modname, '/') != NULL) {
|
||||
/*
|
||||
* Absolute paths are not allowed if RESTRICT_MODULE_NAME
|
||||
* is in effect. Relative paths are never allowed.
|
||||
*/
|
||||
if (OPENPAM_FEATURE(RESTRICT_MODULE_NAME) ||
|
||||
modname[0] != '/') {
|
||||
openpam_log(PAM_LOG_ERROR,
|
||||
"invalid module name: %s", modname);
|
||||
return (NULL);
|
||||
}
|
||||
return (try_module(modname));
|
||||
}
|
||||
|
||||
/*
|
||||
* Complicated case: search for the module in the usual places.
|
||||
*/
|
||||
for (path = openpam_module_path; *path != NULL; ++path) {
|
||||
/*
|
||||
* Assemble the full path, including the version suffix. Take
|
||||
* note of where the suffix begins so we can cut it off later.
|
||||
*/
|
||||
len = snprintf(modpath, sizeof modpath, "%s/%s%n.%d",
|
||||
*path, modname, &dot, LIB_MAJ);
|
||||
if (len < 0 || (unsigned int)len >= sizeof modpath) {
|
||||
errno = ENOENT;
|
||||
continue;
|
||||
}
|
||||
/* try the versioned path */
|
||||
if ((module = try_module(modpath)) != NULL)
|
||||
return (module);
|
||||
if (errno == ENOENT) {
|
||||
/* no luck, try the unversioned path */
|
||||
modpath[dot] = '\0';
|
||||
if ((module = try_module(modpath)) != NULL)
|
||||
return (module);
|
||||
}
|
||||
}
|
||||
|
||||
/* :( */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue