ws curl + http client tls option handling + ca cert processing for mbedtls

This commit is contained in:
Benjamin Sergeant 2019-09-29 21:13:11 -07:00
parent 4e4792d6dc
commit 55141aa875
9 changed files with 51 additions and 14 deletions

View File

@ -43,6 +43,11 @@ namespace ix
_thread.join(); _thread.join();
} }
void HttpClient::setTLSOptions(const SocketTLSOptions& tlsOptions)
{
_tlsOptions = tlsOptions;
}
HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, const std::string& verb) HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, const std::string& verb)
{ {
auto request = std::make_shared<HttpRequestArgs>(); auto request = std::make_shared<HttpRequestArgs>();
@ -142,8 +147,7 @@ namespace ix
bool tls = protocol == "https"; bool tls = protocol == "https";
std::string errorMsg; std::string errorMsg;
SocketTLSOptions tlsOptions; _socket = createSocket(tls, errorMsg, _tlsOptions);
_socket = createSocket(tls, errorMsg, tlsOptions);
if (!_socket) if (!_socket)
{ {

View File

@ -9,6 +9,7 @@
#include "IXHttp.h" #include "IXHttp.h"
#include "IXSocket.h" #include "IXSocket.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
#include "IXSocketTLSOptions.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
@ -58,6 +59,9 @@ namespace ix
bool performRequest(HttpRequestArgsPtr request, bool performRequest(HttpRequestArgsPtr request,
const OnResponseCallback& onResponseCallback); const OnResponseCallback& onResponseCallback);
// TLS
void setTLSOptions(const SocketTLSOptions& tlsOptions);
std::string serializeHttpParameters(const HttpParameters& httpParameters); std::string serializeHttpParameters(const HttpParameters& httpParameters);
std::string urlEncode(const std::string& value); std::string urlEncode(const std::string& value);
@ -86,5 +90,7 @@ namespace ix
std::shared_ptr<Socket> _socket; std::shared_ptr<Socket> _socket;
std::mutex _mutex; // to protect accessing the _socket (only one socket per client) std::mutex _mutex; // to protect accessing the _socket (only one socket per client)
SocketTLSOptions _tlsOptions;
}; };
} // namespace ix } // namespace ix

View File

@ -17,8 +17,9 @@
namespace ix namespace ix
{ {
SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions) SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd)
: _tlsOptions(tlsOptions) : Socket(fd)
, _tlsOptions(tlsOptions)
{ {
initMBedTLS(); initMBedTLS();
} }
@ -36,6 +37,7 @@ namespace ix
mbedtls_ssl_config_init(&_conf); mbedtls_ssl_config_init(&_conf);
mbedtls_ctr_drbg_init(&_ctr_drbg); mbedtls_ctr_drbg_init(&_ctr_drbg);
mbedtls_entropy_init(&_entropy); mbedtls_entropy_init(&_entropy);
mbedtls_x509_crt_init(&_cacert);
} }
bool SocketMbedTLS::init(const std::string& host, std::string& errMsg) bool SocketMbedTLS::init(const std::string& host, std::string& errMsg)
@ -66,8 +68,27 @@ namespace ix
mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);
// FIXME: cert verification is disabled if (_tlsOptions.isPeerVerifyDisabled())
{
mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_NONE);
}
else
{
mbedtls_ssl_conf_ca_chain(&_conf, &_cacert, NULL);
// FIXME: should we call mbedtls_ssl_conf_verify ?
if (_tlsOptions.isUsingSystemDefaults())
{
; // FIXME
}
else if (mbedtls_x509_crt_parse_file(&_cacert, _tlsOptions.caFile.c_str()) < 0)
{
errMsg = "Cannot parse CA file '" + _tlsOptions.caFile + "'";
return false;
}
mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
}
if (mbedtls_ssl_setup(&_ssl, &_conf) != 0) if (mbedtls_ssl_setup(&_ssl, &_conf) != 0)
{ {
@ -134,6 +155,7 @@ namespace ix
mbedtls_ssl_config_free(&_conf); mbedtls_ssl_config_free(&_conf);
mbedtls_ctr_drbg_free(&_ctr_drbg); mbedtls_ctr_drbg_free(&_ctr_drbg);
mbedtls_entropy_free(&_entropy); mbedtls_entropy_free(&_entropy);
mbedtls_x509_crt_free(&_cacert);
Socket::close(); Socket::close();
} }

View File

