Skip to content

Commit

Permalink
rpc: New rpc_unix transport based on Unix socket
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikos Mavrogiannopoulos authored and ueno committed Jan 25, 2017
1 parent ce2bf68 commit cc892f0
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 0 deletions.
85 changes: 85 additions & 0 deletions p11-kit/rpc-transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@
#include "private.h"
#include "rpc.h"
#include "rpc-message.h"
#include "path.h"

#include <sys/types.h>

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -820,6 +822,80 @@ rpc_exec_init (const char *remote,
return &rex->base;
}

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 *
Expand All @@ -842,6 +918,15 @@ p11_rpc_transport_new (p11_virtual *virt,
if (remote[0] == '|') {
rpc = rpc_exec_init (remote + 1, name);

} 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);

} else {
p11_message ("remote not supported: %s", remote);
return NULL;
Expand Down
107 changes: 107 additions & 0 deletions p11-kit/test-transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -54,6 +57,9 @@ struct {
char *directory;
char *user_config;
char *user_modules;
#ifdef OS_UNIX
pid_t pid;
#endif
} test;

static void
Expand Down Expand Up @@ -137,6 +143,102 @@ 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;
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 (&data, "remote: unix:path=%s/pkcs11\n", test.directory) < 0)
assert_not_reached ();
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

static void
test_basic_exec (void)
{
Expand Down Expand Up @@ -315,5 +417,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);
}

0 comments on commit cc892f0

Please sign in to comment.