aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2017-01-04 18:52:51 -0500
committerRob Austein <sra@hactrn.net>2017-01-04 18:52:51 -0500
commit17366b5296920cd37f716426fd7c653063dd5d78 (patch)
tree126c8a56afc9c42d36fb7db6ae6dce3dc8450822
parent0c9048b97575e56131cd89b3b0882cefa5de2cf2 (diff)
Convert "daemon" mode of C client code to use Python RPC MUX.
-rw-r--r--Makefile13
-rwxr-xr-x[-rw-r--r--]cryptech_rpcmuxd0
-rw-r--r--daemon.c330
-rw-r--r--hal_internal.h2
-rw-r--r--rpc_client_daemon.c41
5 files changed, 34 insertions, 352 deletions
diff --git a/Makefile b/Makefile
index c0a136b..1e7316a 100644
--- a/Makefile
+++ b/Makefile
@@ -144,16 +144,12 @@ endif
# the C preprocessor: we can use symbolic names so long as they're defined as macros
# in the C code, but we can't use things like C enum symbols.
-ifneq "${RPC_MODE}" "server"
- OBJ += rpc_serial.o
-endif
-
RPC_CLIENT_OBJ = rpc_client.o
ifeq "${RPC_TRANSPORT}" "loopback"
RPC_CLIENT_OBJ += rpc_client_loopback.o
else ifeq "${RPC_TRANSPORT}" "serial"
- RPC_CLIENT_OBJ += rpc_client_serial.o
+ RPC_CLIENT_OBJ += rpc_serial.o rpc_client_serial.o
else ifeq "${RPC_TRANSPORT}" "daemon"
RPC_CLIENT_OBJ += rpc_client_daemon.o
endif
@@ -225,13 +221,10 @@ server:
serial:
${MAKE} RPC_MODE=client-mixed RPC_TRANSPORT=serial
-daemon: mixed cryptech_rpcd
+daemon: mixed
.PHONY: client mixed server serial daemon
-cryptech_rpcd: daemon.o ${LIB}
- ${CC} ${CFLAGS} -o $@ $^ ${LDFLAGS}
-
${OBJ}: ${INC}
${LIB}: ${OBJ}
@@ -251,7 +244,7 @@ test: all
cd tests; ${MAKE} -k $@
clean:
- rm -f *.o ${LIB} cryptech_rpcd
+ rm -f *.o ${LIB}
cd tests; ${MAKE} $@
cd utils; ${MAKE} $@
diff --git a/cryptech_rpcmuxd b/cryptech_rpcmuxd
index d08d6df..d08d6df 100644..100755
--- a/cryptech_rpcmuxd
+++ b/cryptech_rpcmuxd
diff --git a/daemon.c b/daemon.c
deleted file mode 100644
index ff95353..0000000
--- a/daemon.c
+++ /dev/null
@@ -1,330 +0,0 @@
-#define DEBUG
-/*
- * daemon.c
- * --------
- * A daemon to arbitrate shared access to a serial connection to the HSM.
- *
- * Copyright (c) 2016, NORDUnet A/S All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <poll.h>
-#include <getopt.h> /* required with -std=c99 */
-#include <termios.h> /* for default speed */
-
-#include "hal_internal.h"
-#include "slip_internal.h"
-#include "xdr_internal.h"
-
-static char usage[] =
- "usage: %s [-n socketname] [-d ttydevice] [-s ttyspeed]\n";
-
-/*
- * Work around glibc "feature test" insanity. This isn't the correct
- * definition according to the POSIX, but it does what seems to be the
- * normal hack on Linux (where this is broken more often than not).
- */
-
-#ifndef SUN_LEN
-#define SUN_LEN(_sun_ptr_) (sizeof(*(_sun_ptr_)))
-#endif
-
-/* select() is hopelessly broken, and epoll() is Linux-specific, so we'll use
- * poll() until such a time as libevent or libev seems more appropriate.
- * Unfortunately, poll() doesn't come with any macros or functions to manage
- * the pollfd array, so we have to invent them.
- */
-
-static struct pollfd *pollfds = NULL;
-static nfds_t nfds = 0;
-static nfds_t npollfds = 0;
-
-static void poll_add(int fd)
-{
- /* add 4 entries at a time to avoid having to realloc too often */
-#define NNEW 4
-
- /* expand the array if necessary */
- if (nfds == npollfds) {
- npollfds = nfds + NNEW;
- pollfds = realloc(pollfds, npollfds * sizeof(struct pollfd));
- if (pollfds == NULL) {
- perror("realloc");
- exit(EXIT_FAILURE);
- }
- /* zero the new entries for hygiene */
- memset(&pollfds[nfds], 0, NNEW * sizeof(struct pollfd));
- }
-
- /* populate the new entry */
- pollfds[nfds].fd = fd;
- pollfds[nfds].events = POLLIN;
- ++nfds;
-}
-
-static void poll_remove(int fd)
-{
- nfds_t i;
-
- /* search the pollfd array */
- for (i = 0; i < nfds; ++i) {
- if (pollfds[i].fd == fd) {
- /* shift remainder of the array left by one */
- memmove(&pollfds[i], &pollfds[i + 1], (nfds - i - 1) * sizeof(struct pollfd));
- /* zero the last entry for hygiene */
- memset(&pollfds[nfds - 1], 0, sizeof(struct pollfd));
- --nfds;
- return;
- }
- }
- /* if it's not found, return without an error */
-}
-
-typedef struct {
- size_t len;
- uint8_t buf[HAL_RPC_MAX_PKT_SIZE];
-} rpc_buffer_t;
-static rpc_buffer_t ibuf, obuf;
-
-const char *socket_name = HAL_CLIENT_DAEMON_DEFAULT_SOCKET_NAME;
-
-/* Set up an atexit handler to remove the filesystem entry for the unix domain
- * socket. This will trigger on error exits, but not on the "normal" SIGKILL.
- */
-void atexit_cleanup(void)
-{
- unlink(socket_name);
-}
-
-#ifdef DEBUG
-static void hexdump(uint8_t *buf, uint32_t len)
-{
- for (uint32_t i = 0; i < len; ++i)
- printf("%02x%c", buf[i], ((i & 0x07) == 0x07) ? '\n' : ' ');
- if ((len & 0x07) != 0)
- printf("\n");
-}
-#endif
-
-int main(int argc, char *argv[])
-{
- struct sockaddr_un name;
- int ret;
- int lsock;
- int dsock;
- int opt;
- const char *device = getenv(HAL_CLIENT_SERIAL_DEVICE_ENVVAR);
- const char *speed_ = getenv(HAL_CLIENT_SERIAL_SPEED_ENVVAR);
- uint32_t speed = HAL_CLIENT_SERIAL_DEFAULT_SPEED;
-
- if (device == NULL)
- device = HAL_CLIENT_SERIAL_DEFAULT_DEVICE;
-
- if (speed_ != NULL)
- speed = (uint32_t) strtoul(speed_, NULL, 10);
-
- while ((opt = getopt(argc, argv, "hn:d:s:")) != -1) {
- switch (opt) {
- case 'h':
- printf(usage, argv[0]);
- exit(EXIT_SUCCESS);
- case 'n':
- socket_name = optarg;
- break;
- case 'd':
- device = optarg;
- break;
- case 's':
- speed = (uint32_t) strtoul(optarg, NULL, 10);
- switch (speed) {
- case 115200:
- case 921600:
- break;
- default:
- printf("invalid speed value %s\n", optarg);
- exit(EXIT_FAILURE);
- }
- break;
- default:
- printf(usage, argv[0]);
- exit(EXIT_FAILURE);
- }
- }
-
- if (atexit(atexit_cleanup) != 0) {
- perror("atexit");
- exit(EXIT_FAILURE);
- }
-
- if (hal_serial_init(device, speed) != HAL_OK)
- exit(EXIT_FAILURE);
-
- int serial_fd = hal_serial_get_fd();
- poll_add(serial_fd);
-
- /* Remove the filesystem entry for the unix domain socket. The usual way
- * to stop a daemon is SIGKILL, which we can't catch, so the file remains,
- * and will prevent us from binding the socket.
- *
- * XXX We should also scan the process table, to make sure the daemon
- * isn't already running.
- */
- unlink(socket_name);
-
- /* Create the listening socket.
- */
- lsock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
- if (lsock == -1) {
- perror("socket");
- exit(EXIT_FAILURE);
- }
- poll_add(lsock);
-
- /* For portability, clear the whole address structure, since some
- * implementations have additional (nonstandard) fields in the structure.
- */
- memset(&name, 0, sizeof(struct sockaddr_un));
-
- /* Bind the listening socket. On some platforms, we have to pass the "real"
- * (number of bytes in use) length of the sockaddr_un to get the name bound
- * correctly, so use the SUN_LEN() macro to calculate that.
- */
- name.sun_family = AF_UNIX;
- strncpy(name.sun_path, socket_name, sizeof(name.sun_path) - 1);
- ret = bind(lsock, (const struct sockaddr *) &name, SUN_LEN(&name));
- if (ret == -1) {
- perror("bind");
- exit(EXIT_FAILURE);
- }
-
- /* Prepare to accept connections.
- */
- ret = listen(lsock, 20);
- if (ret == -1) {
- perror("listen");
- exit(EXIT_FAILURE);
- }
-
- /* The main loop.
- */
- for (;;) {
-
- /* Blocking poll on all descriptors of interest.
- */
- ret = poll(pollfds, nfds, -1);
- if (ret == -1) {
- perror("poll");
- exit(EXIT_FAILURE);
- }
-
- for (nfds_t i = 0; i < nfds; ++i) {
- if (pollfds[i].revents != 0) {
- /* XXX POLLERR|POLLHUP|POLLNVAL */
-
- /* serial port */
- if (pollfds[i].fd == serial_fd) {
- int complete;
- hal_slip_recv_char(ibuf.buf, &ibuf.len, sizeof(ibuf.buf), &complete);
- if (complete) {
-#ifdef DEBUG
- printf("serial port received response:\n");
- hexdump(ibuf.buf, ibuf.len);
-#endif
- /* We've got a complete rpc response packet. */
- const uint8_t *bufptr = ibuf.buf + 4;
- const uint8_t * const limit = ibuf.buf + ibuf.len;
- uint32_t sock;
- /* Second word of the response is the client ID. */
- hal_xdr_decode_int(&bufptr, limit, &sock);
- /* Pass response on to the client that requested it. */
- send(sock, ibuf.buf, ibuf.len, 0);
- /* Reinitialize the receive buffer. */
- memset(&ibuf, 0, sizeof(ibuf));
- }
- }
-
- /* listening socket */
- else if (pollfds[i].fd == lsock) {
- /* Accept incoming connection. */
- dsock = accept(lsock, NULL, NULL);
- if (ret == -1) {
- perror("accept");
- exit(EXIT_FAILURE);
- }
- poll_add(dsock);
-#ifdef DEBUG
- printf("listening socket accept data socket %d\n", dsock);
-#endif
- }
-
- /* client data socket */
- else {
- const uint8_t * const limit = obuf.buf + HAL_RPC_MAX_PKT_SIZE;
- /* Get the client's rpc request packet. */
- obuf.len = recv(pollfds[i].fd, obuf.buf, HAL_RPC_MAX_PKT_SIZE, 0);
-#ifdef DEBUG
- printf("data socket %d received request:\n", pollfds[i].fd);
- hexdump(obuf.buf, obuf.len);
-#endif
-
- /* Fill in the client handle arg - first field after opcode. */
- uint8_t *bufptr = obuf.buf + 4;
- hal_xdr_encode_int(&bufptr, limit, pollfds[i].fd);
-
- if (obuf.len > 0) {
-#ifdef DEBUG
- printf("passing to serial port:\n");
- hexdump(obuf.buf, obuf.len);
-#endif
- /* Pass it on to the serial port. */
- hal_slip_send(obuf.buf, obuf.len);
- }
- else {
-#ifdef DEBUG
- printf("closing data socket\n");
-#endif
- /* Client has closed the socket. */
- close(pollfds[i].fd);
- poll_remove(pollfds[i].fd);
- }
- /* Reinitialize the transmit buffer. */
- memset(&obuf, 0, sizeof(obuf));
- }
- }
- }
- }
-
- /*NOTREACHED*/
- exit(EXIT_SUCCESS);
-}
diff --git a/hal_internal.h b/hal_internal.h
index a8f88e2..ef3dd49 100644
--- a/hal_internal.h
+++ b/hal_internal.h
@@ -880,7 +880,7 @@ typedef enum {
*/
#ifndef HAL_CLIENT_DAEMON_DEFAULT_SOCKET_NAME
-#define HAL_CLIENT_DAEMON_DEFAULT_SOCKET_NAME "/tmp/cryptech_rpcd.socket"
+#define HAL_CLIENT_DAEMON_DEFAULT_SOCKET_NAME "/tmp/.cryptech_rpcmuxd"
#endif
/*
diff --git a/rpc_client_daemon.c b/rpc_client_daemon.c
index dea352f..7ff3f21 100644
--- a/rpc_client_daemon.c
+++ b/rpc_client_daemon.c
@@ -45,17 +45,18 @@ static int sock = -1;
hal_error_t hal_rpc_client_transport_init(void)
{
+ const char *sockname = getenv("CRYPTECH_RPC_CLIENT_SOCKET_NAME");
struct sockaddr_un name;
- int ret;
- sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1)
return perror("socket"), HAL_ERROR_RPC_TRANSPORT;
+ if (sockname == NULL)
+ sockname = HAL_CLIENT_DAEMON_DEFAULT_SOCKET_NAME;
memset(&name, 0, sizeof(struct sockaddr_un));
name.sun_family = AF_UNIX;
- strncpy(name.sun_path, HAL_CLIENT_DAEMON_DEFAULT_SOCKET_NAME, sizeof(name.sun_path) - 1);
- ret = connect(sock, (const struct sockaddr *) &name, sizeof(struct sockaddr_un));
- if (ret == -1)
+ strncpy(name.sun_path, sockname, sizeof(name.sun_path) - 1);
+ if (connect(sock, (const struct sockaddr *) &name, sizeof(struct sockaddr_un)) < 0)
return perror("connect"), HAL_ERROR_RPC_TRANSPORT;
return HAL_OK;
}
@@ -69,17 +70,35 @@ hal_error_t hal_rpc_client_transport_close(void)
return HAL_OK;
}
+
hal_error_t hal_rpc_send(const uint8_t * const buf, const size_t len)
{
- ssize_t ret = send(sock, (const void *)buf, len, 0);
- return (ret == -1) ? HAL_ERROR_RPC_TRANSPORT : HAL_OK;
+ return hal_slip_send(buf, len);
}
hal_error_t hal_rpc_recv(uint8_t * const buf, size_t * const len)
{
- ssize_t ret = recv(sock, (void *)buf, *len, 0);
- if (ret == -1)
- return HAL_ERROR_RPC_TRANSPORT;
- *len = (size_t)ret;
+ size_t maxlen = *len;
+ *len = 0;
+ hal_error_t err = hal_slip_recv(buf, len, maxlen);
+ return err;
+}
+
+/*
+ * These two are sort of mis-named, fix eventually, but this is what
+ * the code in slip.c expects.
+ */
+
+hal_error_t hal_serial_send_char(const uint8_t c)
+{
+ if (write(sock, &c, 1) != 1)
+ return perror("write"), HAL_ERROR_RPC_TRANSPORT;
+ return HAL_OK;
+}
+
+hal_error_t hal_serial_recv_char(uint8_t * const c)
+{
+ if (read(sock, c, 1) != 1)
+ return perror("read"), HAL_ERROR_RPC_TRANSPORT;
return HAL_OK;
}