From aeb49f80e5d8bf50e9cf01084531ef49a3088161 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Fri, 24 Mar 2023 02:41:01 +0000 Subject: [PATCH] Add support for OpenSSL. This is a good demo of how easy it is to support TLS libraries. --- src/HttpClient.c | 1 - src/Main.c | 1 + src/Tls/TlsOpenSSL.c | 244 +++++++++++++++++++++++++++++++++++++++++++ src/include/Tls.h | 1 + tools/bin/td | 3 + 5 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/Tls/TlsOpenSSL.c diff --git a/src/HttpClient.c b/src/HttpClient.c index aa4d511..1ee1568 100644 --- a/src/HttpClient.c +++ b/src/HttpClient.c @@ -210,7 +210,6 @@ HttpRequestSend(HttpClientContext * context) if (lineLen == -1) { - Log(LOG_ERR, "HttpRequestSend(): %s", strerror(errno)); return 0; } diff --git a/src/Main.c b/src/Main.c index 87319f5..024212d 100644 --- a/src/Main.c +++ b/src/Main.c @@ -65,6 +65,7 @@ TelodendriaSignalHandler(int signal) for (i = 0; i < ArraySize(httpServers); i++) { HttpServer *server = ArrayGet(httpServers, i); + HttpServerStop(server); } break; diff --git a/src/Tls/TlsOpenSSL.c b/src/Tls/TlsOpenSSL.c new file mode 100644 index 0000000..de73733 --- /dev/null +++ b/src/Tls/TlsOpenSSL.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include + +#if TLS_IMPL == TLS_OPENSSL + +#include +#include + +#include +#include + +typedef struct OpenSSLCookie +{ + int fd; + const SSL_METHOD *method; + SSL_CTX *ctx; + SSL *ssl; +} OpenSSLCookie; + +void * +TlsInitClient(int fd, const char *serverName) +{ + OpenSSLCookie *cookie; + char errorStr[256]; + + /* + * TODO: Seems odd that this isn't needed to make the + * connection... we should figure out how to verify the + * certificate matches the server we think we're + * connecting to. + */ + (void) serverName; + + cookie = Malloc(sizeof(OpenSSLCookie)); + if (!cookie) + { + return NULL; + } + + memset(cookie, 0, sizeof(OpenSSLCookie)); + + cookie->method = TLS_client_method(); + cookie->ctx = SSL_CTX_new(cookie->method); + if (!cookie->ctx) + { + goto error; + } + + cookie->ssl = SSL_new(cookie->ctx); + if (!cookie->ssl) + { + goto error; + } + + if (!SSL_set_fd(cookie->ssl, fd)) + { + goto error; + } + + if (SSL_connect(cookie->ssl) <= 0) + { + goto error; + } + + return cookie; + +error: + Log(LOG_ERR, "TlsClientInit(): %s", ERR_error_string(ERR_get_error(), errorStr)); + + if (cookie->ssl) + { + SSL_shutdown(cookie->ssl); + SSL_free(cookie->ssl); + } + + close(cookie->fd); + + if (cookie->ctx) + { + SSL_CTX_free(cookie->ctx); + } + + return NULL; + return NULL; +} + +void * +TlsInitServer(int fd, const char *crt, const char *key) +{ + OpenSSLCookie *cookie; + char errorStr[256]; + + cookie = Malloc(sizeof(OpenSSLCookie)); + if (!cookie) + { + return NULL; + } + + memset(cookie, 0, sizeof(OpenSSLCookie)); + + cookie->method = TLS_server_method(); + cookie->ctx = SSL_CTX_new(cookie->method); + if (!cookie->ctx) + { + goto error; + } + + if (SSL_CTX_use_certificate_file(cookie->ctx, crt, SSL_FILETYPE_PEM) <= 0) + { + goto error; + } + + if (SSL_CTX_use_PrivateKey_file(cookie->ctx, key, SSL_FILETYPE_PEM) <= 0) + { + goto error; + } + + cookie->ssl = SSL_new(cookie->ctx); + if (!cookie->ssl) + { + goto error; + } + + if (!SSL_set_fd(cookie->ssl, fd)) + { + goto error; + } + + if (SSL_accept(cookie->ssl) <= 0) + { + goto error; + } + + return cookie; + +error: + Log(LOG_ERR, "TlsServerInit(): %s", ERR_error_string(ERR_get_error(), errorStr)); + + if (cookie->ssl) + { + SSL_shutdown(cookie->ssl); + SSL_free(cookie->ssl); + } + + close(cookie->fd); + + if (cookie->ctx) + { + SSL_CTX_free(cookie->ctx); + } + + return NULL; +} + +ssize_t +TlsRead(void *cookie, void *buf, size_t nBytes) +{ + OpenSSLCookie *ssl = cookie; + int ret = SSL_read(ssl->ssl, buf, nBytes); + + if (ret <= 0) + { + ret = -1; + switch (SSL_get_error(ssl->ssl, ret)) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + errno = EAGAIN; + break; + default: + errno = EIO; + break; + } + } + + return ret; +} + +ssize_t +TlsWrite(void *cookie, void *buf, size_t nBytes) +{ + OpenSSLCookie *ssl = cookie; + int ret = SSL_write(ssl->ssl, buf, nBytes); + + if (ret <= 0) + { + ret = -1; + switch (SSL_get_error(ssl->ssl, ret)) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + errno = EAGAIN; + break; + default: + errno = EIO; + break; + } + } + + return ret; +} + +int +TlsClose(void *cookie) +{ + OpenSSLCookie *ssl = cookie; + + SSL_shutdown(ssl->ssl); + SSL_free(ssl->ssl); + close(ssl->fd); + SSL_CTX_free(ssl->ctx); + + Free(ssl); + + return 0; +} + +#endif diff --git a/src/include/Tls.h b/src/include/Tls.h index fff6e0a..6f3651b 100644 --- a/src/include/Tls.h +++ b/src/include/Tls.h @@ -27,6 +27,7 @@ #include #define TLS_LIBRESSL 2 +#define TLS_OPENSSL 3 extern Stream * TlsClientStream(int, const char *); diff --git a/tools/bin/td b/tools/bin/td index b67b854..bb710d6 100644 --- a/tools/bin/td +++ b/tools/bin/td @@ -37,6 +37,9 @@ if [ -n "$TLS_IMPL" ]; then "LIBRESSL") TLS_LIBS="-ltls -lcrypto -lssl" ;; + "OPENSSL") + TLS_LIBS="-lcrypto -lssl" + ;; *) echo "Unrecognized TLS implementation: ${TLS_IMPL}" echo "Consult src/include/Tls.h for supported implementations."