summaryrefslogtreecommitdiff
path: root/p11-kit
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2012-04-01 21:53:04 +0200
committerStef Walter <stefw@gnome.org>2012-04-01 21:53:04 +0200
commita899d9be0cab72dcfe00f100527c52ea598fed70 (patch)
tree8b2e58d055a1cf8e5fced45195a3ffb598eef9c4 /p11-kit
parentaf8d28014f97ab0d9e4d00961e72aefd7adb470b (diff)
Add enable-in and disable-in options to module config
* These can be used to load certain modules in certain programs, or prevent loading in others. * Useful for a key manager like seahorse, so we can load extra modules (think NSS) that other modules shouldn't load.
Diffstat (limited to 'p11-kit')
-rw-r--r--p11-kit/modules.c75
-rw-r--r--p11-kit/p11-kit.h2
-rw-r--r--p11-kit/private.h4
-rw-r--r--p11-kit/util.c115
4 files changed, 193 insertions, 3 deletions
diff --git a/p11-kit/modules.c b/p11-kit/modules.c
index 047a2ca..f059097 100644
--- a/p11-kit/modules.c
+++ b/p11-kit/modules.c
@@ -47,6 +47,7 @@
#include <sys/types.h>
#include <assert.h>
+#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <limits.h>
@@ -336,6 +337,61 @@ expand_module_path (const char *filename)
return path;
}
+static int
+is_list_delimiter (char ch)
+{
+ return ch == ',' || isspace (ch);
+}
+
+static int
+is_string_in_list (const char *list,
+ const char *string)
+{
+ const char *where;
+
+ where = strstr (list, string);
+ if (where == NULL)
+ return 0;
+
+ /* Has to be at beginning/end of string, and delimiter before/after */
+ if (where != list && !is_list_delimiter (*(where - 1)))
+ return 0;
+
+ where += strlen (string);
+ return (*where == '\0' || is_list_delimiter (*where));
+}
+
+static int
+is_module_enabled_unlocked (const char *name,
+ hashmap *config)
+{
+ const char *progname;
+ const char *enable_in;
+ const char *disable_in;
+ int enable;
+
+ enable_in = _p11_hash_get (config, "enable-in");
+ disable_in = _p11_hash_get (config, "disable-in");
+
+ /* Defaults to enabled if neither of these are set */
+ if (!enable_in && !disable_in)
+ return 1;
+
+ progname = _p11_get_progname_unlocked ();
+ if (enable_in && disable_in)
+ _p11_message ("module '%s' has both enable-in and disable-in options", name);
+ if (enable_in)
+ enable = (progname != NULL && is_string_in_list (enable_in, progname));
+ else if (disable_in)
+ enable = (progname == NULL || !is_string_in_list (disable_in, progname));
+
+ _p11_debug ("%s module '%s' running in '%s'",
+ enable ? "enabled" : "disabled",
+ name,
+ progname ? progname : "(null)");
+ return enable;
+}
+
static CK_RV
take_config_and_load_module_unlocked (char **name, hashmap **config)
{
@@ -349,6 +405,9 @@ take_config_and_load_module_unlocked (char **name, hashmap **config)
assert (config);
assert (*config);
+ if (!is_module_enabled_unlocked (*name, *config))
+ return CKR_OK;
+
module_filename = _p11_hash_get (*config, "module");
if (module_filename == NULL) {
_p11_debug ("no module path for module, skipping: %s", *name);
@@ -832,8 +891,22 @@ _p11_kit_registered_modules_unlocked (void)
if (result) {
_p11_hash_iterate (gl.modules, &iter);
while (_p11_hash_next (&iter, NULL, (void **)&mod)) {
- if (mod->ref_count && mod->name)
+
+ /*
+ * We don't include unreferenced modules. We don't include
+ * modules that have been initialized but aren't in the
+ * registry. These have a NULL name.
+ *
+ * In addition we check again that the module isn't disabled
+ * using enable-in or disable-in. This is because a caller
+ * can change the progname we recognize the process as after
+ * having initialized. This is a corner case, but want to make
+ * sure to cover it.
+ */
+ if (mod->ref_count && mod->name &&
+ is_module_enabled_unlocked (mod->name, mod->config)) {
result[i++] = mod->funcs;
+ }
}
}
diff --git a/p11-kit/p11-kit.h b/p11-kit/p11-kit.h
index cf84db6..77cf1b5 100644
--- a/p11-kit/p11-kit.h
+++ b/p11-kit/p11-kit.h
@@ -80,6 +80,8 @@ char* p11_kit_space_strdup (const unsigned char
#ifdef P11_KIT_FUTURE_UNSTABLE_API
+void p11_kit_set_progname (const char *progname);
+
void p11_kit_be_quiet (void);
const char* p11_kit_message (void);
diff --git a/p11-kit/private.h b/p11-kit/private.h
index d23c1e6..36acb7e 100644
--- a/p11-kit/private.h
+++ b/p11-kit/private.h
@@ -92,4 +92,8 @@ void _p11_kit_clear_message (void);
void _p11_kit_default_message (CK_RV rv);
+const char * _p11_get_progname_unlocked (void);
+
+void _p11_set_progname_unlocked (const char *progname);
+
#endif /* __P11_KIT_PRIVATE_H__ */
diff --git a/p11-kit/util.c b/p11-kit/util.c
index c04b636..fd7708a 100644
--- a/p11-kit/util.c
+++ b/p11-kit/util.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2011 Collabora Ltd
+ * Copyright (c) 2012 Stef Walter
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,7 +32,7 @@
*
*
* CONTRIBUTORS
- * Stef Walter <stef@memberwebs.com>
+ * Stef Walter <stef@thewalter.net>
*/
#include "config.h"
@@ -246,6 +247,14 @@ _p11_kit_default_message (CK_RV rv)
}
}
+static void
+uninit_common (void)
+{
+ _p11_debug ("uninitializing library");
+
+ _p11_set_progname_unlocked (NULL);
+}
+
#ifdef OS_UNIX
static pthread_key_t thread_local = 0;
@@ -277,10 +286,47 @@ _p11_library_init (void)
void
_p11_library_uninit (void)
{
+ uninit_common ();
+
pthread_key_delete (thread_local);
_p11_mutex_uninit (&_p11_mutex);
}
+#if defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) && !HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
+extern char *program_invocation_short_name;
+#endif
+
+#if defined (HAVE___PROGNAME) && !HAVE_DECL___PROGNAME
+extern char *__progname;
+#endif
+
+static char *
+get_default_progname (void)
+{
+ const char *name;
+
+#if defined (HAVE_GETPROGNAME)
+ name = getprogname();
+#elif defined (HAVE_GETEXECNAME)
+ const char *p;
+ name = getexecname();
+ p = strrchr (name ? name : "", '/');
+ if (p != NULL)
+ name = p + 1;
+#elif defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME)
+ name = program_invocation_short_name;
+#elif defined (HAVE___PROGNAME)
+ name = __progname;
+#else
+ #error No way to retrieve program name from p11-kit library
+#endif
+
+ if (name == NULL)
+ return NULL;
+
+ return strdup (name);
+}
+
#endif /* OS_UNIX */
#ifdef OS_WIN32
@@ -331,7 +377,7 @@ _p11_library_uninit (void)
{
LPVOID data;
- _p11_debug ("uninitializing library");
+ uninit_common ();
if (thread_local != TLS_OUT_OF_INDEXES) {
data = TlsGetValue (thread_local);
@@ -376,4 +422,69 @@ DllMain (HINSTANCE instance,
return TRUE;
}
+extern char **__argv;
+
+static char *
+get_default_progname (void)
+{
+ const char *name;
+ const char *p;
+ char *progname;
+ size_t length;
+
+ name = __argv[0];
+ if (name == NULL)
+ return NULL;
+
+ p = strrchr (name, '\\');
+ if (p != NULL)
+ name = p + 1;
+
+ progname = strdup (name);
+ length = strlen (progname);
+ if (length > 4 && _stricmp(progname + (length - 4), ".exe"))
+ progname[length - 4] = '\0';
+
+ return progname;
+}
+
#endif /* OS_WIN32 */
+
+/* This is the progname that we think of this process as. */
+char *_p11_my_progname = NULL;
+
+/**
+ * p11_kit_set_progname:
+ * @progname: the program base name
+ *
+ * Set the program base name that is used by the <literal>enable-in</literal>
+ * and <literal>disable-in</literal> module configuration options.
+ *
+ * Normally this is automatically calculated from the program's argument list.
+ * You would usually call this before initializing p11-kit modules.
+ */
+void
+p11_kit_set_progname (const char *progname)
+{
+ _p11_library_init_once ();
+
+ _p11_lock ();
+ _p11_set_progname_unlocked (progname);
+ _p11_unlock ();
+}
+
+void
+_p11_set_progname_unlocked (const char *progname)
+{
+ /* We can be called with NULL, to cleanup memory usage */
+ free (_p11_my_progname);
+ _p11_my_progname = progname ? strdup (progname) : NULL;
+}
+
+const char *
+_p11_get_progname_unlocked (void)
+{
+ if (_p11_my_progname == NULL)
+ _p11_my_progname = get_default_progname ();
+ return _p11_my_progname;
+}