From 90668f1f234ea49e507231435d2df2035708aa4a Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 3 Nov 2015 08:11:39 +0100 Subject: [PATCH 1/4] common: use recursive pthread mutex for library lock This allows us to do nested locking within one thread avoiding a lockup when remoting the p11-kit-proxy.so module. The Windows NT mutex is aready recursive by default. --- common/compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/compat.c b/common/compat.c index 02e6408a0..627411e40 100644 --- a/common/compat.c +++ b/common/compat.c @@ -171,7 +171,7 @@ p11_mutex_init (p11_mutex_t *mutex) int ret; pthread_mutexattr_init (&attr); - pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_DEFAULT); + pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); ret = pthread_mutex_init (mutex, &attr); assert (ret == 0); pthread_mutexattr_destroy (&attr); From 7cb250335c754526ec8db98ba81e2769e567d26e Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 3 Nov 2015 08:55:56 +0100 Subject: [PATCH 2/4] p11-kit: relax sanity checking when remoting This allows us to remote the proxy module. No reason that wouldn't be allowed. --- p11-kit/modules.c | 18 +++++++++++------- p11-kit/p11-kit.h | 1 + p11-kit/remote.c | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/p11-kit/modules.c b/p11-kit/modules.c index fc456ce7b..1642e2429 100644 --- a/p11-kit/modules.c +++ b/p11-kit/modules.c @@ -292,6 +292,7 @@ alloc_module_unlocked (void) static CK_RV dlopen_and_get_function_list (Module *mod, const char *path, + int flags, CK_FUNCTION_LIST **funcs) { CK_C_GetFunctionList gfl; @@ -331,9 +332,11 @@ dlopen_and_get_function_list (Module *mod, return rv; } - if (p11_proxy_module_check (*funcs)) { - p11_message ("refusing to load the p11-kit-proxy.so module as a registered module"); - return CKR_FUNCTION_FAILED; + if (!(flags & P11_KIT_MODULE_REMOTING)) { + if (p11_proxy_module_check (*funcs)) { + p11_message ("refusing to load the p11-kit-proxy.so module as a registered module"); + return CKR_FUNCTION_FAILED; + } } p11_virtual_init (&mod->virt, &p11_virtual_base, *funcs, NULL); @@ -344,6 +347,7 @@ dlopen_and_get_function_list (Module *mod, static CK_RV load_module_from_file_inlock (const char *name, const char *path, + int flags, Module **result) { CK_FUNCTION_LIST *funcs; @@ -369,7 +373,7 @@ load_module_from_file_inlock (const char *name, mod->filename = strdup (path); - rv = dlopen_and_get_function_list (mod, path, &funcs); + rv = dlopen_and_get_function_list (mod, path, flags, &funcs); free (expand); if (rv != CKR_OK) { @@ -517,7 +521,7 @@ take_config_and_load_module_inlock (char **name, } else { - rv = load_module_from_file_inlock (*name, filename, &mod); + rv = load_module_from_file_inlock (*name, filename, 0, &mod); if (rv != CKR_OK) goto out; } @@ -2414,7 +2418,7 @@ p11_kit_module_load (const char *module_path, rv = init_globals_unlocked (); if (rv == CKR_OK) { - rv = load_module_from_file_inlock (NULL, module_path, &mod); + rv = load_module_from_file_inlock (NULL, module_path, flags, &mod); if (rv == CKR_OK) { /* WARNING: Reentrancy can occur here */ rv = prepare_module_inlock_reentrant (mod, flags, &module); @@ -2680,7 +2684,7 @@ p11_kit_load_initialize_module (const char *module_path, rv = init_globals_unlocked (); if (rv == CKR_OK) { - rv = load_module_from_file_inlock (NULL, module_path, &mod); + rv = load_module_from_file_inlock (NULL, module_path, 0, &mod); if (rv == CKR_OK) { /* WARNING: Reentrancy can occur here */ diff --git a/p11-kit/p11-kit.h b/p11-kit/p11-kit.h index a266c35b4..953d16b59 100644 --- a/p11-kit/p11-kit.h +++ b/p11-kit/p11-kit.h @@ -57,6 +57,7 @@ enum { P11_KIT_MODULE_UNMANAGED = 1 << 0, P11_KIT_MODULE_CRITICAL = 1 << 1, P11_KIT_MODULE_TRUSTED = 1 << 2, + P11_KIT_MODULE_REMOTING = 1 << 3, }; typedef void (* p11_kit_destroyer) (void *data); diff --git a/p11-kit/remote.c b/p11-kit/remote.c index 77172770e..fdb40fbf9 100644 --- a/p11-kit/remote.c +++ b/p11-kit/remote.c @@ -100,7 +100,7 @@ main (int argc, return 2; } - module = p11_kit_module_load (argv[0], 0); + module = p11_kit_module_load (argv[0], P11_KIT_MODULE_REMOTING); if (module == NULL) return 1; From e10e473ed937c5fa9e3ead67c3186ad5126e0a4b Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 27 Nov 2016 22:51:22 +0100 Subject: [PATCH 3/4] p11-kit: add a routine to allow setting up module remoting --- p11-kit/modules.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ p11-kit/p11-kit.h | 3 +++ 2 files changed, 62 insertions(+) diff --git a/p11-kit/modules.c b/p11-kit/modules.c index 1642e2429..2201e84a0 100644 --- a/p11-kit/modules.c +++ b/p11-kit/modules.c @@ -2442,6 +2442,65 @@ p11_kit_module_load (const char *module_path, } +/** + * p11_kit_module_remote: + * @remote: a remote module specifier + * @flags: flags to use when loading the module + * + * Setup a PKCS\#11 module for remoting and initialize it. + * + * A command (prefixed with "|") or a file descriptor (digits only) is + * accepted. The standard input and output of the command or the file + * descriptor are used for communication via the p11-kit remoting protocol. + * + * If @flags contains the %P11_KIT_MODULE_UNMANAGED flag, then the module + * will be not be set up in 'managed' mode and not be coordinated. This + * is not recommended for general usage. + * + * The module should be released with p11_kit_module_release(). + * + * If this function fails, then an error message will be available via the + * p11_kit_message() function. + * + * Returns: the remote module PKCS\#11 functions or %NULL on failure + */ +CK_FUNCTION_LIST * +p11_kit_module_remote (const char *remote, + int flags) +{ + CK_FUNCTION_LIST *module = NULL; + CK_RV rv; + Module *mod; + + return_val_if_fail (remote != NULL, NULL); + + p11_library_init_once (); + + /* WARNING: This function must be reentrant */ + p11_debug ("in"); + + p11_lock (); + + p11_message_clear (); + + rv = init_globals_unlocked (); + if (rv == CKR_OK) { + + rv = setup_module_for_remote_inlock ("remote", remote, &mod); + if (rv == CKR_OK) { + /* WARNING: Reentrancy can occur here */ + rv = prepare_module_inlock_reentrant (mod, flags, &module); + if (rv != CKR_OK) + module = NULL; + } + } + + p11_unlock (); + + p11_debug ("out: %s", module ? "success" : "fail"); + return module; +} + /** * p11_kit_finalize_module: * @module: loaded module to finalize. diff --git a/p11-kit/p11-kit.h b/p11-kit/p11-kit.h index 953d16b59..50f86059c 100644 --- a/p11-kit/p11-kit.h +++ b/p11-kit/p11-kit.h @@ -87,6 +87,9 @@ int p11_kit_module_get_flags (CK_FUNCTION_LIST *m CK_FUNCTION_LIST * p11_kit_module_load (const char *module_path, int flags); +CK_FUNCTION_LIST * p11_kit_module_remote (const char *remote, + int flags); + CK_RV p11_kit_module_initialize (CK_FUNCTION_LIST *module); CK_RV p11_kit_module_finalize (CK_FUNCTION_LIST *module); From 0a01c7fe4e55d728713ef75c058181463665cb98 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 27 Nov 2016 23:18:01 +0100 Subject: [PATCH 4/4] p11-kit-remote-proxy: add a PKCS#11 module for remoting This allows making a PKCS#11-enabled application that doesn't link to p11-kit to use a remote module easily. The remote is set up using P11_REMOTE environment variable, for a lack of a better mechanism to pass data to the PKCS#11 module. --- doc/manual/p11-kit-docs.xml | 1 + doc/manual/p11-kit-remote-proxy.xml | 17 +++++++++ p11-kit/Makefile.am | 14 +++++++- p11-kit/p11-kit-1.pc.in | 1 + p11-kit/remote-proxy.c | 54 +++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 doc/manual/p11-kit-remote-proxy.xml create mode 100644 p11-kit/remote-proxy.c diff --git a/doc/manual/p11-kit-docs.xml b/doc/manual/p11-kit-docs.xml index 77ff3184f..34284b9ff 100644 --- a/doc/manual/p11-kit-docs.xml +++ b/doc/manual/p11-kit-docs.xml @@ -14,6 +14,7 @@ + diff --git a/doc/manual/p11-kit-remote-proxy.xml b/doc/manual/p11-kit-remote-proxy.xml new file mode 100644 index 000000000..6e880a4b5 --- /dev/null +++ b/doc/manual/p11-kit-remote-proxy.xml @@ -0,0 +1,17 @@ + + + + Remote Proxy Module + + While the proxy module exposes the configured modules, the remoting + functionality of p11-kit often needs to be set up + dynamically (while the module for an actual token is selected by the remote + end). + + To allow use of the remoting capability for PKCS#11 consumers that don't + link to p11-kit, a separate proxy module is provided that can be used in place + of an ordinary PKCS#11 module. It proxies the PKCS#11 calls to a remote specified + by the P11_REMOTE environment variable, using the same syntax as + a remote module in the configuration file. + diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am index 5ee1b718c..5fce1834b 100644 --- a/p11-kit/Makefile.am +++ b/p11-kit/Makefile.am @@ -28,7 +28,8 @@ MODULE_SRCS = \ $(inc_HEADERS) lib_LTLIBRARIES += \ - libp11-kit.la + libp11-kit.la \ + p11-kit-remote-proxy.la libp11_kit_la_CFLAGS = \ -DP11_SYSTEM_CONFIG_FILE=\""$(p11_system_config_file)"\" \ @@ -54,6 +55,17 @@ libp11_kit_la_LIBADD = \ $(LTLIBINTL) \ $(NULL) +p11_kit_remote_proxy_la_SOURCES = \ + p11-kit/remote-proxy.c + +p11_kit_remote_proxy_la_LDFLAGS = \ + -module \ + -avoid-version \ + -export-symbols-regex '^C_GetFunctionList' + +p11_kit_remote_proxy_la_LIBADD = \ + libp11-kit.la + noinst_LTLIBRARIES += \ libp11-kit-testable.la diff --git a/p11-kit/p11-kit-1.pc.in b/p11-kit/p11-kit-1.pc.in index 392b8ea0e..3e609ed9a 100644 --- a/p11-kit/p11-kit-1.pc.in +++ b/p11-kit/p11-kit-1.pc.in @@ -10,6 +10,7 @@ p11_module_configs=@p11_package_config_modules@ p11_module_path=@p11_module_path@ p11_trust_paths=@with_trust_paths@ proxy_module=@libdir@/p11-kit-proxy.so +remote_proxy_module=@libdir@/p11-kit-remote-proxy.so # This is for compatibility. Other packages were using this to determine # the directory they should install their module configs to, so override diff --git a/p11-kit/remote-proxy.c b/p11-kit/remote-proxy.c new file mode 100644 index 000000000..838640af8 --- /dev/null +++ b/p11-kit/remote-proxy.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Author: Lubomir Rintel + */ + +#include "config.h" +#include "p11-kit.h" + +#include + +CK_RV +C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list) +{ + char *remote; + + remote = getenv ("P11_REMOTE"); + if (remote == NULL) + return CKR_ARGUMENTS_BAD; + + *list = p11_kit_module_remote (remote, 0); + if (*list == NULL) + return CKR_GENERAL_ERROR; + + return CKR_OK; +}