Code

frontend, sysdbd: Let all TCP connections use SSL.
authorSebastian Harl <sh@tokkee.org>
Wed, 28 Jan 2015 15:14:23 +0000 (16:14 +0100)
committerSebastian Harl <sh@tokkee.org>
Wed, 28 Jan 2015 15:14:23 +0000 (16:14 +0100)
Client certificate checks are enforced and the client cert's common name (CN)
is used as the peer name.

src/frontend/connection-private.h
src/frontend/connection.c
src/frontend/sock.c
src/tools/sysdbd/main.c

index a0f28ae985b37a81442ad7145eb3a056e9dffbca..94c3b4a576ef443602b14ebf4e0b969cd0a22cfd 100644 (file)
@@ -37,6 +37,7 @@
 #include "core/object.h"
 #include "core/store.h"
 #include "core/timeseries.h"
+#include "utils/ssl.h"
 #include "utils/strbuf.h"
 
 #include <inttypes.h>
@@ -62,7 +63,7 @@ struct sdb_conn {
        ssize_t (*read)(sdb_conn_t *, size_t);
        ssize_t (*write)(sdb_conn_t *, const void *, size_t);
        int (*finish)(sdb_conn_t *);
-       void *session;
+       sdb_ssl_session_t *ssl_session;
 
        /* read buffer */
        sdb_strbuf_t *buf;
index 44247ebd4961988035b7c90c70baf12e377b8c0b..64f2cb2000322dcb83557c932282e0125a797ca2 100644 (file)
@@ -125,7 +125,7 @@ connection_init(sdb_object_t *obj, va_list ap)
        conn->read = conn_read;
        conn->write = conn_write;
        conn->finish = NULL;
-       conn->session = NULL;
+       conn->ssl_session = NULL;
 
        sock_fl = fcntl(conn->fd, F_GETFL);
        if (fcntl(conn->fd, F_SETFL, sock_fl | O_NONBLOCK)) {
index 5279cbae84fd44d1c05623537a1bbf468860653b..c9d28b1bf16365fa4c86853fc4b74a54a9da0bc4 100644 (file)
@@ -38,6 +38,7 @@
 #include "utils/error.h"
 #include "utils/llist.h"
 #include "utils/os.h"
+#include "utils/ssl.h"
 #include "utils/strbuf.h"
 
 #include <assert.h>
@@ -78,6 +79,10 @@ typedef struct {
        char *address;
        int   type;
 
+       /* optional SSL settings */
+       sdb_ssl_server_t *ssl;
+
+       /* listener configuration */
        int sock_fd;
        int (*setup)(sdb_conn_t *, void *);
 } listener_t;
@@ -108,6 +113,30 @@ struct sdb_fe_socket {
        sdb_channel_t *chan;
 };
 
+/*
+ * SSL helper functions
+ */
+
+static ssize_t
+ssl_read(sdb_conn_t *conn, size_t n)
+{
+       char buf[n];
+       ssize_t ret;
+
+       ret = sdb_ssl_session_read(conn->ssl_session, buf, n);
+       if (ret <= 0)
+               return ret;
+
+       sdb_strbuf_memappend(conn->buf, buf, ret);
+       return ret;
+} /* ssl_read */
+
+static ssize_t
+ssl_write(sdb_conn_t *conn, const void *buf, size_t n)
+{
+       return sdb_ssl_session_write(conn->ssl_session, buf, n);
+} /* ssl_write */
+
 /*
  * connection management functions
  */
@@ -225,6 +254,34 @@ close_unixsock(listener_t *listener)
        unlink(listener->address);
 } /* close_unixsock */
 
+static int
+finish_tcp(sdb_conn_t *conn)
+{
+       if (! conn->ssl_session)
+               return 0;
+
+       sdb_ssl_session_destroy(conn->ssl_session);
+       conn->ssl_session = NULL;
+       return 0;
+} /* finish_tcp */
+
+static int
+setup_tcp(sdb_conn_t *conn, void *user_data)
+{
+       listener_t *listener = user_data;
+
+       conn->ssl_session = sdb_ssl_server_accept(listener->ssl, conn->fd);
+       if (! conn->ssl_session)
+               return -1;
+
+       conn->username = sdb_ssl_session_peer(conn->ssl_session);
+
+       conn->finish = finish_tcp;
+       conn->read = ssl_read;
+       conn->write = ssl_write;
+       return 0;
+} /* setup_tcp */
+
 static int
 open_tcp(listener_t *listener)
 {
@@ -233,6 +290,11 @@ open_tcp(listener_t *listener)
 
        assert(listener);
 
+       /* TODO: make options configurable */
+       listener->ssl = sdb_ssl_server_create(NULL);
+       if (! listener->ssl)
+               return -1;
+
        if ((status = sdb_resolve(SDB_NET_TCP, listener->address, &ai_list))) {
                sdb_log(SDB_LOG_ERR, "frontend: Failed to resolve '%s': %s",
                                listener->address, gai_strerror(status));
@@ -277,6 +339,8 @@ open_tcp(listener_t *listener)
 
        if (listener->sock_fd < 0)
                return -1;
+
+       listener->setup = setup_tcp;
        return 0;
 } /* open_tcp */
 
@@ -285,6 +349,9 @@ close_tcp(listener_t *listener)
 {
        assert(listener);
 
+       sdb_ssl_server_destroy(listener->ssl);
+       listener->ssl = NULL;
+
        if (listener->sock_fd >= 0)
                close(listener->sock_fd);
        listener->sock_fd = -1;
@@ -424,6 +491,7 @@ listener_create(sdb_fe_socket_t *sock, const char *address)
        }
        listener->type = type;
        listener->setup = NULL;
+       listener->ssl = NULL;
 
        if (listener_impls[type].open(listener)) {
                /* prints error */
@@ -519,7 +587,7 @@ connection_accept(sdb_fe_socket_t *sock, listener_t *listener)
        int status;
 
        obj = SDB_OBJ(sdb_connection_accept(listener->sock_fd,
-                               listener->setup, NULL));
+                               listener->setup, listener));
        if (! obj)
                return -1;
 
index bf56656d05ca3e93c961a76c32501d335ffcbfb2..9d85ba8ead2005d285b91c1bdf513fae21372f3d 100644 (file)
@@ -60,6 +60,9 @@
 
 #include <pthread.h>
 
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
 #ifndef CONFIGFILE
 #      define CONFIGFILE SYSCONFDIR"/sysdb/sysdbd.conf"
 #endif
@@ -366,6 +369,9 @@ main(int argc, char **argv)
                if (daemonize())
                        exit(1);
 
+       SSL_load_error_strings();
+       OpenSSL_add_ssl_algorithms();
+
        sdb_plugin_init_all();
        plugin_main_loop.default_interval = SECS_TO_SDB_TIME(60);
 
@@ -389,6 +395,8 @@ main(int argc, char **argv)
        sdb_log(SDB_LOG_INFO, "Shutting down SysDB daemon "SDB_VERSION_STRING
                        SDB_VERSION_EXTRA" (pid %i)", (int)getpid());
        sdb_plugin_shutdown_all();
+
+       ERR_free_strings();
        return status;
 } /* main */