From 4e1888ac1951190969746574bab1e5c7886f4170 Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Wed, 18 Dec 2019 11:51:02 -0800 Subject: [PATCH] (tls) Experimental TLS server support with mbedtls (windows) + process cert tlsoption (client + server) --- docs/CHANGELOG.md | 4 ++ ixwebsocket/IXSocketMbedTLS.cpp | 63 +++++++++++++++++++++++++++++--- ixwebsocket/IXSocketMbedTLS.h | 3 +- ixwebsocket/IXWebSocketVersion.h | 2 +- ws/test_ws.sh | 2 +- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index dd8250de..6ace1dab 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +## [7.5.7] - 2019-12-18 + +(tls) Experimental TLS server support with mbedtls (windows) + process cert tlsoption (client + server) + ## [7.5.6] - 2019-12-18 (tls servers) Make it clear that apple ssl and mbedtls backends do not support SSL in server mode diff --git a/ixwebsocket/IXSocketMbedTLS.cpp b/ixwebsocket/IXSocketMbedTLS.cpp index 402ffca5..964cdffc 100644 --- a/ixwebsocket/IXSocketMbedTLS.cpp +++ b/ixwebsocket/IXSocketMbedTLS.cpp @@ -38,9 +38,10 @@ namespace ix mbedtls_ctr_drbg_init(&_ctr_drbg); mbedtls_entropy_init(&_entropy); mbedtls_x509_crt_init(&_cacert); + mbedtls_x509_crt_init(&_cert); } - bool SocketMbedTLS::init(const std::string& host, std::string& errMsg) + bool SocketMbedTLS::init(const std::string& host, bool isClient, std::string& errMsg) { initMBedTLS(); std::lock_guard lock(_mutex); @@ -58,7 +59,8 @@ namespace ix } if (mbedtls_ssl_config_defaults(&_conf, - MBEDTLS_SSL_IS_CLIENT, + (isClient) ? MBEDTLS_SSL_IS_CLIENT + : MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { @@ -68,6 +70,15 @@ namespace ix mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); + if (_tlsOptions.hasCertAndKey()) + { + if (mbedtls_x509_crt_parse_file(&_cacert, _tlsOptions.certFile.c_str()) < 0) + { + errMsg = "Cannot parse cert file '" + _tlsOptions.certFile + "'"; + return false; + } + } + if (_tlsOptions.isPeerVerifyDisabled()) { mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE); @@ -96,7 +107,7 @@ namespace ix return false; } - if (mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0) + if (!host.empty() && mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0) { errMsg = "SNI setup failed"; return false; @@ -107,8 +118,46 @@ namespace ix bool SocketMbedTLS::accept(std::string& errMsg) { - errMsg = "TLS not supported yet in server mode with mbedtls backend"; - return false; + bool isClient = false; + bool initialized = init(std::string(), isClient, errMsg); + if (!initialized) + { + close(); + return false; + } + + mbedtls_ssl_set_bio(&_ssl, &_sockfd, mbedtls_net_send, mbedtls_net_recv, NULL); + + int res; + do + { + std::lock_guard lock(_mutex); + res = mbedtls_ssl_handshake(&_ssl); + } while (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (res != 0) + { + char buf[256]; + mbedtls_strerror(res, buf, sizeof(buf)); + + errMsg = "error in handshake : "; + errMsg += buf; + + if (res == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) + { + char verifyBuf[512]; + uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl); + + mbedtls_x509_crt_verify_info(verifyBuf, sizeof(verifyBuf), " ! ", flags); + errMsg += " : "; + errMsg += verifyBuf; + } + + close(); + return false; + } + + return true; } bool SocketMbedTLS::connect(const std::string& host, @@ -122,7 +171,8 @@ namespace ix if (_sockfd == -1) return false; } - bool initialized = init(host, errMsg); + bool isClient = true; + bool initialized = init(host, isClient, errMsg); if (!initialized) { close(); @@ -162,6 +212,7 @@ namespace ix mbedtls_ctr_drbg_free(&_ctr_drbg); mbedtls_entropy_free(&_entropy); mbedtls_x509_crt_free(&_cacert); + mbedtls_x509_crt_free(&_cert); Socket::close(); } diff --git a/ixwebsocket/IXSocketMbedTLS.h b/ixwebsocket/IXSocketMbedTLS.h index 690d8646..8ff7e2a0 100644 --- a/ixwebsocket/IXSocketMbedTLS.h +++ b/ixwebsocket/IXSocketMbedTLS.h @@ -44,11 +44,12 @@ namespace ix mbedtls_entropy_context _entropy; mbedtls_ctr_drbg_context _ctr_drbg; mbedtls_x509_crt _cacert; + mbedtls_x509_crt _cert; std::mutex _mutex; SocketTLSOptions _tlsOptions; - bool init(const std::string& host, std::string& errMsg); + bool init(const std::string& host, bool isClient, std::string& errMsg); void initMBedTLS(); }; diff --git a/ixwebsocket/IXWebSocketVersion.h b/ixwebsocket/IXWebSocketVersion.h index 173ee422..ccc91115 100644 --- a/ixwebsocket/IXWebSocketVersion.h +++ b/ixwebsocket/IXWebSocketVersion.h @@ -6,4 +6,4 @@ #pragma once -#define IX_WEBSOCKET_VERSION "7.5.6" +#define IX_WEBSOCKET_VERSION "7.5.7" diff --git a/ws/test_ws.sh b/ws/test_ws.sh index a8d4f44e..5bd9fb46 100644 --- a/ws/test_ws.sh +++ b/ws/test_ws.sh @@ -53,7 +53,7 @@ done # Start a receiver mkdir -p /tmp/ws_test/receive cd /tmp/ws_test/receive -ws receive "${protocol}127.0.0.1:8090" ${delay} --pidfile /tmp/ws_test/pidfile.receive ${server_tls} & +ws receive "${protocol}127.0.0.1:8090" ${delay} --pidfile /tmp/ws_test/pidfile.receive ${client_tls} & mkdir -p /tmp/ws_test/send cd /tmp/ws_test/send