@ -14,6 +14,8 @@
#include <mbedtls/error.h> #include <mbedtls/error.h>
#include <mbedtls/net.h> #include <mbedtls/net.h>
#include <mbedtls/platform.h> #include <mbedtls/platform.h>
#include <mbedtls/x509.h>
#include <mbedtls/x509_crt.h>
#include <mutex> #include <mutex>
namespace ix namespace ix
@ -21,7 +23,7 @@ namespace ix
class SocketMbedTLS final : public Socket class SocketMbedTLS final : public Socket
{ {
public: public:
SocketMbedTLS(const SocketTLSOptions& tlsOptions); SocketMbedTLS(const SocketTLSOptions& tlsOptions, int fd = -1);
~SocketMbedTLS(); ~SocketMbedTLS();
virtual bool connect(const std::string& host, virtual bool connect(const std::string& host,
@ -39,6 +41,7 @@ namespace ix
mbedtls_ssl_config _conf; mbedtls_ssl_config _conf;
mbedtls_entropy_context _entropy; mbedtls_entropy_context _entropy;
mbedtls_ctr_drbg_context _ctr_drbg; mbedtls_ctr_drbg_context _ctr_drbg;
mbedtls_x509_crt _cacert;
std::mutex _mutex; std::mutex _mutex;
SocketTLSOptions _tlsOptions; SocketTLSOptions _tlsOptions;

View File

@ -280,6 +280,7 @@ namespace ix
auto sslErr = ERR_get_error(); auto sslErr = ERR_get_error();
errMsg = "OpenSSL failed - SSL_CTX_default_verify_paths loading failed: "; errMsg = "OpenSSL failed - SSL_CTX_default_verify_paths loading failed: ";
errMsg += ERR_error_string(sslErr, nullptr); errMsg += ERR_error_string(sslErr, nullptr);
return false;
} }
} }
else if (SSL_CTX_load_verify_locations( else if (SSL_CTX_load_verify_locations(
@ -289,6 +290,7 @@ namespace ix
errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" + errMsg = "OpenSSL failed - SSL_CTX_load_verify_locations(\"" +
_tlsOptions.caFile + "\") failed: "; _tlsOptions.caFile + "\") failed: ";
errMsg += ERR_error_string(sslErr, nullptr); errMsg += ERR_error_string(sslErr, nullptr);
return false;
} }
SSL_CTX_set_verify(_ssl_context, SSL_CTX_set_verify(_ssl_context,

View File

@ -17,10 +17,6 @@ namespace ix
bool SocketTLSOptions::isValid() const bool SocketTLSOptions::isValid() const
{ {
#ifndef IXWEBSOCKET_USE_TLS
_errMsg = "To use TLS features the library must be compiled with USE_TLS";
return false;
#endif
if (!_validated) if (!_validated)
{ {
if (!certFile.empty() && !std::ifstream(certFile)) if (!certFile.empty() && !std::ifstream(certFile))

View File

@ -10,9 +10,7 @@
#pragma once #pragma once
#include "IXProgressCallback.h" #include "IXProgressCallback.h"
#ifdef IXWEBSOCKET_USE_TLS
#include "IXSocketTLSOptions.h" #include "IXSocketTLSOptions.h"
#endif
#include "IXWebSocketCloseConstants.h" #include "IXWebSocketCloseConstants.h"
#include "IXWebSocketErrorInfo.h" #include "IXWebSocketErrorInfo.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"

View File

@ -68,7 +68,11 @@ test:
(cd test ; python2.7 run.py -r) (cd test ; python2.7 run.py -r)
test_openssl: test_openssl:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4) mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_TEST=1 .. ; make -j 4)
(cd test ; python2.7 run.py -r)
test_mbedtls:
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. ; make -j 4)
(cd test ; python2.7 run.py -r) (cd test ; python2.7 run.py -r)
ws_test: ws ws_test: ws

View File

@ -98,6 +98,8 @@ namespace ix
const ix::SocketTLSOptions& tlsOptions) const ix::SocketTLSOptions& tlsOptions)
{ {
HttpClient httpClient; HttpClient httpClient;
httpClient.setTLSOptions(tlsOptions);
auto args = httpClient.createRequest(); auto args = httpClient.createRequest();
args->extraHeaders = parseHeaders(headersData); args->extraHeaders = parseHeaders(headersData);
args->connectTimeout = connectTimeout; args->connectTimeout = connectTimeout;