From e13442c12226fea4750c0ba6f4039ae7c16b78ed Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Thu, 23 Mar 2023 16:39:15 +0000 Subject: [PATCH] Fix strange behavior in TlsLibreSSL. tls_read() and tls_write() may return TLS_WANT_POLLIN or TLS_WANT_POLLOUT if data isn't ready to be read or written yet. We have to account for this by converting it to EAGAIN, which is how a typical read() or write() function should behave. Also installed a SIGPIPE handler; we do not want to be terminated by SIGPIPE, and it's safe to ignore this signal because it should be handled thoroughly in the code. --- contrib/development.conf | 7 ++++++ src/Main.c | 50 ++++++++++++++++++++++++---------------- src/Tls/TlsLibreSSL.c | 38 ++++++++++++++++++++++-------- tools/bin/td | 1 + 4 files changed, 67 insertions(+), 29 deletions(-) diff --git a/contrib/development.conf b/contrib/development.conf index effc86e..b132661 100644 --- a/contrib/development.conf +++ b/contrib/development.conf @@ -10,6 +10,13 @@ { "port": 8008, "tls": false + }, + { + "port": 8448, + "tls": { + "cert": "telodendria.crt", + "key": "telodendria.key" + } } ], "registration": true, diff --git a/src/Main.c b/src/Main.c index 5b701ed..87319f5 100644 --- a/src/Main.c +++ b/src/Main.c @@ -48,22 +48,26 @@ static Array *httpServers = NULL; static void -TelodendriaSignalHandler(int signalNo) +TelodendriaSignalHandler(int signal) { size_t i; - (void) signalNo; - - if (!httpServers) + switch (signal) { - return; - } + case SIGPIPE: + return; + case SIGINT: + if (!httpServers) + { + return; + } - for (i = 0; i < ArraySize(httpServers); i++) - { - HttpServer *server = ArrayGet(httpServers, i); - - HttpServerStop(server); + for (i = 0; i < ArraySize(httpServers); i++) + { + HttpServer *server = ArrayGet(httpServers, i); + HttpServerStop(server); + } + break; } } @@ -478,17 +482,23 @@ main(int argc, char **argv) sigfillset(&sigAction.sa_mask); sigAction.sa_flags = SA_RESTART; - if (sigaction(SIGINT, &sigAction, NULL) < 0) - { - Log(LOG_ERR, "Unable to install signal handler."); - exit = EXIT_FAILURE; - goto finish; - } - else - { - Log(LOG_DEBUG, "Installed SIGINT signal handler."); +#define SIGACTION(sig, act, oact) \ + if (sigaction(sig, act, oact) < 0) \ + { \ + Log(LOG_ERR, "Unable to install signal handler: %s", #sig); \ + exit = EXIT_FAILURE; \ + goto finish; \ + } \ + else \ + { \ + Log(LOG_DEBUG, "Installed signal handler: %s", #sig); \ } + SIGACTION(SIGINT, &sigAction, NULL); + SIGACTION(SIGPIPE, &sigAction, NULL); + +#undef SIGACTION + /* Block this thread until the servers are terminated by a signal * handler */ for (i = 0; i < ArraySize(httpServers); i++) diff --git a/src/Tls/TlsLibreSSL.c b/src/Tls/TlsLibreSSL.c index ddcba3f..27b9fa7 100644 --- a/src/Tls/TlsLibreSSL.c +++ b/src/Tls/TlsLibreSSL.c @@ -28,6 +28,8 @@ #include #include +#include + #include /* LibreSSL TLS */ typedef struct LibreSSLCookie @@ -74,6 +76,11 @@ TlsInitClient(int fd, const char *serverName) goto error; } + if (tls_handshake(cookie->ctx) == -1) + { + goto error; + } + return cookie; error: @@ -119,25 +126,26 @@ TlsInitServer(int fd, const char *crt, const char *key) if (tls_config_set_cert_file(cookie->cfg, crt) == -1) { - Log(LOG_ERR, "Error with certificate file."); goto error; } if (tls_config_set_key_file(cookie->cfg, key) == -1) { - Log(LOG_ERR, "Error with key file."); goto error; } if (tls_configure(cookie->ctx, cookie->cfg) == -1) { - Log(LOG_ERR, "Error configuring context."); goto error; } - if (tls_accept_socket(cookie->ctx, &cookie->cctx, fd) == -1) + if (tls_accept_fds(cookie->ctx, &cookie->cctx, fd, fd) == -1) + { + goto error; + } + + if (tls_handshake(cookie->cctx) == -1) { - Log(LOG_ERR, "Error accepting socket."); goto error; } @@ -177,11 +185,17 @@ ssize_t TlsRead(void *cookie, void *buf, size_t nBytes) { LibreSSLCookie *tls = cookie; - ssize_t ret = tls_read(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes); + struct tls *ctx = tls->cctx ? tls->cctx : tls->ctx; + ssize_t ret = tls_read(ctx, buf, nBytes); if (ret == -1) { - Log(LOG_ERR, "TlsRead(): %s", tls_error(tls->cctx ? tls->cctx : tls->ctx)); + errno = EIO; + } + else if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) + { + errno = EAGAIN; + ret = -1; } return ret; @@ -191,11 +205,17 @@ ssize_t TlsWrite(void *cookie, void *buf, size_t nBytes) { LibreSSLCookie *tls = cookie; - ssize_t ret = tls_write(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes); + struct tls *ctx = tls->cctx ? tls->cctx : tls->ctx; + ssize_t ret = tls_write(ctx, buf, nBytes); if (ret == -1) { - Log(LOG_ERR, "TlsWrite(): %s", tls_error(tls->cctx ? tls->cctx : tls->ctx)); + errno = EIO; + } + else if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) + { + errno = EAGAIN; + ret = -1; } return ret; diff --git a/tools/bin/td b/tools/bin/td index 234ab0a..41a79f0 100644 --- a/tools/bin/td +++ b/tools/bin/td @@ -55,6 +55,7 @@ MAIN="Main" if [ "$DEBUG" = "1" ]; then CFLAGS="$CFLAGS -O0 -g" + LDFLAGS="-lm -pthread ${TLS_LIBS}" PROG="$PROG-debug" fi