diff options
author | Daiki Ueno <dueno@redhat.com> | 2018-06-27 16:31:54 +0200 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2018-07-16 16:19:42 +0200 |
commit | b6d20ac16da7128089031248eed4afe08f6934d3 (patch) | |
tree | d62557a053824e613a70a9df8a7263d999e8fb33 | |
parent | 9d2ce267e6714c6a565a9ded3aa0001918d1ae1d (diff) |
rpc-server: p11_kit_remote_serve_tokens: Allow exporting all modules
This patch removes the restriction of p11_kit_remote_serve_tokens()
that were not capable of serving tokens across multiple modules.
-rw-r--r-- | p11-kit/Makefile.am | 5 | ||||
-rw-r--r-- | p11-kit/remote.h | 2 | ||||
-rw-r--r-- | p11-kit/rpc-server.c | 209 | ||||
-rw-r--r-- | p11-kit/test-server.c | 83 |
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); } |