diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-08-24 14:41:49 +0200 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2017-02-16 16:56:40 +0100 |
commit | 89fa381ce5573a925b90da973cd8956937d79caa (patch) | |
tree | 83322f09eaba0267cb5a5490f6b3c8a420f48358 | |
parent | 3bab48000c4e61104b30ac379806cad3e1376ea6 (diff) |
rpc: New rpc_unix transport based on Unix socket
-rw-r--r-- | p11-kit/rpc-transport.c | 89 | ||||
-rw-r--r-- | p11-kit/test-transport.c | 118 |
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); } |