summaryrefslogtreecommitdiff
path: root/p11-kit/modules.c
diff options
context:
space:
mode:
Diffstat (limited to 'p11-kit/modules.c')
-rw-r--r--p11-kit/modules.c366
1 files changed, 61 insertions, 305 deletions
diff --git a/p11-kit/modules.c b/p11-kit/modules.c
index 268a3d5..999770d 100644
--- a/p11-kit/modules.c
+++ b/p11-kit/modules.c
@@ -51,7 +51,6 @@
#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>
-#include <pwd.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
@@ -130,71 +129,6 @@ static struct _Shared {
} gl = { NULL, NULL };
/* -----------------------------------------------------------------------------
- * UTILITIES
- */
-
-static void
-warning (const char* msg, ...)
-{
- char buffer[512];
- va_list va;
-
- va_start (va, msg);
-
- vsnprintf(buffer, sizeof (buffer) - 1, msg, va);
- buffer[sizeof (buffer) - 1] = 0;
- fprintf (stderr, "p11-kit: %s\n", buffer);
-
- va_end (va);
-}
-
-static void
-conf_error (const char *buffer)
-{
- /* called from conf.c */
- fprintf (stderr, "p11-kit: %s\n", buffer);
-}
-
-static char*
-strconcat (const char *first, ...)
-{
- size_t length = 0;
- const char *arg;
- char *result, *at;
- va_list va;
-
- va_start (va, first);
-
- for (arg = first; arg; arg = va_arg (va, const char*))
- length += strlen (arg);
-
- va_end (va);
-
- at = result = malloc (length + 1);
- if (!result)
- return NULL;
-
- va_start (va, first);
-
- for (arg = first; arg; arg = va_arg (va, const char*)) {
- length = strlen (arg);
- memcpy (at, arg, length);
- at += length;
- }
-
- va_end (va);
-
- *at = 0;
- return result;
-}
-
-static int
-strequal (const char *one, const char *two)
-{
- return strcmp (one, two) == 0;
-}
-
-/* -----------------------------------------------------------------------------
* P11-KIT FUNCTIONALITY
*/
@@ -322,7 +256,7 @@ dlopen_and_get_function_list (Module *mod, const char *path)
mod->dl_module = dlopen (path, RTLD_LOCAL | RTLD_NOW);
if (mod->dl_module == NULL) {
- warning ("couldn't load module: %s: %s", path, dlerror ());
+ _p11_warning ("couldn't load module: %s: %s", path, dlerror ());
return CKR_GENERAL_ERROR;
}
@@ -330,15 +264,15 @@ dlopen_and_get_function_list (Module *mod, const char *path)
gfl = dlsym (mod->dl_module, "C_GetFunctionList");
if (!gfl) {
- warning ("couldn't find C_GetFunctionList entry point in module: %s: %s",
- path, dlerror ());
+ _p11_warning ("couldn't find C_GetFunctionList entry point in module: %s: %s",
+ path, dlerror ());
return CKR_GENERAL_ERROR;
}
rv = gfl (&mod->funcs);
if (rv != CKR_OK) {
- warning ("call to C_GetFunctiontList failed in module: %s: %s",
- path, p11_kit_strerror (rv));
+ _p11_warning ("call to C_GetFunctiontList failed in module: %s: %s",
+ path, p11_kit_strerror (rv));
return rv;
}
@@ -380,38 +314,32 @@ load_module_from_file_unlocked (const char *path, Module **result)
}
static CK_RV
-load_module_from_config_unlocked (const char *configfile, const char *name)
+take_config_and_load_module_unlocked (char **name, hash_t **config)
{
Module *mod, *prev;
const char *path;
CK_RV rv;
- assert (configfile);
-
- mod = alloc_module_unlocked ();
- if (!mod)
- return CKR_HOST_MEMORY;
+ assert (name);
+ assert (*name);
+ assert (config);
+ assert (*config);
- mod->config = conf_parse_file (configfile, 0, conf_error);
- if (!mod->config) {
- free_module_unlocked (mod);
- if (errno == ENOMEM)
- return CKR_HOST_MEMORY;
- return CKR_GENERAL_ERROR;
+ path = hash_get (*config, "module");
+ if (path == NULL) {
+ debug ("no module path for module, skipping: %s", *name);
+ return CKR_OK;
}
- mod->name = strdup (name);
- if (!mod->name) {
- free_module_unlocked (mod);
+ mod = alloc_module_unlocked ();
+ if (!mod)
return CKR_HOST_MEMORY;
- }
- path = hash_get (mod->config, "module");
- if (path == NULL) {
- free_module_unlocked (mod);
- debug ("no module path specified in config, skipping: %s", configfile);
- return CKR_OK;
- }
+ /* Take ownership of thes evariables */
+ mod->config = *config;
+ *config = NULL;
+ mod->name = *name;
+ *name = NULL;
rv = dlopen_and_get_function_list (mod, path);
if (rv != CKR_OK) {
@@ -432,7 +360,7 @@ load_module_from_config_unlocked (const char *configfile, const char *name)
/* Refuse to load duplicate module */
if (prev) {
- warning ("duplicate configured module: %s: %s", mod->name, path);
+ _p11_warning ("duplicate configured module: %s: %s", mod->name, path);
free_module_unlocked (mod);
return CKR_GENERAL_ERROR;
}
@@ -453,233 +381,61 @@ load_module_from_config_unlocked (const char *configfile, const char *name)
}
static CK_RV
-load_modules_from_config_unlocked (const char *directory)
-{
- struct dirent *dp;
- struct stat st;
- CK_RV rv = CKR_OK;
- DIR *dir;
- int is_dir;
- char *path;
-
- debug ("loading module configs in: %s", directory);
-
- /* First we load all the modules */
- dir = opendir (directory);
- if (!dir) {
- if (errno == ENOENT || errno == ENOTDIR)
- return CKR_OK;
- warning ("couldn't list directory: %s", directory);
- return CKR_GENERAL_ERROR;
- }
-
- /* We're within a global mutex, so readdir is safe */
- while ((dp = readdir(dir)) != NULL) {
- path = strconcat (directory, "/", dp->d_name, NULL);
- if (!path) {
- rv = CKR_HOST_MEMORY;
- break;
- }
-
- is_dir = 0;
-#ifdef HAVE_STRUCT_DIRENT_D_TYPE
- if(dp->d_type != DT_UNKNOWN) {
- is_dir = (dp->d_type == DT_DIR);
- } else
-#endif
- {
- if (stat (path, &st) < 0) {
- warning ("couldn't stat path: %s", path);
- free (path);
- rv = CKR_GENERAL_ERROR;
- break;
- }
- is_dir = S_ISDIR (st.st_mode);
- }
-
- if (is_dir)
- rv = CKR_OK;
- else
- rv = load_module_from_config_unlocked (path, dp->d_name);
-
- free (path);
-
- if (rv != CKR_OK)
- break;
- }
-
- closedir (dir);
-
- return rv;
-}
-
-static char*
-expand_user_path (const char *path)
-{
- const char *env;
- struct passwd *pwd;
-
- if (path[0] == '~' && path[1] == '/') {
- env = getenv ("HOME");
- if (env && env[0]) {
- return strconcat (env, path + 1, NULL);
- } else {
- pwd = getpwuid (getuid ());
- if (!pwd)
- return NULL;
- return strconcat (pwd->pw_dir, path + 1, NULL);
- }
- }
-
- return strdup (path);
-}
-
-enum {
- USER_CONFIG_INVALID = 0,
- USER_CONFIG_NONE = 1,
- USER_CONFIG_MERGE,
- USER_CONFIG_OVERRIDE
-};
-
-static int
-user_config_mode (hash_t *config, int defmode)
-{
- const char *mode;
-
- /* Whether we should use or override from user directory */
- mode = hash_get (config, "user-config");
- if (mode == NULL) {
- return defmode;
- } else if (strequal (mode, "none")) {
- return USER_CONFIG_NONE;
- } else if (strequal (mode, "merge")) {
- return USER_CONFIG_MERGE;
- } else if (strequal (mode, "override")) {
- return USER_CONFIG_OVERRIDE;
- } else {
- warning ("invalid mode for 'user-config': %s", mode);
- return USER_CONFIG_INVALID;
- }
-}
-
-static CK_RV
-load_config_files_unlocked (int *user_mode)
+load_registered_modules_unlocked (void)
{
- hash_t *config = NULL;
- hash_t *uconfig = NULL;
- void *key = NULL;
- void *value = NULL;
- char *path;
- int mode;
- CK_RV rv = CKR_GENERAL_ERROR;
hash_iter_t hi;
+ hash_t *configs;
+ void *key;
+ char *name;
+ hash_t *config;
+ int mode;
+ CK_RV rv;
- /* Should only be called after everything has been unloaded */
- assert (!gl.config);
-
- /* Load the main configuration */
- config = conf_parse_file (P11_SYSTEM_CONF, CONF_IGNORE_MISSING, conf_error);
- if (!config) {
- rv = (errno == ENOMEM) ? CKR_HOST_MEMORY : CKR_GENERAL_ERROR;
- goto finished;
- }
-
- /* Whether we should use or override from user directory */
- mode = user_config_mode (config, USER_CONFIG_NONE);
- if (mode == USER_CONFIG_INVALID)
- goto finished;
-
- if (mode != USER_CONFIG_NONE) {
- path = expand_user_path (P11_USER_CONF);
- if (!path)
- goto finished;
-
- /* Load up the user configuration */
- uconfig = conf_parse_file (path, CONF_IGNORE_MISSING, conf_error);
- free (path);
+ if (gl.config)
+ return CKR_OK;
- if (!uconfig) {
- rv = (errno == ENOMEM) ? CKR_HOST_MEMORY : CKR_GENERAL_ERROR;
- goto finished;
- }
+ /* Load the global configuration files */
+ config = _p11_conf_load_globals (P11_SYSTEM_CONF, P11_USER_CONF, &mode);
+ if (config == NULL)
+ return (errno == ENOMEM) ? CKR_HOST_MEMORY : CKR_GENERAL_ERROR;
- /* Figure out what the user mode is */
- mode = user_config_mode (uconfig, mode);
- if (mode == USER_CONFIG_INVALID)
- goto finished;
-
- /* Merge everything into the system config */
- if (mode == USER_CONFIG_MERGE) {
- hash_iterate (uconfig, &hi);
- while (hash_next (&hi, &key, &value)) {
- key = strdup (key);
- if (key == NULL)
- goto finished;
- value = strdup (value);
- if (value == NULL)
- goto finished;
- if (!hash_set (config, key, value))
- goto finished;
- key = NULL;
- value = NULL;
- }
+ assert (mode != CONF_USER_INVALID);
- /* Override the system config */
- } else if (mode == USER_CONFIG_OVERRIDE) {
- hash_free (config);
- config = uconfig;
- uconfig = NULL;
- }
+ configs = _p11_conf_load_modules (mode, P11_SYSTEM_MODULES, P11_USER_MODULES);
+ if (configs == NULL) {
+ rv = (errno == ENOMEM) ? CKR_HOST_MEMORY : CKR_GENERAL_ERROR;
+ hash_free (config);
+ return rv;
}
+ assert (gl.config == NULL);
gl.config = config;
- config = NULL;
- rv = CKR_OK;
-
- if (user_mode)
- *user_mode = mode;
-
-finished:
- hash_free (config);
- hash_free (uconfig);
- free (key);
- free (value);
- return rv;
-}
-
-static CK_RV
-load_registered_modules_unlocked (void)
-{
- char *path;
- int mode;
- CK_RV rv;
- rv = load_config_files_unlocked (&mode);
- if (rv != CKR_OK)
- return rv;
+ /*
+ * Now go through each config and turn it into a module. As we iterate
+ * we steal the values of the config.
+ */
+ hash_iterate (configs, &hi);
+ while (hash_next (&hi, &key, NULL)) {
+ if (!hash_steal (configs, name, (void**)&name, (void**)config))
+ assert (0 && "not reached");
- assert (gl.config);
- assert (mode != USER_CONFIG_INVALID);
+ rv = take_config_and_load_module_unlocked (&name, &config);
- /* Load each module from the main list */
- if (mode != USER_CONFIG_OVERRIDE) {
- rv = load_modules_from_config_unlocked (P11_SYSTEM_MODULES);
- if (rv != CKR_OK);
- return rv;
- }
+ /*
+ * These variables will be cleared if ownership is transeferred
+ * by the above function call.
+ */
+ free (name);
+ hash_free (config);
- /* Load each module from the user list */
- if (mode != USER_CONFIG_NONE) {
- path = expand_user_path (P11_USER_MODULES);
- if (!path)
- rv = CKR_GENERAL_ERROR;
- else
- rv = load_modules_from_config_unlocked (path);
- free (path);
- if (rv != CKR_OK);
+ if (rv != CKR_OK) {
+ hash_free (configs);
return rv;
+ }
}
+ hash_free (configs);
return CKR_OK;
}