From 7b81a859a6137d551ef6eee002c2cc6dcc0d5522 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Wed, 28 Jan 2015 16:14:23 +0100 Subject: [PATCH] frontend, sysdbd: Let all TCP connections use SSL. Client certificate checks are enforced and the client cert's common name (CN) is used as the peer name. --- src/frontend/connection-private.h | 3 +- src/frontend/connection.c | 2 +- src/frontend/sock.c | 70 ++++++++++++++++++++++++++++++- src/tools/sysdbd/main.c | 8 ++++ 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index a0f28ae..94c3b4a 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -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 @@ -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; diff --git a/src/frontend/connection.c b/src/frontend/connection.c index 44247eb..64f2cb2 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -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)) { diff --git a/src/frontend/sock.c b/src/frontend/sock.c index 5279cba..c9d28b1 100644 --- a/src/frontend/sock.c +++ b/src/frontend/sock.c @@ -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 @@ -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; diff --git a/src/tools/sysdbd/main.c b/src/tools/sysdbd/main.c index bf56656..9d85ba8 100644 --- a/src/tools/sysdbd/main.c +++ b/src/tools/sysdbd/main.c @@ -60,6 +60,9 @@ #include +#include +#include + #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 */ -- 2.30.2