summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--p11-kit/Makefile.am5
-rw-r--r--p11-kit/remote.h2
-rw-r--r--p11-kit/rpc-server.c209
-rw-r--r--p11-kit/test-server.c83
4 files changed, 210 insertions, 89 deletions
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am
index 49d25dc..b6dffde 100644
--- a/p11-kit/Makefile.am
+++ b/p11-kit/Makefile.am
@@ -22,7 +22,7 @@ COMMON_SRCS = \
p11-kit/messages.c \
p11-kit/rpc-transport.c p11-kit/rpc.h \
p11-kit/rpc-message.c p11-kit/rpc-message.h \
- p11-kit/rpc-client.c p11-kit/rpc-server.c \
+ p11-kit/rpc-client.c \
p11-kit/uri.c \
p11-kit/virtual.c p11-kit/virtual.h \
p11-kit/virtual-fixed.h \
@@ -90,7 +90,8 @@ libp11_kit_la_LDFLAGS = \
-export-symbols-regex '^C_GetFunctionList|^p11_kit_'
libp11_kit_la_SOURCES = \
- p11-kit/proxy.c p11-kit/proxy.h p11-kit/proxy-init.c
+ p11-kit/proxy.c p11-kit/proxy.h p11-kit/proxy-init.c \
+ p11-kit/rpc-server.c \
$(NULL)
libp11_kit_la_LIBADD = \
diff --git a/p11-kit/remote.h b/p11-kit/remote.h
index a3d4fe2..c5a94a1 100644
--- a/p11-kit/remote.h
+++ b/p11-kit/remote.h
@@ -58,7 +58,7 @@ int p11_kit_remote_serve_token (CK_FUNCTION_LIST *module,
int p11_kit_remote_serve_tokens (const char **tokens,
size_t n_tokens,
- CK_FUNCTION_LIST *module,
+ CK_FUNCTION_LIST *provider,
int in_fd,
int out_fd);
diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c
index b222e8c..2db3524 100644
--- a/p11-kit/rpc-server.c
+++ b/p11-kit/rpc-server.c
@@ -44,6 +44,7 @@
#include "library.h"
#include "private.h"
#include "message.h"
+#include "proxy.h"
#include "remote.h"
#include "rpc.h"
#include "rpc-message.h"
@@ -2086,32 +2087,59 @@ p11_kit_remote_serve_token (CK_FUNCTION_LIST *module,
return ret;
}
+static void
+token_set_write_protected (CK_TOKEN_INFO *token, P11KitUri *uri)
+{
+ const char *write_protected =
+ p11_kit_uri_get_vendor_query (uri, "write-protected");
+ if (write_protected &&
+ _p11_conf_parse_boolean (write_protected, false))
+ token->flags |= CKF_WRITE_PROTECTED;
+ else
+ token->flags &= ~CKF_WRITE_PROTECTED;
+}
+
+static void
+module_unwrap (CK_FUNCTION_LIST *module)
+{
+ if (module)
+ p11_virtual_unwrap (module);
+}
+
/**
* p11_kit_remote_serve_tokens:
* @tokens: a list of token URIs
* @n_tokens: the length of @tokens
- * @module: (nullable): a PKCS\#11 module that provides the tokens
+ * @provider: (nullable): a PKCS\#11 module that provides the tokens
* @in_fd: input fd
* @out_fd: output fd
*
- * Expose tokens on a given pair of input/output FDs. All the tokens
- * must be provided by the same module.
+ * Expose tokens on a given pair of input/output FDs. If @provider is
+ * not NULL, all the tokens must be provided by the same module.
*
* Returns: 0 if success, non-zero otherwise.
*/
int
p11_kit_remote_serve_tokens (const char **tokens,
size_t n_tokens,
- CK_FUNCTION_LIST *module,
+ CK_FUNCTION_LIST *provider,
int in_fd,
int out_fd)
{
- p11_virtual virt;
+ p11_virtual *lower = NULL;
p11_virtual *filter = NULL;
- CK_FUNCTION_LIST **modules = NULL, *filtered = NULL;
+ CK_FUNCTION_LIST *proxy = NULL;
+ CK_FUNCTION_LIST **modules = NULL;
+ CK_FUNCTION_LIST *provider_modules[2] = { NULL, NULL };
+ CK_FUNCTION_LIST *module;
+ p11_dict *filters = NULL;
+ p11_dictiter filters_iter;
+ p11_array *filtered = NULL;
P11KitIter *iter;
- P11KitUri *uri;
+ P11KitUri **uris = NULL;
+ void *value;
int ret = 1;
+ int error = 0;
size_t i;
return_val_if_fail (tokens != NULL, 2);
@@ -2119,91 +2147,140 @@ p11_kit_remote_serve_tokens (const char **tokens,
return_val_if_fail (in_fd >= 0, 2);
return_val_if_fail (out_fd >= 0, 2);
- if (!module) {
- modules = p11_kit_modules_load_and_initialize (0);
- if (modules == NULL)
- goto out;
+ uris = calloc (n_tokens, sizeof (P11KitUri *));
+ if (uris == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
- /* Find a module that provides the first token */
- uri = p11_kit_uri_new ();
- if (uri == NULL)
+ for (i = 0; i < n_tokens; i++) {
+ uris[i] = p11_kit_uri_new ();
+ if (uris[i] == NULL) {
+ error = ENOMEM;
goto out;
-
- if (p11_kit_uri_parse (tokens[0], P11_KIT_URI_FOR_TOKEN, uri) !=
- P11_KIT_URI_OK)
+ }
+ if (p11_kit_uri_parse (tokens[i], P11_KIT_URI_FOR_TOKEN, uris[i]) !=
+ P11_KIT_URI_OK) {
+ error = EINVAL;
goto out;
+ }
+ }
- iter = p11_kit_iter_new (uri,
- P11_KIT_ITER_WITH_TOKENS |
- P11_KIT_ITER_WITHOUT_OBJECTS);
- p11_kit_uri_free (uri);
- if (iter == NULL)
+ if (provider) {
+ if (p11_kit_module_initialize (provider) != CKR_OK) {
+ error = EINVAL;
goto out;
-
- p11_kit_iter_begin (iter, modules);
- if (p11_kit_iter_next (iter) != CKR_OK) {
- p11_kit_iter_free (iter);
+ }
+ provider_modules[0] = provider;
+ modules = provider_modules;
+ } else {
+ modules = p11_kit_modules_load_and_initialize (0);
+ if (modules == NULL) {
+ error = EINVAL;
goto out;
}
+ }
- module = p11_kit_iter_get_module (iter);
- assert (module != NULL);
-
- p11_kit_iter_free (iter);
-
- /* Call C_Finalize on modules as C_Initialize on the
- * found module will be called later */
- p11_kit_modules_finalize (modules);
+ filters = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal,
+ NULL, p11_filter_release);
+ if (filters == NULL) {
+ error = ENOMEM;
+ goto out;
}
- /* Create a virtual module that provides only the specified tokens */
- p11_virtual_init (&virt, &p11_virtual_base, module, NULL);
- filter = p11_filter_subclass (&virt, NULL);
- if (filter == NULL)
+ iter = p11_kit_iter_new (NULL,
+ P11_KIT_ITER_WITH_TOKENS |
+ P11_KIT_ITER_WITHOUT_OBJECTS);
+ if (iter == NULL) {
+ error = ENOMEM;
goto out;
+ }
- for (i = 0; i < n_tokens; i++) {
+ p11_kit_iter_begin (iter, modules);
+ while (p11_kit_iter_next (iter) == CKR_OK) {
CK_TOKEN_INFO *token;
- const char *write_protected;
- uri = p11_kit_uri_new ();
- if (uri == NULL)
- goto out;
+ assert (p11_kit_iter_get_kind (iter) == P11_KIT_ITER_KIND_TOKEN);
- if (p11_kit_uri_parse (tokens[i], P11_KIT_URI_FOR_TOKEN, uri) !=
- P11_KIT_URI_OK) {
- p11_kit_uri_free (uri);
- goto out;
- }
+ token = p11_kit_iter_get_token (iter);
- token = p11_kit_uri_get_token_info (uri);
+ /* Check if the token is the one we want to export */
+ for (i = 0; i < n_tokens; i++)
+ if (p11_kit_uri_match_token_info (uris[i], token))
+ break;
+ if (i == n_tokens)
+ continue;
- /* Reflect "write-protected" setting in the URI */
- write_protected =
- p11_kit_uri_get_vendor_query (uri, "write-protected");
- if (write_protected &&
- _p11_conf_parse_boolean (write_protected, false))
- token->flags |= CKF_WRITE_PROTECTED;
- else
- token->flags &= ~CKF_WRITE_PROTECTED;
+ module = p11_kit_iter_get_module (iter);
+ assert (module != NULL);
+
+ /* Create a virtual module that provides only the
+ * specified tokens */
+ filter = p11_dict_get (filters, module);
+ if (filter == NULL) {
+ lower = calloc (1, sizeof (p11_virtual));
+ p11_virtual_init (lower, &p11_virtual_base, module, NULL);
+ filter = p11_filter_subclass (lower, NULL);
+ if (filter == NULL) {
+ error = EINVAL;
+ p11_message_err (error, "couldn't subclass filter");
+ goto out;
+ }
+ p11_dict_set (filters, module, filter);
+ }
+
+ for (i = 0; i < n_tokens; i++) {
+ if (p11_kit_uri_match_token_info (uris[i], token)) {
+ token_set_write_protected (token, uris[i]);
+ p11_filter_allow_token (filter, token);
+ }
+ }
+ }
+ p11_kit_iter_free (iter);
+
+ filtered = p11_array_new ((p11_destroyer)module_unwrap);
+ p11_dict_iterate (filters, &filters_iter);
+ while (p11_dict_next (&filters_iter, NULL, &value)) {
+ module = p11_virtual_wrap ((p11_virtual *)value,
+ (p11_destroyer)p11_virtual_uninit);
+ if (module == NULL) {
+ error = EINVAL;
+ p11_message_err (error, "couldn't wrap filter module");
+ goto out;
+ }
+ if (!p11_array_push (filtered, module)) {
+ error = ENOMEM;
+ goto out;
+ }
+ }
- p11_filter_allow_token (filter, token);
- p11_kit_uri_free (uri);
+ /* NULL terminate the array */
+ if (!p11_array_push (filtered, NULL)) {
+ error = ENOMEM;
+ goto out;
}
- filtered = p11_virtual_wrap (filter, (p11_destroyer)p11_virtual_uninit);
- if (filtered == NULL)
+ /* Need to finalize the modules that we initialized for iteration */
+ p11_kit_modules_finalize (modules);
+
+ if (p11_proxy_module_create (&proxy, (CK_FUNCTION_LIST **)filtered->elem)
+ != CKR_OK) {
+ error = EINVAL;
+ p11_message_err (error, "couldn't create a proxy module");
goto out;
+ }
- ret = p11_kit_remote_serve_module (filtered, in_fd, out_fd);
+ ret = p11_kit_remote_serve_module (proxy, in_fd, out_fd);
out:
if (filtered != NULL)
- p11_virtual_unwrap (filtered);
- if (filter != NULL)
- p11_filter_release (filter);
- if (modules != NULL)
+ p11_array_free (filtered);
+ if (filters != NULL)
+ p11_dict_free (filters);
+ if (modules != provider_modules)
p11_kit_modules_release (modules);
+ if (error != 0)
+ errno = error;
return ret;
}
diff --git a/p11-kit/test-server.c b/p11-kit/test-server.c
index 691f68a..d6ab5d5 100644
--- a/p11-kit/test-server.c
+++ b/p11-kit/test-server.c
@@ -35,6 +35,7 @@
#include "config.h"
#include "test.h"
+#include "array.h"
#include "dict.h"
#include "library.h"
#include "filter.h"
@@ -61,19 +62,17 @@ struct {
pid_t pid;
} test;
+struct fixture {
+ char *provider;
+ char *token;
+ int slots;
+};
+
static void
setup_server (void *arg)
{
- char *argv[] = {
- "p11-kit-server-testable",
- "-f",
- "--provider",
- BUILDDIR "/.libs/mock-one" SHLEXT,
- "-n",
- NULL,
- NULL,
- NULL
- };
+ struct fixture *fixture = arg;
+ p11_array *args;
char *address;
int fds[2];
struct pollfd pfd;
@@ -81,6 +80,18 @@ setup_server (void *arg)
const char *envvar;
char *path;
+ args = p11_array_new (NULL);
+ if (!p11_array_push (args, "p11-kit-server-testable"))
+ assert_not_reached ();
+ if (!p11_array_push (args, "-f"))
+ assert_not_reached ();
+ if (fixture->provider) {
+ if (!p11_array_push (args, "--provider"))
+ assert_not_reached ();
+ if (!p11_array_push (args, fixture->provider))
+ assert_not_reached ();
+ }
+
test.directory = p11_test_directory ("p11-test-server");
if (asprintf (&path, "%s/p11-kit", test.directory) < 0)
assert_not_reached ();
@@ -101,19 +112,30 @@ setup_server (void *arg)
if (envvar)
setenv ("LD_PRELOAD", envvar, 1);
- argv[5] = test.socket_path;
- argv[6] = (char *)arg;
+ if (!p11_array_push (args, "-n"))
+ assert_not_reached ();
+ if (!p11_array_push (args, test.socket_path))
+ assert_not_reached ();
+ if (!p11_array_push (args, fixture->token))
+ assert_not_reached ();
+ if (!p11_array_push (args, NULL))
+ assert_not_reached ();
test.pid = fork ();
+ assert (test.pid >= 0);
/* The child */
if (test.pid == 0) {
close (STDOUT_FILENO);
- dup2 (fds[0], STDOUT_FILENO);
- execv (BUILDDIR "/p11-kit-server-testable", argv);
+ if (dup2 (fds[0], STDOUT_FILENO) == -1)
+ assert_not_reached ();
+ if (execv (BUILDDIR "/p11-kit-server-testable", (char **)args->elem) == -1)
+ assert_not_reached ();
+ p11_array_free (args);
_exit (0);
}
+ p11_array_free (args);
memset (&pfd, 0, sizeof (struct pollfd));
pfd.fd = fds[1];
pfd.events = POLLIN | POLLHUP | POLLERR;
@@ -181,8 +203,9 @@ test_initialize_no_address (void *unused)
}
static void
-test_open_session (void *unused)
+test_open_session (void *arg)
{
+ struct fixture *fixture = arg;
CK_SESSION_HANDLE session;
CK_FUNCTION_LIST_PTR module;
CK_SLOT_ID slots[32];
@@ -198,7 +221,7 @@ test_open_session (void *unused)
count = 32;
rv = module->C_GetSlotList (CK_TRUE, slots, &count);
assert (rv == CKR_OK);
- assert_num_eq (1, count);
+ assert_num_eq (fixture->slots, count);
rv = module->C_OpenSession (slots[0], CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session);
assert (rv == CKR_OK);
@@ -245,14 +268,34 @@ int
main (int argc,
char *argv[])
{
+ struct fixture with_provider = {
+ BUILDDIR "/.libs/mock-one" SHLEXT,
+ "pkcs11:",
+ 1
+ };
+ struct fixture without_provider = {
+ NULL,
+ "pkcs11:",
+ 3
+ };
+ struct fixture write_protected = {
+ BUILDDIR "/.libs/mock-one" SHLEXT,
+ "pkcs11:?write-protected=yes",
+ 1
+ };
+
p11_library_init ();
mock_module_init ();
p11_fixture (setup_server, teardown_server);
- p11_testx (test_initialize, (void *)"pkcs11:", "/server/initialize");
- p11_testx (test_initialize_no_address, (void *)"pkcs11:", "/server/initialize-no-address");
- p11_testx (test_open_session, (void *)"pkcs11:", "/server/open-session");
- p11_testx (test_open_session_write_protected, (void *)"pkcs11:?write-protected=yes", "/server/open-session-write-protected");
+ p11_testx (test_initialize, (void *)&with_provider, "/server/initialize");
+ p11_testx (test_initialize_no_address, (void *)&with_provider, "/server/initialize-no-address");
+ p11_testx (test_open_session, (void *)&with_provider, "/server/open-session");
+ p11_testx (test_open_session_write_protected, (void *)&write_protected, "/server/open-session-write-protected");
+
+ p11_testx (test_initialize, (void *)&without_provider, "/server/all/initialize");
+ p11_testx (test_initialize_no_address, (void *)&without_provider, "/server/all/initialize-no-address");
+ p11_testx (test_open_session, (void *)&without_provider, "/server/all/open-session");
return p11_test_run (argc, argv);
}