summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-08-24 14:41:49 +0200
committerDaiki Ueno <ueno@gnu.org>2017-02-16 16:56:40 +0100
commit89fa381ce5573a925b90da973cd8956937d79caa (patch)
tree83322f09eaba0267cb5a5490f6b3c8a420f48358
parent3bab48000c4e61104b30ac379806cad3e1376ea6 (diff)
rpc: New rpc_unix transport based on Unix socket
-rw-r--r--p11-kit/rpc-transport.c89
-rw-r--r--p11-kit/test-transport.c118
2 files changed, 207 insertions, 0 deletions
diff --git a/p11-kit/rpc-transport.c b/p11-kit/rpc-transport.c
index 5902157..d8f0cda 100644
--- a/p11-kit/rpc-transport.c
+++ b/p11-kit/rpc-transport.c
@@ -44,6 +44,7 @@
#include "private.h"
#include "rpc.h"
#include "rpc-message.h"
+#include "path.h"
#include <sys/types.h>
@@ -1043,6 +1044,84 @@ rpc_exec_init (const char *remote,
return &rex->base;
}
+#ifdef OS_UNIX
+
+typedef struct {
+ p11_rpc_transport base;
+ struct sockaddr_un sa;
+} rpc_unix;
+
+static CK_RV
+rpc_unix_connect (p11_rpc_client_vtable *vtable,
+ void *init_reserved)
+{
+ rpc_unix *run = (rpc_unix *)vtable;
+ int fd;
+
+ fd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ p11_message_err (errno, "failed to create socket for remote");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (connect (fd, (struct sockaddr *)&run->sa, sizeof (run->sa)) < 0) {
+ p11_message_err (errno, "failed to connect to socket");
+ close (fd);
+ return CKR_DEVICE_REMOVED;
+ }
+
+ run->base.socket = rpc_socket_new (fd);
+ return_val_if_fail (run->base.socket != NULL, CKR_GENERAL_ERROR);
+
+ return CKR_OK;
+}
+
+static void
+rpc_unix_disconnect (p11_rpc_client_vtable *vtable,
+ void *fini_reserved)
+{
+ rpc_unix *run = (rpc_unix *)vtable;
+
+ if (run->base.socket)
+ rpc_socket_close (run->base.socket);
+
+ /* Do the common disconnect stuff */
+ rpc_transport_disconnect (vtable, fini_reserved);
+}
+
+static void
+rpc_unix_free (void *data)
+{
+ rpc_unix *run = data;
+ rpc_unix_disconnect (data, NULL);
+ rpc_transport_uninit (&run->base);
+ free (run);
+}
+
+static p11_rpc_transport *
+rpc_unix_init (const char *remote,
+ const char *name)
+{
+ rpc_unix *run;
+
+ run = calloc (1, sizeof (rpc_unix));
+ return_val_if_fail (run != NULL, NULL);
+
+ memset (&run->sa, 0, sizeof (run->sa));
+ run->sa.sun_family = AF_UNIX;
+ snprintf (run->sa.sun_path, sizeof (run->sa.sun_path), "%s", remote);
+
+ run->base.vtable.connect = rpc_unix_connect;
+ run->base.vtable.disconnect = rpc_unix_disconnect;
+ run->base.vtable.transport = rpc_transport_buffer;
+ rpc_transport_init (&run->base, name, rpc_unix_free);
+
+ p11_debug ("initialized rpc socket: %s", remote);
+ return &run->base;
+}
+
+#endif /* OS_UNIX */
+
p11_rpc_transport *
p11_rpc_transport_new (p11_virtual *virt,
const char *remote,
@@ -1058,6 +1137,16 @@ p11_rpc_transport_new (p11_virtual *virt,
if (remote[0] == '|') {
rpc = rpc_exec_init (remote + 1, name);
+#ifdef OS_UNIX
+ } else if (strncmp (remote, "unix:path=/", 11) == 0) {
+ /* Only absolute path is supported */
+ char *path;
+
+ path = p11_path_decode (remote + 10);
+ return_val_if_fail (path != NULL, NULL);
+ rpc = rpc_unix_init (path, name);
+ free (path);
+#endif /* OS_UNIX */
} else {
p11_message ("remote not supported: %s", remote);
return NULL;
diff --git a/p11-kit/test-transport.c b/p11-kit/test-transport.c
index 86e5e87..7e9079d 100644
--- a/p11-kit/test-transport.c
+++ b/p11-kit/test-transport.c
@@ -43,8 +43,11 @@
#include "p11-kit.h"
#include "rpc.h"
+#include <errno.h>
#include <sys/types.h>
#ifdef OS_UNIX
+#include <sys/socket.h>
+#include <sys/un.h>
#include <sys/wait.h>
#endif
#include <stdlib.h>
@@ -54,6 +57,9 @@ struct {
char *directory;
char *user_config;
char *user_modules;
+#ifdef OS_UNIX
+ pid_t pid;
+#endif
} test;
static void
@@ -137,6 +143,113 @@ teardown_mock_module (CK_FUNCTION_LIST *module)
teardown_remote (NULL);
}
+#ifdef OS_UNIX
+
+static void
+launch_server (void)
+{
+ int fd, nfd, rc;
+ socklen_t sa_len;
+ struct sockaddr_un sa;
+ fd_set fds;
+ char *argv[3];
+
+ memset (&sa, 0, sizeof (sa));
+ sa.sun_family = AF_UNIX;
+
+ snprintf (sa.sun_path, sizeof (sa.sun_path), "%s/pkcs11",
+ test.directory);
+
+ remove (sa.sun_path);
+ fd = socket (AF_UNIX, SOCK_STREAM, 0);
+ assert_num_cmp (fd, !=, -1);
+
+ rc = bind (fd, (struct sockaddr *)&sa, SUN_LEN (&sa));
+ assert_num_cmp (rc, !=, -1);
+
+ rc = listen (fd, 1024);
+ assert_num_cmp (rc, !=, -1);
+
+ FD_ZERO (&fds);
+ FD_SET (fd, &fds);
+ rc = select (fd + 1, &fds, NULL, NULL, NULL);
+ assert_num_cmp (rc, !=, -1);
+
+ assert (FD_ISSET (fd, &fds));
+
+ nfd = accept (fd, (struct sockaddr *)&sa, &sa_len);
+ assert_num_cmp (rc, !=, -1);
+ close (fd);
+
+ rc = dup2 (nfd, STDIN_FILENO);
+ assert_num_cmp (rc, !=, -1);
+
+ rc = dup2 (nfd, STDOUT_FILENO);
+ assert_num_cmp (rc, !=, -1);
+
+ argv[0] = "p11-kit-remote";
+ argv[1] = BUILDDIR "/.libs/mock-two.so";
+ argv[2] = NULL;
+
+ rc = execv (BUILDDIR "/p11-kit-remote", argv);
+ assert_num_cmp (rc, !=, -1);
+}
+
+static void
+setup_remote_unix (void *unused)
+{
+ char *data;
+ char *path;
+ pid_t pid;
+
+ test.directory = p11_test_directory ("p11-test-config");
+ test.user_modules = p11_path_build (test.directory, "modules", NULL);
+ if (mkdir (test.user_modules, 0700) < 0)
+ assert_not_reached ();
+
+ data = "user-config: only\n";
+ test.user_config = p11_path_build (test.directory, "pkcs11.conf", NULL);
+ p11_test_file_write (NULL, test.user_config, data, strlen (data));
+
+ pid = fork ();
+ switch (pid) {
+ case -1:
+ assert_not_reached ();
+ break;
+ case 0:
+ launch_server ();
+ exit (0);
+ break;
+ default:
+ test.pid = pid;
+ }
+
+ setenv ("P11_KIT_PRIVATEDIR", BUILDDIR, 1);
+
+ if (asprintf (&path, "%s/pkcs11", test.directory) < 0)
+ assert_not_reached ();
+ data = p11_path_encode (path);
+ assert_ptr_not_null (data);
+ free (path);
+ path = data;
+ if (asprintf (&data, "remote: unix:path=%s\n", path) < 0)
+ assert_not_reached ();
+ free (path);
+ p11_test_file_write (test.user_modules, "remote.module", data, strlen (data));
+ free (data);
+
+ p11_config_user_modules = test.user_modules;
+ p11_config_user_file = test.user_config;
+}
+
+static void
+teardown_remote_unix (void *unused)
+{
+ kill (test.pid, SIGKILL);
+}
+
+#endif /* OS_UNIX */
+
static void
test_basic_exec (void)
{
@@ -315,5 +428,10 @@ main (int argc,
test_mock_add_tests ("/transport");
+#ifdef OS_UNIX
+ p11_fixture (setup_remote_unix, teardown_remote_unix);
+ p11_test (test_basic_exec, "/transport/unix/basic");
+#endif
+
return p11_test_run (argc, argv);
}