diff options
-rw-r--r-- | doc/manual/p11-kit-sections.txt | 1 | ||||
-rw-r--r-- | p11-kit/remote.c | 118 | ||||
-rw-r--r-- | p11-kit/remote.h | 14 | ||||
-rw-r--r-- | p11-kit/rpc-server.c | 142 | ||||
-rw-r--r-- | p11-kit/server.c | 74 |
5 files changed, 248 insertions, 101 deletions
diff --git a/doc/manual/p11-kit-sections.txt b/doc/manual/p11-kit-sections.txt index c1c1df1..cb0cb1c 100644 --- a/doc/manual/p11-kit-sections.txt +++ b/doc/manual/p11-kit-sections.txt @@ -141,6 +141,7 @@ P11KitIterKind P11KitIterBehavior p11_kit_remote_serve_module p11_kit_remote_serve_token +p11_kit_remote_serve_tokens </SECTION> <SECTION> diff --git a/p11-kit/remote.c b/p11-kit/remote.c index d524bbd..1642c7b 100644 --- a/p11-kit/remote.c +++ b/p11-kit/remote.c @@ -49,89 +49,30 @@ #include <string.h> #include <unistd.h> -static int -serve_module_from_uri (const char *uri_string) -{ - CK_FUNCTION_LIST **modules; - CK_FUNCTION_LIST *module; - P11KitIter *iter = NULL; - P11KitUri *uri; - CK_TOKEN_INFO *token; - int ret = 1; - CK_RV rv; - - modules = p11_kit_modules_load_and_initialize (0); - if (modules == NULL) - return 1; - - uri = p11_kit_uri_new (); - if (uri == NULL) - goto out; - ret = p11_kit_uri_parse (uri_string, P11_KIT_URI_FOR_TOKEN, uri); - if (ret != P11_KIT_URI_OK) { - p11_kit_uri_free (uri); - 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) - goto out; - - p11_kit_iter_begin (iter, modules); - rv = p11_kit_iter_next (iter); - if (rv != CKR_OK) - goto out; - - module = p11_kit_iter_get_module (iter); - token = p11_kit_iter_get_token (iter); - p11_kit_modules_finalize (modules); - - ret = p11_kit_remote_serve_token (module, token, 0, 1); - - out: - p11_kit_iter_free (iter); - p11_kit_modules_release (modules); - - return ret; -} - -static int -serve_module_from_file (const char *file) -{ - CK_FUNCTION_LIST *module; - int ret; - - module = p11_kit_module_load (file, 0); - if (module == NULL) - return 1; - - ret = p11_kit_remote_serve_module (module, 0, 1); - p11_kit_module_release (module); - - return ret; -} - int main (int argc, char *argv[]) { int opt; - int ret; + char *provider = NULL; enum { opt_verbose = 'v', opt_help = 'h', + opt_provider = 'p' }; struct option options[] = { { "verbose", no_argument, NULL, opt_verbose }, { "help", no_argument, NULL, opt_help }, + { "provider", required_argument, NULL, opt_provider }, { 0 }, }; p11_tool_desc usages[] = { - { 0, "usage: p11-kit remote <module-or-token>" }, + { 0, "usage: p11-kit remote <module>\n" + " p11-kit remote [-p <provider>] <token> ..." }, + { opt_provider, "specify the module to use" }, { 0 }, }; @@ -144,6 +85,9 @@ main (int argc, case '?': p11_tool_usage (usages, options); return 0; + case opt_provider: + provider = optarg; + break; default: assert_not_reached (); break; @@ -153,8 +97,8 @@ main (int argc, argc -= optind; argv += optind; - if (argc != 1) { - p11_message ("specify the module or token URI to remote"); + if (argc < 1) { + p11_message ("specify a module or tokens to remote"); return 2; } @@ -163,10 +107,40 @@ main (int argc, return 2; } - if (strncmp (argv[0], "pkcs11:", 7) == 0) - ret = serve_module_from_uri (argv[0]); - else - ret = serve_module_from_file (argv[0]); + if (strncmp (argv[0], "pkcs11:", 7) == 0) { + CK_FUNCTION_LIST *module = NULL; + int ret; + + if (provider) { + module = p11_kit_module_load (provider, 0); + if (module == NULL) + return 1; + } + + ret = p11_kit_remote_serve_tokens ((const char **)argv, argc, + module, + STDIN_FILENO, STDOUT_FILENO); + if (module) + p11_kit_module_release (module); - return ret; + return ret; + } else { + CK_FUNCTION_LIST *module; + int ret; + + if (argc != 1) { + p11_message ("only one module can be specified"); + return 2; + } + + module = p11_kit_module_load (argv[0], 0); + if (module == NULL) + return 1; + + ret = p11_kit_remote_serve_module (module, + STDIN_FILENO, STDOUT_FILENO); + p11_kit_module_release (module); + + return ret; + } } diff --git a/p11-kit/remote.h b/p11-kit/remote.h index 899f070..3c84736 100644 --- a/p11-kit/remote.h +++ b/p11-kit/remote.h @@ -47,11 +47,25 @@ int p11_kit_remote_serve_module (CK_FUNCTION_LIST *m int in_fd, int out_fd); +#ifndef P11_KIT_DISABLE_DEPRECATED + int p11_kit_remote_serve_token (CK_FUNCTION_LIST *module, CK_TOKEN_INFO *token, int in_fd, int out_fd); +#endif /* P11_KIT_DISABLE_DEPRECATED */ + +int p11_kit_remote_serve_tokens (const char **tokens, + size_t n_tokens, + CK_FUNCTION_LIST *module, + int in_fd, + int out_fd); + +int p11_kit_remote_serve (const char *module_or_token, + int in_fd, + int out_fd); + #endif #ifdef __cplusplus diff --git a/p11-kit/rpc-server.c b/p11-kit/rpc-server.c index 47beed0..fcf837b 100644 --- a/p11-kit/rpc-server.c +++ b/p11-kit/rpc-server.c @@ -38,6 +38,7 @@ #define P11_DEBUG_FLAG P11_DEBUG_RPC #include "debug.h" #include "filter.h" +#include "iter.h" #include "pkcs11.h" #include "library.h" #include "private.h" @@ -45,6 +46,7 @@ #include "remote.h" #include "rpc.h" #include "rpc-message.h" +#include "uri.h" #include <sys/types.h> #include <sys/param.h> @@ -1924,6 +1926,16 @@ p11_rpc_server_handle (CK_X_FUNCTION_LIST *self, return true; } +/** + * p11_kit_remote_serve_module: + * @module: a pointer to a loaded module + * @in_fd: input fd + * @out_fd: output fd + * + * Run a module on a given pair of input/output FDs. + * + * Returns: 0 if success, non-zero otherwise. + */ int p11_kit_remote_serve_module (CK_FUNCTION_LIST *module, int in_fd, @@ -2024,6 +2036,19 @@ out: return ret; } +/** + * p11_kit_remote_serve_token: + * @module: a pointer to a loaded module + * @token: a token info + * @in_fd: input fd + * @out_fd: output fd + * + * Run a token wrapped in a module on a given pair of input/output FDs. + * + * Returns: 0 if success, non-zero otherwise. + * + * Deprecated: use p11_kit_remote_serve_tokens() + */ int p11_kit_remote_serve_token (CK_FUNCTION_LIST *module, CK_TOKEN_INFO *token, @@ -2059,3 +2084,120 @@ p11_kit_remote_serve_token (CK_FUNCTION_LIST *module, return ret; } + +/* Find a module providing a token */ +static CK_FUNCTION_LIST * +find_module (const char *token) +{ + CK_FUNCTION_LIST **modules = NULL, *module = NULL; + P11KitUri *uri = NULL; + P11KitIter *iter = NULL; + CK_RV rv; + + modules = p11_kit_modules_load_and_initialize (0); + if (modules == NULL) + goto out; + + uri = p11_kit_uri_new (); + if (uri == NULL) + goto out; + + if (p11_kit_uri_parse (token, P11_KIT_URI_FOR_TOKEN, uri) != + P11_KIT_URI_OK) + goto out; + + iter = p11_kit_iter_new (uri, + P11_KIT_ITER_WITH_TOKENS | + P11_KIT_ITER_WITHOUT_OBJECTS); + p11_kit_uri_free (uri); + uri = NULL; + if (iter == NULL) + goto out; + + p11_kit_iter_begin (iter, modules); + rv = p11_kit_iter_next (iter); + if (rv != CKR_OK) + goto out; + + module = p11_kit_iter_get_module (iter); + + out: + p11_kit_iter_free (iter); + p11_kit_modules_release (modules); + + return 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 + * @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. + * + * Returns: 0 if success, non-zero otherwise. + */ +int +p11_kit_remote_serve_tokens (const char **tokens, + size_t n_tokens, + CK_FUNCTION_LIST *module, + int in_fd, + int out_fd) +{ + p11_virtual virt; + p11_virtual *filter = NULL; + CK_FUNCTION_LIST *filtered = NULL; + int ret = 1; + size_t i; + + return_val_if_fail (tokens != NULL, 2); + return_val_if_fail (n_tokens > 0, 2); + return_val_if_fail (in_fd >= 0, 2); + return_val_if_fail (out_fd >= 0, 2); + + if (!module) + module = find_module (tokens[0]); + + /* 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) + goto out; + + for (i = 0; i < n_tokens; i++) { + P11KitUri *uri; + CK_TOKEN_INFO *token; + + uri = p11_kit_uri_new (); + if (uri == NULL) + goto out; + + 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_uri_get_token_info (uri); + p11_filter_allow_token (filter, token); + p11_kit_uri_free (uri); + } + + filtered = p11_virtual_wrap (filter, (p11_destroyer)p11_virtual_uninit); + if (filtered == NULL) + goto out; + + ret = p11_kit_remote_serve_module (filtered, in_fd, out_fd); + + out: + if (filtered != NULL) + p11_virtual_unwrap (filtered); + if (filter != NULL) + p11_filter_release (filter); + + return ret; +} diff --git a/p11-kit/server.c b/p11-kit/server.c index 1d9f469..ce7900a 100644 --- a/p11-kit/server.c +++ b/p11-kit/server.c @@ -75,9 +75,11 @@ static unsigned children_avail = 0; static bool quiet = false; typedef struct { - char *module_or_token; - char *socket_name; + const char **tokens; + size_t n_tokens; + const char *provider; + const char *socket_name; uid_t uid; gid_t gid; @@ -243,17 +245,14 @@ server_free (Server *server) { if (server == NULL) return; - if (server->module_or_token) - free (server->module_or_token); - if (server->socket_name) - free (server->socket_name); if (server->socket >= 0) close (server->socket); free (server); } static Server * -server_new (const char *module_or_token, const char *socket_name) +server_new (const char **tokens, size_t n_tokens, const char *provider, + const char *socket_name) { Server *server; @@ -262,18 +261,9 @@ server_new (const char *module_or_token, const char *socket_name) if (server == NULL) return NULL; - server->module_or_token = strdup (module_or_token); - if (server->module_or_token == NULL) { - server_free (server); - return NULL; - } - - server->socket_name = strdup (socket_name); - if (server->socket_name == NULL) { - server_free (server); - return NULL; - } - + server->tokens = tokens; + server->n_tokens = n_tokens; + server->socket_name = socket_name; server->socket = -1; return server; @@ -291,7 +281,8 @@ server_loop (Server *server, struct sockaddr_un sa; fd_set rd_set; sigset_t emptyset, blockset; - char *args[] = { "p11-kit-remote", NULL, NULL }; + char **args; + size_t n_args, i; int max_fd; int errn; @@ -396,11 +387,32 @@ server_loop (Server *server, fdwalk (set_cloexec_on_fd, &max_fd); /* Execute 'p11-kit remote'; this shouldn't return */ - args[1] = (char *) server->module_or_token; - exec_external (2, args); + args = calloc (3 + server->n_tokens + 1, sizeof (char *)); + if (args == NULL) { + errn = errno; + p11_message_err (errn, "couldn't allocate memory for 'p11-kit remote' arguments"); + _exit (errn); + } + + n_args = 0; + args[n_args] = "p11-kit-remote"; + n_args++; + + if (server->provider) { + args[n_args] = "--provider"; + n_args++; + args[n_args] = (char *)server->provider; + n_args++; + } + + for (i = 0; i < server->n_tokens; i++, n_args++) + args[n_args] = (char *)server->tokens[i]; + + exec_external (n_args, args); + free (args); errn = errno; - p11_message_err (errn, "couldn't execute 'p11-kit remote' for module '%s'", server->module_or_token); + p11_message_err (errn, "couldn't execute 'p11-kit remote'"); _exit (errn); default: children_avail++; @@ -419,7 +431,6 @@ int main (int argc, char *argv[]) { - char *module_or_token; char *socket_base = NULL, *socket_name = NULL; uid_t uid = -1, run_as_uid = -1; gid_t gid = -1, run_as_gid = -1; @@ -429,6 +440,7 @@ main (int argc, bool foreground = false; struct timespec *timeout = NULL, ts; char *name = NULL; + char *provider = NULL; Server *server = NULL; int ret = 0; @@ -443,6 +455,7 @@ main (int argc, opt_foreground = 'f', opt_timeout = 't', opt_name = 'n', + opt_provider = 'p' }; struct option options[] = { @@ -456,11 +469,12 @@ main (int argc, { "run-as-group", required_argument, NULL, opt_run_as_group }, { "timeout", required_argument, NULL, opt_timeout }, { "name", required_argument, NULL, opt_name }, + { "provider", required_argument, NULL, opt_provider }, { 0 }, }; p11_tool_desc usages[] = { - { 0, "usage: p11-kit server <module-or-token>" }, + { 0, "usage: p11-kit server <token> ..." }, { opt_foreground, "run the server in foreground" }, { opt_user, "specify user who can connect to the socket" }, { opt_group, "specify group who can connect to the socket" }, @@ -468,6 +482,7 @@ main (int argc, { opt_run_as_group, "specify group who runs the server" }, { opt_timeout, "exit if no connection until the given timeout" }, { opt_name, "specify name of the socket (default: pkcs11-<pid>)" }, + { opt_provider, "specify the module to use" }, { 0 }, }; @@ -522,6 +537,9 @@ main (int argc, case opt_foreground: foreground = true; break; + case opt_provider: + provider = optarg; + break; case opt_help: case '?': p11_tool_usage (usages, options); @@ -535,13 +553,11 @@ main (int argc, argc -= optind; argv += optind; - if (argc != 1) { + if (argc < 1) { p11_tool_usage (usages, options); return 2; } - module_or_token = argv[0]; - if (run_as_gid != -1) { if (setgid (run_as_gid) == -1) { p11_message_err (errno, "cannot set gid to %u", (unsigned)run_as_gid); @@ -598,7 +614,7 @@ main (int argc, socket_name = strdup (name); } - server = server_new (module_or_token, socket_name); + server = server_new ((const char **)argv, argc, provider, socket_name); free (socket_name); if (server == NULL) { ret = 1; |