Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc: New rpc_unix transport based on Unix socket #38

Merged
merged 2 commits into from
Feb 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions common/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@

#include "config.h"

#include "buffer.h"
#include "debug.h"
#include "message.h"
#include "path.h"
#include "url.h"

#include <assert.h>
#include <errno.h>
Expand Down Expand Up @@ -325,3 +327,34 @@ p11_path_canon (char *name)
name[i] = '_';
}
}

char *
p11_path_encode (const char *path)
{
static const char *VALID =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/\\";
p11_buffer buf;
char *result;

return_val_if_fail (path != NULL, NULL);

if (!p11_buffer_init_null (&buf, strlen (path)))
return_val_if_reached (NULL);

p11_url_encode ((unsigned char *)path,
(unsigned char *)path + strlen (path),
VALID,
&buf);
return_val_if_fail (p11_buffer_ok (&buf), NULL);

result = p11_buffer_steal (&buf, NULL);
p11_buffer_uninit (&buf);

return result;
}

char *
p11_path_decode (const char *path)
{
return (char *) p11_url_decode (path, path + strlen (path), "", NULL);
}
4 changes: 4 additions & 0 deletions common/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,8 @@ bool p11_path_prefix (const char *string,

void p11_path_canon (char *name);

char * p11_path_encode (const char *path);

char * p11_path_decode (const char *path);

#endif /* P11_PATH_H__ */
22 changes: 22 additions & 0 deletions common/test-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,26 @@ test_canon (void)
free (test);
}

static void
test_encode (void)
{
char *test;

test = p11_path_encode ("2309haonutb;/AOE@#$O ");
assert_str_eq (test, "2309haonutb%3b/AOE%40%23%24O%20");
free (test);
}

static void
test_decode (void)
{
char *test;

test = p11_path_decode ("2309haonutb%3b/AOE%40%23%24O%20");
assert_str_eq (test, "2309haonutb;/AOE@#$O ");
free (test);
}

int
main (int argc,
char *argv[])
Expand All @@ -211,6 +231,8 @@ main (int argc,
p11_test (test_parent, "/path/parent");
p11_test (test_prefix, "/path/prefix");
p11_test (test_canon, "/path/canon");
p11_test (test_encode, "/path/encode");
p11_test (test_decode, "/path/decode");

return p11_test_run (argc, argv);
}
89 changes: 89 additions & 0 deletions p11-kit/rpc-transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "private.h"
#include "rpc.h"
#include "rpc-message.h"
#include "path.h"

#include <sys/types.h>

Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down
118 changes: 118 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,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)
{
Expand Down Expand Up @@ -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);
}