]> granicus.if.org Git - p11-kit/commitdiff
rpc: New p11_kit_remote_serve_tokens function
authorDaiki Ueno <dueno@redhat.com>
Fri, 10 Mar 2017 08:53:50 +0000 (09:53 +0100)
committerDaiki Ueno <ueno@gnu.org>
Thu, 25 May 2017 12:13:01 +0000 (14:13 +0200)
doc/manual/p11-kit-sections.txt
p11-kit/remote.c
p11-kit/remote.h
p11-kit/rpc-server.c
p11-kit/server.c

index c1c1df1e333ad0e2ab83f1eecf4c888d6b5000e5..cb0cb1c8f0fcbb4e6ee83147d77c9450f5bfd6f9 100644 (file)
@@ -141,6 +141,7 @@ P11KitIterKind
 P11KitIterBehavior
 p11_kit_remote_serve_module
 p11_kit_remote_serve_token
+p11_kit_remote_serve_tokens
 </SECTION>
 
 <SECTION>
index d524bbd2afa4ff1f5fc4786fdb5cf92bce8a9543..1642c7b86cb4ff10eb1337ba262dacbc43060f6d 100644 (file)
 #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;
+       }
 }
index 899f0706d4a1173da8bca3923b5672fac38f7e19..3c847366ee07294ef7de6010d84c3ff08c40a304 100644 (file)
@@ -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
index 47beed0d1ac2e576b7ca9b69fb3b6730a127c114..fcf837b50329bf434e8a9e74d73ab4f9ce20b98a 100644 (file)
@@ -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;
+}
index 1d9f469ac5c730c8b42303be6824ffa6204d6cc6..ce7900a3d5d2a8cb181cead1e1289cc09457806b 100644 (file)
@@ -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;