|
@@ -1927,7 +1927,7 @@ public:
|
|
|
[[deprecated("Use load_ca_cert_store() instead")]]
|
|
[[deprecated("Use load_ca_cert_store() instead")]]
|
|
|
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
|
void set_ca_cert_store(X509_STORE *ca_cert_store);
|
|
|
|
|
|
|
|
- [[deprecated("Use detail::tls::tls_create_ca_store() instead")]]
|
|
|
|
|
|
|
+ [[deprecated("Use tls::tls_create_ca_store() instead")]]
|
|
|
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const;
|
|
X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const;
|
|
|
|
|
|
|
|
void set_server_certificate_verifier(
|
|
void set_server_certificate_verifier(
|
|
@@ -2168,6 +2168,29 @@ public:
|
|
|
#endif
|
|
#endif
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
|
|
|
|
|
+// Mbed TLS context wrapper (holds config, entropy, DRBG, CA chain, own
|
|
|
|
|
+// cert/key). This struct is exposed for use in SSL context setup callbacks.
|
|
|
|
|
+struct MbedTlsContext {
|
|
|
|
|
+ mbedtls_ssl_config conf;
|
|
|
|
|
+ mbedtls_entropy_context entropy;
|
|
|
|
|
+ mbedtls_ctr_drbg_context ctr_drbg;
|
|
|
|
|
+ mbedtls_x509_crt ca_chain;
|
|
|
|
|
+ mbedtls_x509_crt own_cert;
|
|
|
|
|
+ mbedtls_pk_context own_key;
|
|
|
|
|
+ bool is_server = false;
|
|
|
|
|
+ bool verify_client = false;
|
|
|
|
|
+ bool has_verify_callback = false;
|
|
|
|
|
+
|
|
|
|
|
+ MbedTlsContext();
|
|
|
|
|
+ ~MbedTlsContext();
|
|
|
|
|
+
|
|
|
|
|
+ // Non-copyable
|
|
|
|
|
+ MbedTlsContext(const MbedTlsContext &) = delete;
|
|
|
|
|
+ MbedTlsContext &operator=(const MbedTlsContext &) = delete;
|
|
|
|
|
+};
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
|
class SSLServer : public Server {
|
|
class SSLServer : public Server {
|
|
|
public:
|
|
public:
|
|
@@ -2872,6 +2895,8 @@ bool is_field_value(const std::string &s);
|
|
|
|
|
|
|
|
} // namespace fields
|
|
} // namespace fields
|
|
|
|
|
|
|
|
|
|
+} // namespace detail
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* TLS Abstraction Layer Declarations
|
|
* TLS Abstraction Layer Declarations
|
|
|
*/
|
|
*/
|
|
@@ -3063,9 +3088,13 @@ std::string tls_error_string(uint64_t code);
|
|
|
|
|
|
|
|
} // namespace tls
|
|
} // namespace tls
|
|
|
|
|
|
|
|
|
|
+#endif // CPPHTTPLIB_SSL_ENABLED
|
|
|
|
|
+
|
|
|
|
|
+namespace detail {
|
|
|
|
|
+
|
|
|
|
|
+#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
|
// Utility function for SSL implementation
|
|
// Utility function for SSL implementation
|
|
|
bool is_ip_address(const std::string &host);
|
|
bool is_ip_address(const std::string &host);
|
|
|
-
|
|
|
|
|
#endif // CPPHTTPLIB_SSL_ENABLED
|
|
#endif // CPPHTTPLIB_SSL_ENABLED
|
|
|
|
|
|
|
|
} // namespace detail
|
|
} // namespace detail
|
|
@@ -10389,7 +10418,7 @@ inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
|
|
|
|
|
|
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
|
if (is_alive && is_ssl()) {
|
|
if (is_alive && is_ssl()) {
|
|
|
- if (detail::tls::tls_is_peer_closed(socket_.ssl, socket_.sock)) {
|
|
|
|
|
|
|
+ if (tls::tls_is_peer_closed(socket_.ssl, socket_.sock)) {
|
|
|
is_alive = false;
|
|
is_alive = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -10576,7 +10605,7 @@ ClientImpl::open_stream(const std::string &method, const std::string &path,
|
|
|
is_alive = detail::is_socket_alive(socket_.sock);
|
|
is_alive = detail::is_socket_alive(socket_.sock);
|
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
|
if (is_alive && is_ssl()) {
|
|
if (is_alive && is_ssl()) {
|
|
|
- if (detail::tls::tls_is_peer_closed(socket_.ssl, socket_.sock)) {
|
|
|
|
|
|
|
+ if (tls::tls_is_peer_closed(socket_.ssl, socket_.sock)) {
|
|
|
is_alive = false;
|
|
is_alive = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -11511,7 +11540,7 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req,
|
|
|
if (is_ssl()) {
|
|
if (is_ssl()) {
|
|
|
auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1;
|
|
auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1;
|
|
|
if (!is_proxy_enabled) {
|
|
if (!is_proxy_enabled) {
|
|
|
- if (detail::tls::tls_is_peer_closed(socket_.ssl, socket_.sock)) {
|
|
|
|
|
|
|
+ if (tls::tls_is_peer_closed(socket_.ssl, socket_.sock)) {
|
|
|
error = Error::SSLPeerCouldBeClosed_;
|
|
error = Error::SSLPeerCouldBeClosed_;
|
|
|
output_error_log(error, &req);
|
|
output_error_log(error, &req);
|
|
|
return false;
|
|
return false;
|
|
@@ -12662,7 +12691,6 @@ inline void ClientImpl::set_error_logger(ErrorLogger error_logger) {
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
|
|
-namespace detail {
|
|
|
|
|
namespace crypto {
|
|
namespace crypto {
|
|
|
|
|
|
|
|
inline size_t hash_size(HashAlgorithm algo) {
|
|
inline size_t hash_size(HashAlgorithm algo) {
|
|
@@ -13135,13 +13163,13 @@ inline bool tls_connect_nonblocking(tls_session_t session, socket_t sock,
|
|
|
auto bio = SSL_get_rbio(ssl);
|
|
auto bio = SSL_get_rbio(ssl);
|
|
|
|
|
|
|
|
// Set non-blocking mode for handshake
|
|
// Set non-blocking mode for handshake
|
|
|
- set_nonblocking(sock, true);
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, true);
|
|
|
if (bio) { BIO_set_nbio(bio, 1); }
|
|
if (bio) { BIO_set_nbio(bio, 1); }
|
|
|
|
|
|
|
|
- auto cleanup = scope_exit([&]() {
|
|
|
|
|
|
|
+ auto cleanup = detail::scope_exit([&]() {
|
|
|
// Restore blocking mode after handshake
|
|
// Restore blocking mode after handshake
|
|
|
if (bio) { BIO_set_nbio(bio, 0); }
|
|
if (bio) { BIO_set_nbio(bio, 0); }
|
|
|
- set_nonblocking(sock, false);
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, false);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
auto res = 0;
|
|
auto res = 0;
|
|
@@ -13149,10 +13177,14 @@ inline bool tls_connect_nonblocking(tls_session_t session, socket_t sock,
|
|
|
auto ssl_err = SSL_get_error(ssl, res);
|
|
auto ssl_err = SSL_get_error(ssl, res);
|
|
|
switch (ssl_err) {
|
|
switch (ssl_err) {
|
|
|
case SSL_ERROR_WANT_READ:
|
|
case SSL_ERROR_WANT_READ:
|
|
|
- if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; }
|
|
|
|
|
|
|
+ if (detail::select_read(sock, timeout_sec, timeout_usec) > 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
case SSL_ERROR_WANT_WRITE:
|
|
case SSL_ERROR_WANT_WRITE:
|
|
|
- if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; }
|
|
|
|
|
|
|
+ if (detail::select_write(sock, timeout_sec, timeout_usec) > 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
default: break;
|
|
default: break;
|
|
|
}
|
|
}
|
|
@@ -13180,13 +13212,13 @@ inline bool tls_accept_nonblocking(tls_session_t session, socket_t sock,
|
|
|
auto bio = SSL_get_rbio(ssl);
|
|
auto bio = SSL_get_rbio(ssl);
|
|
|
|
|
|
|
|
// Set non-blocking mode for handshake
|
|
// Set non-blocking mode for handshake
|
|
|
- set_nonblocking(sock, true);
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, true);
|
|
|
if (bio) { BIO_set_nbio(bio, 1); }
|
|
if (bio) { BIO_set_nbio(bio, 1); }
|
|
|
|
|
|
|
|
- auto cleanup = scope_exit([&]() {
|
|
|
|
|
|
|
+ auto cleanup = detail::scope_exit([&]() {
|
|
|
// Restore blocking mode after handshake
|
|
// Restore blocking mode after handshake
|
|
|
if (bio) { BIO_set_nbio(bio, 0); }
|
|
if (bio) { BIO_set_nbio(bio, 0); }
|
|
|
- set_nonblocking(sock, false);
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, false);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
auto res = 0;
|
|
auto res = 0;
|
|
@@ -13194,10 +13226,14 @@ inline bool tls_accept_nonblocking(tls_session_t session, socket_t sock,
|
|
|
auto ssl_err = SSL_get_error(ssl, res);
|
|
auto ssl_err = SSL_get_error(ssl, res);
|
|
|
switch (ssl_err) {
|
|
switch (ssl_err) {
|
|
|
case SSL_ERROR_WANT_READ:
|
|
case SSL_ERROR_WANT_READ:
|
|
|
- if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; }
|
|
|
|
|
|
|
+ if (detail::select_read(sock, timeout_sec, timeout_usec) > 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
case SSL_ERROR_WANT_WRITE:
|
|
case SSL_ERROR_WANT_WRITE:
|
|
|
- if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; }
|
|
|
|
|
|
|
+ if (detail::select_write(sock, timeout_sec, timeout_usec) > 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
break;
|
|
break;
|
|
|
default: break;
|
|
default: break;
|
|
|
}
|
|
}
|
|
@@ -13277,8 +13313,8 @@ inline bool tls_is_peer_closed(tls_session_t session, socket_t sock) {
|
|
|
if (!session) return true;
|
|
if (!session) return true;
|
|
|
|
|
|
|
|
// Temporarily set socket to non-blocking to avoid blocking on SSL_peek
|
|
// Temporarily set socket to non-blocking to avoid blocking on SSL_peek
|
|
|
- set_nonblocking(sock, true);
|
|
|
|
|
- auto se = scope_exit([&]() { set_nonblocking(sock, false); });
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, true);
|
|
|
|
|
+ auto se = detail::scope_exit([&]() { detail::set_nonblocking(sock, false); });
|
|
|
|
|
|
|
|
auto ssl = static_cast<SSL *>(session);
|
|
auto ssl = static_cast<SSL *>(session);
|
|
|
char buf;
|
|
char buf;
|
|
@@ -13876,12 +13912,11 @@ inline tls_ctx_t create_client_context_from_x509(X509 *cert, EVP_PKEY *key,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // namespace tls
|
|
} // namespace tls
|
|
|
-} // namespace detail
|
|
|
|
|
|
|
|
|
|
// ClientImpl::set_ca_cert_store - defined here to use tls::x509_store_to_pem
|
|
// ClientImpl::set_ca_cert_store - defined here to use tls::x509_store_to_pem
|
|
|
inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
|
inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
|
|
|
if (ca_cert_store && ca_cert_store != ca_cert_store_) {
|
|
if (ca_cert_store && ca_cert_store != ca_cert_store_) {
|
|
|
- ca_cert_pem_ = detail::tls::x509_store_to_pem(ca_cert_store);
|
|
|
|
|
|
|
+ ca_cert_pem_ = tls::x509_store_to_pem(ca_cert_store);
|
|
|
ca_cert_store_ = ca_cert_store;
|
|
ca_cert_store_ = ca_cert_store;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -13916,19 +13951,19 @@ inline bool SSLClient::check_host_name(const char *pattern,
|
|
|
|
|
|
|
|
inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key,
|
|
inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key,
|
|
|
X509_STORE *client_ca_cert_store) {
|
|
X509_STORE *client_ca_cert_store) {
|
|
|
- ctx_ = detail::tls::create_server_context_from_x509(
|
|
|
|
|
|
|
+ ctx_ = tls::create_server_context_from_x509(
|
|
|
cert, private_key, client_ca_cert_store, last_ssl_error_);
|
|
cert, private_key, client_ca_cert_store, last_ssl_error_);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline SSLServer::SSLServer(
|
|
inline SSLServer::SSLServer(
|
|
|
const std::function<bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback) {
|
|
const std::function<bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback) {
|
|
|
// Use abstract API to create context
|
|
// Use abstract API to create context
|
|
|
- ctx_ = detail::tls::tls_create_server_context();
|
|
|
|
|
|
|
+ ctx_ = tls::tls_create_server_context();
|
|
|
if (ctx_) {
|
|
if (ctx_) {
|
|
|
// Pass to OpenSSL-specific callback (ctx_ is SSL_CTX* internally)
|
|
// Pass to OpenSSL-specific callback (ctx_ is SSL_CTX* internally)
|
|
|
auto ssl_ctx = static_cast<SSL_CTX *>(ctx_);
|
|
auto ssl_ctx = static_cast<SSL_CTX *>(ctx_);
|
|
|
if (!setup_ssl_ctx_callback(*ssl_ctx)) {
|
|
if (!setup_ssl_ctx_callback(*ssl_ctx)) {
|
|
|
- detail::tls::tls_free_context(ctx_);
|
|
|
|
|
|
|
+ tls::tls_free_context(ctx_);
|
|
|
ctx_ = nullptr;
|
|
ctx_ = nullptr;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -13941,8 +13976,8 @@ inline SSL_CTX *SSLServer::ssl_context() const {
|
|
|
inline void SSLServer::update_certs(X509 *cert, EVP_PKEY *private_key,
|
|
inline void SSLServer::update_certs(X509 *cert, EVP_PKEY *private_key,
|
|
|
X509_STORE *client_ca_cert_store) {
|
|
X509_STORE *client_ca_cert_store) {
|
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
|
- detail::tls::update_server_certs_from_x509(ctx_, cert, private_key,
|
|
|
|
|
- client_ca_cert_store);
|
|
|
|
|
|
|
+ tls::update_server_certs_from_x509(ctx_, cert, private_key,
|
|
|
|
|
+ client_ca_cert_store);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// SSL HTTP client implementation
|
|
// SSL HTTP client implementation
|
|
@@ -13957,7 +13992,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
const std::string &client_key_path,
|
|
const std::string &client_key_path,
|
|
|
const std::string &private_key_password)
|
|
const std::string &private_key_password)
|
|
|
: ClientImpl(host, port, client_cert_path, client_key_path) {
|
|
: ClientImpl(host, port, client_cert_path, client_key_path) {
|
|
|
- ctx_ = detail::tls::tls_create_client_context();
|
|
|
|
|
|
|
+ ctx_ = tls::tls_create_client_context();
|
|
|
|
|
|
|
|
// TODO: Add tls_set_min_protocol_version() to TLS abstraction API
|
|
// TODO: Add tls_set_min_protocol_version() to TLS abstraction API
|
|
|
// SSL_CTX_set_min_proto_version(ctx_, TLS1_2_VERSION);
|
|
// SSL_CTX_set_min_proto_version(ctx_, TLS1_2_VERSION);
|
|
@@ -13970,11 +14005,10 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
if (!client_cert_path.empty() && !client_key_path.empty()) {
|
|
if (!client_cert_path.empty() && !client_key_path.empty()) {
|
|
|
const char *password =
|
|
const char *password =
|
|
|
private_key_password.empty() ? nullptr : private_key_password.c_str();
|
|
private_key_password.empty() ? nullptr : private_key_password.c_str();
|
|
|
- if (!detail::tls::tls_set_client_cert_file(ctx_, client_cert_path.c_str(),
|
|
|
|
|
- client_key_path.c_str(),
|
|
|
|
|
- password)) {
|
|
|
|
|
|
|
+ if (!tls::tls_set_client_cert_file(ctx_, client_cert_path.c_str(),
|
|
|
|
|
+ client_key_path.c_str(), password)) {
|
|
|
last_backend_error_ = ERR_get_error();
|
|
last_backend_error_ = ERR_get_error();
|
|
|
- detail::tls::tls_free_context(ctx_);
|
|
|
|
|
|
|
+ tls::tls_free_context(ctx_);
|
|
|
ctx_ = nullptr;
|
|
ctx_ = nullptr;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -13986,8 +14020,8 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
: ClientImpl(host, port) {
|
|
: ClientImpl(host, port) {
|
|
|
const char *password =
|
|
const char *password =
|
|
|
private_key_password.empty() ? nullptr : private_key_password.c_str();
|
|
private_key_password.empty() ? nullptr : private_key_password.c_str();
|
|
|
- ctx_ = detail::tls::create_client_context_from_x509(
|
|
|
|
|
- client_cert, client_key, password, last_backend_error_);
|
|
|
|
|
|
|
+ ctx_ = tls::create_client_context_from_x509(client_cert, client_key, password,
|
|
|
|
|
+ last_backend_error_);
|
|
|
detail::split(&host_[0], &host_[host_.size()], '.',
|
|
detail::split(&host_[0], &host_[host_.size()], '.',
|
|
|
[&](const char *b, const char *e) {
|
|
[&](const char *b, const char *e) {
|
|
|
host_components_.emplace_back(b, e);
|
|
host_components_.emplace_back(b, e);
|
|
@@ -13997,7 +14031,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
inline SSLClient::SSLClient(const std::string &host, int port,
|
|
inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
const PemMemory &pem)
|
|
const PemMemory &pem)
|
|
|
: ClientImpl(host, port) {
|
|
: ClientImpl(host, port) {
|
|
|
- ctx_ = detail::tls::tls_create_client_context();
|
|
|
|
|
|
|
+ ctx_ = tls::tls_create_client_context();
|
|
|
|
|
|
|
|
detail::split(&host_[0], &host_[host_.size()], '.',
|
|
detail::split(&host_[0], &host_[host_.size()], '.',
|
|
|
[&](const char *b, const char *e) {
|
|
[&](const char *b, const char *e) {
|
|
@@ -14005,10 +14039,10 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
if (ctx_ && pem.cert_pem && pem.key_pem) {
|
|
if (ctx_ && pem.cert_pem && pem.key_pem) {
|
|
|
- if (!detail::tls::tls_set_client_cert_pem(ctx_, pem.cert_pem, pem.key_pem,
|
|
|
|
|
- pem.private_key_password)) {
|
|
|
|
|
- last_backend_error_ = detail::tls::tls_get_error();
|
|
|
|
|
- detail::tls::tls_free_context(ctx_);
|
|
|
|
|
|
|
+ if (!tls::tls_set_client_cert_pem(ctx_, pem.cert_pem, pem.key_pem,
|
|
|
|
|
+ pem.private_key_password)) {
|
|
|
|
|
+ last_backend_error_ = tls::tls_get_error();
|
|
|
|
|
+ tls::tls_free_context(ctx_);
|
|
|
ctx_ = nullptr;
|
|
ctx_ = nullptr;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -14017,24 +14051,23 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
inline void SSLClient::set_ca_cert_store(void *ca_cert_store) {
|
|
inline void SSLClient::set_ca_cert_store(void *ca_cert_store) {
|
|
|
if (ca_cert_store && ctx_) {
|
|
if (ca_cert_store && ctx_) {
|
|
|
// tls_set_ca_store takes ownership of ca_cert_store
|
|
// tls_set_ca_store takes ownership of ca_cert_store
|
|
|
- detail::tls::tls_set_ca_store(ctx_, ca_cert_store);
|
|
|
|
|
|
|
+ tls::tls_set_ca_store(ctx_, ca_cert_store);
|
|
|
} else if (ca_cert_store) {
|
|
} else if (ca_cert_store) {
|
|
|
- detail::tls::tls_free_ca_store(ca_cert_store);
|
|
|
|
|
|
|
+ tls::tls_free_ca_store(ca_cert_store);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void SSLClient::load_ca_cert_store(const char *ca_cert,
|
|
inline void SSLClient::load_ca_cert_store(const char *ca_cert,
|
|
|
std::size_t size) {
|
|
std::size_t size) {
|
|
|
ca_cert_pem_.assign(ca_cert, size); // Store for redirect transfer
|
|
ca_cert_pem_.assign(ca_cert, size); // Store for redirect transfer
|
|
|
- set_ca_cert_store(detail::tls::tls_create_ca_store(ca_cert, size));
|
|
|
|
|
|
|
+ set_ca_cert_store(tls::tls_create_ca_store(ca_cert, size));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
inline void
|
|
|
SSLClient::set_server_certificate_verifier(TlsVerifyCallback verifier) {
|
|
SSLClient::set_server_certificate_verifier(TlsVerifyCallback verifier) {
|
|
|
if (!ctx_) { return; }
|
|
if (!ctx_) { return; }
|
|
|
- detail::tls::tls_set_verify_callback(
|
|
|
|
|
- ctx_, [verifier](detail::tls::tls_session_t session,
|
|
|
|
|
- detail::tls::tls_cert_t cert) {
|
|
|
|
|
|
|
+ tls::tls_set_verify_callback(
|
|
|
|
|
+ ctx_, [verifier](tls::tls_session_t session, tls::tls_cert_t cert) {
|
|
|
return verifier(session, cert);
|
|
return verifier(session, cert);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
@@ -14054,18 +14087,18 @@ inline bool SSLClient::load_certs() {
|
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
|
|
|
|
|
|
if (!ca_cert_file_path_.empty()) {
|
|
if (!ca_cert_file_path_.empty()) {
|
|
|
- if (!detail::tls::tls_load_ca_file(ctx_, ca_cert_file_path_.c_str())) {
|
|
|
|
|
|
|
+ if (!tls::tls_load_ca_file(ctx_, ca_cert_file_path_.c_str())) {
|
|
|
last_backend_error_ = ERR_get_error();
|
|
last_backend_error_ = ERR_get_error();
|
|
|
ret = false;
|
|
ret = false;
|
|
|
}
|
|
}
|
|
|
} else if (!ca_cert_dir_path_.empty()) {
|
|
} else if (!ca_cert_dir_path_.empty()) {
|
|
|
- if (!detail::tls::tls_load_ca_dir(ctx_, ca_cert_dir_path_.c_str())) {
|
|
|
|
|
|
|
+ if (!tls::tls_load_ca_dir(ctx_, ca_cert_dir_path_.c_str())) {
|
|
|
last_backend_error_ = ERR_get_error();
|
|
last_backend_error_ = ERR_get_error();
|
|
|
ret = false;
|
|
ret = false;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
// Load system certificates
|
|
// Load system certificates
|
|
|
- if (!detail::tls::tls_load_system_certs(ctx_)) {
|
|
|
|
|
|
|
+ if (!tls::tls_load_system_certs(ctx_)) {
|
|
|
last_backend_error_ = ERR_get_error();
|
|
last_backend_error_ = ERR_get_error();
|
|
|
// Ignore error and continue - some systems may not have certs
|
|
// Ignore error and continue - some systems may not have certs
|
|
|
}
|
|
}
|
|
@@ -14076,7 +14109,7 @@ inline bool SSLClient::load_certs() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|
inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
|
|
|
|
|
// Load CA certificates if server verification is enabled
|
|
// Load CA certificates if server verification is enabled
|
|
|
if (server_certificate_verification_) {
|
|
if (server_certificate_verification_) {
|
|
@@ -14292,7 +14325,6 @@ inline bool SSLClient::verify_host_with_common_name(X509 *server_cert) const {
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
|
|
#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
|
|
|
-namespace detail {
|
|
|
|
|
namespace crypto {
|
|
namespace crypto {
|
|
|
|
|
|
|
|
inline size_t hash_size(HashAlgorithm algo) {
|
|
inline size_t hash_size(HashAlgorithm algo) {
|
|
@@ -14383,42 +14415,6 @@ inline std::string hash(HashAlgorithm algo, const std::string &data) {
|
|
|
|
|
|
|
|
namespace tls {
|
|
namespace tls {
|
|
|
|
|
|
|
|
-// Mbed TLS context wrapper (holds config, entropy, DRBG, CA chain, own
|
|
|
|
|
-// cert/key)
|
|
|
|
|
-struct MbedTlsContext {
|
|
|
|
|
- mbedtls_ssl_config conf;
|
|
|
|
|
- mbedtls_entropy_context entropy;
|
|
|
|
|
- mbedtls_ctr_drbg_context ctr_drbg;
|
|
|
|
|
- mbedtls_x509_crt ca_chain;
|
|
|
|
|
- mbedtls_x509_crt own_cert;
|
|
|
|
|
- mbedtls_pk_context own_key;
|
|
|
|
|
- bool is_server = false;
|
|
|
|
|
- bool verify_client = false;
|
|
|
|
|
- bool has_verify_callback = false;
|
|
|
|
|
-
|
|
|
|
|
- MbedTlsContext() {
|
|
|
|
|
- mbedtls_ssl_config_init(&conf);
|
|
|
|
|
- mbedtls_entropy_init(&entropy);
|
|
|
|
|
- mbedtls_ctr_drbg_init(&ctr_drbg);
|
|
|
|
|
- mbedtls_x509_crt_init(&ca_chain);
|
|
|
|
|
- mbedtls_x509_crt_init(&own_cert);
|
|
|
|
|
- mbedtls_pk_init(&own_key);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- ~MbedTlsContext() {
|
|
|
|
|
- mbedtls_pk_free(&own_key);
|
|
|
|
|
- mbedtls_x509_crt_free(&own_cert);
|
|
|
|
|
- mbedtls_x509_crt_free(&ca_chain);
|
|
|
|
|
- mbedtls_ctr_drbg_free(&ctr_drbg);
|
|
|
|
|
- mbedtls_entropy_free(&entropy);
|
|
|
|
|
- mbedtls_ssl_config_free(&conf);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Non-copyable
|
|
|
|
|
- MbedTlsContext(const MbedTlsContext &) = delete;
|
|
|
|
|
- MbedTlsContext &operator=(const MbedTlsContext &) = delete;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
// Mbed TLS session wrapper
|
|
// Mbed TLS session wrapper
|
|
|
struct MbedTlsSession {
|
|
struct MbedTlsSession {
|
|
|
mbedtls_ssl_context ssl;
|
|
mbedtls_ssl_context ssl;
|
|
@@ -14519,7 +14515,7 @@ inline int mbedtls_net_recv_cb(void *ctx, unsigned char *buf, size_t len) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline tls_ctx_t tls_create_client_context() {
|
|
inline tls_ctx_t tls_create_client_context() {
|
|
|
- auto ctx = new (std::nothrow) MbedTlsContext();
|
|
|
|
|
|
|
+ auto ctx = new (std::nothrow) httplib::MbedTlsContext();
|
|
|
if (!ctx) { return nullptr; }
|
|
if (!ctx) { return nullptr; }
|
|
|
|
|
|
|
|
ctx->is_server = false;
|
|
ctx->is_server = false;
|
|
@@ -14567,7 +14563,7 @@ inline int mbedtls_sni_callback(void *p_ctx, mbedtls_ssl_context *ssl,
|
|
|
const unsigned char *name, size_t name_len);
|
|
const unsigned char *name, size_t name_len);
|
|
|
|
|
|
|
|
inline tls_ctx_t tls_create_server_context() {
|
|
inline tls_ctx_t tls_create_server_context() {
|
|
|
- auto ctx = new (std::nothrow) MbedTlsContext();
|
|
|
|
|
|
|
+ auto ctx = new (std::nothrow) httplib::MbedTlsContext();
|
|
|
if (!ctx) { return nullptr; }
|
|
if (!ctx) { return nullptr; }
|
|
|
|
|
|
|
|
ctx->is_server = true;
|
|
ctx->is_server = true;
|
|
@@ -14614,12 +14610,12 @@ inline tls_ctx_t tls_create_server_context() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void tls_free_context(tls_ctx_t ctx) {
|
|
inline void tls_free_context(tls_ctx_t ctx) {
|
|
|
- if (ctx) { delete static_cast<MbedTlsContext *>(ctx); }
|
|
|
|
|
|
|
+ if (ctx) { delete static_cast<httplib::MbedTlsContext *>(ctx); }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool tls_set_min_version(tls_ctx_t ctx, int version) {
|
|
inline bool tls_set_min_version(tls_ctx_t ctx, int version) {
|
|
|
if (!ctx) { return false; }
|
|
if (!ctx) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Map OpenSSL-style version constants to Mbed TLS
|
|
// Map OpenSSL-style version constants to Mbed TLS
|
|
|
// TLS1_2_VERSION = 0x0303, TLS1_3_VERSION = 0x0304
|
|
// TLS1_2_VERSION = 0x0303, TLS1_3_VERSION = 0x0304
|
|
@@ -14650,7 +14646,7 @@ inline bool tls_set_min_version(tls_ctx_t ctx, int version) {
|
|
|
|
|
|
|
|
inline bool tls_load_ca_pem(tls_ctx_t ctx, const char *pem, size_t len) {
|
|
inline bool tls_load_ca_pem(tls_ctx_t ctx, const char *pem, size_t len) {
|
|
|
if (!ctx || !pem) { return false; }
|
|
if (!ctx || !pem) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// mbedtls_x509_crt_parse expects null-terminated string for PEM
|
|
// mbedtls_x509_crt_parse expects null-terminated string for PEM
|
|
|
// Add null terminator if not present
|
|
// Add null terminator if not present
|
|
@@ -14669,7 +14665,7 @@ inline bool tls_load_ca_pem(tls_ctx_t ctx, const char *pem, size_t len) {
|
|
|
|
|
|
|
|
inline bool tls_load_ca_file(tls_ctx_t ctx, const char *file_path) {
|
|
inline bool tls_load_ca_file(tls_ctx_t ctx, const char *file_path) {
|
|
|
if (!ctx || !file_path) { return false; }
|
|
if (!ctx || !file_path) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
int ret = mbedtls_x509_crt_parse_file(&mctx->ca_chain, file_path);
|
|
int ret = mbedtls_x509_crt_parse_file(&mctx->ca_chain, file_path);
|
|
|
if (ret != 0) {
|
|
if (ret != 0) {
|
|
@@ -14683,7 +14679,7 @@ inline bool tls_load_ca_file(tls_ctx_t ctx, const char *file_path) {
|
|
|
|
|
|
|
|
inline bool tls_load_ca_dir(tls_ctx_t ctx, const char *dir_path) {
|
|
inline bool tls_load_ca_dir(tls_ctx_t ctx, const char *dir_path) {
|
|
|
if (!ctx || !dir_path) { return false; }
|
|
if (!ctx || !dir_path) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
int ret = mbedtls_x509_crt_parse_path(&mctx->ca_chain, dir_path);
|
|
int ret = mbedtls_x509_crt_parse_path(&mctx->ca_chain, dir_path);
|
|
|
if (ret < 0) { // Returns number of certs on success, negative on error
|
|
if (ret < 0) { // Returns number of certs on success, negative on error
|
|
@@ -14697,7 +14693,7 @@ inline bool tls_load_ca_dir(tls_ctx_t ctx, const char *dir_path) {
|
|
|
|
|
|
|
|
inline bool tls_load_system_certs(tls_ctx_t ctx) {
|
|
inline bool tls_load_system_certs(tls_ctx_t ctx) {
|
|
|
if (!ctx) { return false; }
|
|
if (!ctx) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
bool loaded = false;
|
|
bool loaded = false;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
#ifdef _WIN32
|
|
@@ -14776,7 +14772,7 @@ inline bool tls_load_system_certs(tls_ctx_t ctx) {
|
|
|
inline bool tls_set_client_cert_pem(tls_ctx_t ctx, const char *cert,
|
|
inline bool tls_set_client_cert_pem(tls_ctx_t ctx, const char *cert,
|
|
|
const char *key, const char *password) {
|
|
const char *key, const char *password) {
|
|
|
if (!ctx || !cert || !key) { return false; }
|
|
if (!ctx || !cert || !key) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Parse certificate
|
|
// Parse certificate
|
|
|
std::string cert_str(cert);
|
|
std::string cert_str(cert);
|
|
@@ -14823,7 +14819,7 @@ inline bool tls_set_client_cert_file(tls_ctx_t ctx, const char *cert_path,
|
|
|
const char *key_path,
|
|
const char *key_path,
|
|
|
const char *password) {
|
|
const char *password) {
|
|
|
if (!ctx || !cert_path || !key_path) { return false; }
|
|
if (!ctx || !cert_path || !key_path) { return false; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Parse certificate file
|
|
// Parse certificate file
|
|
|
int ret = mbedtls_x509_crt_parse_file(&mctx->own_cert, cert_path);
|
|
int ret = mbedtls_x509_crt_parse_file(&mctx->own_cert, cert_path);
|
|
@@ -14883,7 +14879,7 @@ inline bool tls_set_client_ca_file(tls_ctx_t ctx, const char *ca_file,
|
|
|
|
|
|
|
|
inline void tls_set_verify_client(tls_ctx_t ctx, bool require) {
|
|
inline void tls_set_verify_client(tls_ctx_t ctx, bool require) {
|
|
|
if (!ctx) { return; }
|
|
if (!ctx) { return; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
mctx->verify_client = require;
|
|
mctx->verify_client = require;
|
|
|
if (require) {
|
|
if (require) {
|
|
|
mbedtls_ssl_conf_authmode(&mctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
|
mbedtls_ssl_conf_authmode(&mctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
|
@@ -14923,7 +14919,7 @@ inline int mbedtls_sni_callback(void *p_ctx, mbedtls_ssl_context *ssl,
|
|
|
|
|
|
|
|
inline tls_session_t tls_create_session(tls_ctx_t ctx, socket_t sock) {
|
|
inline tls_session_t tls_create_session(tls_ctx_t ctx, socket_t sock) {
|
|
|
if (!ctx || sock == INVALID_SOCKET) { return nullptr; }
|
|
if (!ctx || sock == INVALID_SOCKET) { return nullptr; }
|
|
|
- auto mctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto mctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
auto session = new (std::nothrow) MbedTlsSession();
|
|
auto session = new (std::nothrow) MbedTlsSession();
|
|
|
if (!session) { return nullptr; }
|
|
if (!session) { return nullptr; }
|
|
@@ -15013,15 +15009,20 @@ inline bool tls_connect_nonblocking(tls_session_t session, socket_t sock,
|
|
|
auto msession = static_cast<MbedTlsSession *>(session);
|
|
auto msession = static_cast<MbedTlsSession *>(session);
|
|
|
|
|
|
|
|
// Set socket to non-blocking mode
|
|
// Set socket to non-blocking mode
|
|
|
- set_nonblocking(sock, true);
|
|
|
|
|
- auto cleanup = scope_exit([&]() { set_nonblocking(sock, false); });
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, true);
|
|
|
|
|
+ auto cleanup =
|
|
|
|
|
+ detail::scope_exit([&]() { detail::set_nonblocking(sock, false); });
|
|
|
|
|
|
|
|
int ret;
|
|
int ret;
|
|
|
while ((ret = mbedtls_ssl_handshake(&msession->ssl)) != 0) {
|
|
while ((ret = mbedtls_ssl_handshake(&msession->ssl)) != 0) {
|
|
|
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
|
|
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
|
|
|
- if (select_read(sock, timeout_sec, timeout_usec) > 0) { continue; }
|
|
|
|
|
|
|
+ if (detail::select_read(sock, timeout_sec, timeout_usec) > 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
} else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
|
} else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
|
|
- if (select_write(sock, timeout_sec, timeout_usec) > 0) { continue; }
|
|
|
|
|
|
|
+ if (detail::select_write(sock, timeout_sec, timeout_usec) > 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Error or timeout
|
|
// Error or timeout
|
|
@@ -15142,8 +15143,9 @@ inline bool tls_is_peer_closed(tls_session_t session, socket_t sock) {
|
|
|
if (mbedtls_ssl_get_bytes_avail(&msession->ssl) > 0) { return false; }
|
|
if (mbedtls_ssl_get_bytes_avail(&msession->ssl) > 0) { return false; }
|
|
|
|
|
|
|
|
// Set socket to non-blocking to avoid blocking on read
|
|
// Set socket to non-blocking to avoid blocking on read
|
|
|
- set_nonblocking(sock, true);
|
|
|
|
|
- auto cleanup = scope_exit([&]() { set_nonblocking(sock, false); });
|
|
|
|
|
|
|
+ detail::set_nonblocking(sock, true);
|
|
|
|
|
+ auto cleanup =
|
|
|
|
|
+ detail::scope_exit([&]() { detail::set_nonblocking(sock, false); });
|
|
|
|
|
|
|
|
// Try a 1-byte read to check connection status
|
|
// Try a 1-byte read to check connection status
|
|
|
// Note: This will consume the byte if data is available, but for the
|
|
// Note: This will consume the byte if data is available, but for the
|
|
@@ -15495,7 +15497,7 @@ inline void tls_free_ca_store(tls_ca_store_t store) {
|
|
|
|
|
|
|
|
inline bool tls_set_ca_store(tls_ctx_t ctx, tls_ca_store_t store) {
|
|
inline bool tls_set_ca_store(tls_ctx_t ctx, tls_ca_store_t store) {
|
|
|
if (!ctx || !store) { return false; }
|
|
if (!ctx || !store) { return false; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
auto *ca_chain = static_cast<mbedtls_x509_crt *>(store);
|
|
auto *ca_chain = static_cast<mbedtls_x509_crt *>(store);
|
|
|
|
|
|
|
|
// Free existing CA chain
|
|
// Free existing CA chain
|
|
@@ -15520,7 +15522,7 @@ inline bool tls_set_ca_store(tls_ctx_t ctx, tls_ca_store_t store) {
|
|
|
inline size_t tls_get_ca_certs(tls_ctx_t ctx, std::vector<tls_cert_t> &certs) {
|
|
inline size_t tls_get_ca_certs(tls_ctx_t ctx, std::vector<tls_cert_t> &certs) {
|
|
|
certs.clear();
|
|
certs.clear();
|
|
|
if (!ctx) { return 0; }
|
|
if (!ctx) { return 0; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Iterate through the CA chain
|
|
// Iterate through the CA chain
|
|
|
mbedtls_x509_crt *cert = &mbed_ctx->ca_chain;
|
|
mbedtls_x509_crt *cert = &mbed_ctx->ca_chain;
|
|
@@ -15543,7 +15545,7 @@ inline size_t tls_get_ca_certs(tls_ctx_t ctx, std::vector<tls_cert_t> &certs) {
|
|
|
inline std::vector<std::string> tls_get_ca_names(tls_ctx_t ctx) {
|
|
inline std::vector<std::string> tls_get_ca_names(tls_ctx_t ctx) {
|
|
|
std::vector<std::string> names;
|
|
std::vector<std::string> names;
|
|
|
if (!ctx) { return names; }
|
|
if (!ctx) { return names; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Iterate through the CA chain
|
|
// Iterate through the CA chain
|
|
|
mbedtls_x509_crt *cert = &mbed_ctx->ca_chain;
|
|
mbedtls_x509_crt *cert = &mbed_ctx->ca_chain;
|
|
@@ -15559,7 +15561,7 @@ inline std::vector<std::string> tls_get_ca_names(tls_ctx_t ctx) {
|
|
|
inline bool tls_update_server_cert(tls_ctx_t ctx, const char *cert_pem,
|
|
inline bool tls_update_server_cert(tls_ctx_t ctx, const char *cert_pem,
|
|
|
const char *key_pem, const char *password) {
|
|
const char *key_pem, const char *password) {
|
|
|
if (!ctx || !cert_pem || !key_pem) { return false; }
|
|
if (!ctx || !cert_pem || !key_pem) { return false; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Free existing certificate and key
|
|
// Free existing certificate and key
|
|
|
mbedtls_x509_crt_free(&mbed_ctx->own_cert);
|
|
mbedtls_x509_crt_free(&mbed_ctx->own_cert);
|
|
@@ -15609,7 +15611,7 @@ inline bool tls_update_server_cert(tls_ctx_t ctx, const char *cert_pem,
|
|
|
|
|
|
|
|
inline bool tls_update_server_client_ca(tls_ctx_t ctx, const char *ca_pem) {
|
|
inline bool tls_update_server_client_ca(tls_ctx_t ctx, const char *ca_pem) {
|
|
|
if (!ctx || !ca_pem) { return false; }
|
|
if (!ctx || !ca_pem) { return false; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
// Free existing CA chain
|
|
// Free existing CA chain
|
|
|
mbedtls_x509_crt_free(&mbed_ctx->ca_chain);
|
|
mbedtls_x509_crt_free(&mbed_ctx->ca_chain);
|
|
@@ -15658,7 +15660,7 @@ inline int mbedtls_verify_callback(void *data, mbedtls_x509_crt *crt, int depth,
|
|
|
|
|
|
|
|
inline bool tls_set_verify_callback(tls_ctx_t ctx, TlsVerifyCallback callback) {
|
|
inline bool tls_set_verify_callback(tls_ctx_t ctx, TlsVerifyCallback callback) {
|
|
|
if (!ctx) { return false; }
|
|
if (!ctx) { return false; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
get_mbedtls_verify_callback() = std::move(callback);
|
|
get_mbedtls_verify_callback() = std::move(callback);
|
|
|
mbed_ctx->has_verify_callback =
|
|
mbed_ctx->has_verify_callback =
|
|
@@ -15724,7 +15726,7 @@ inline int mbedtls_verify_callback_ex(void *data, mbedtls_x509_crt *crt,
|
|
|
inline bool tls_set_verify_callback_ex(tls_ctx_t ctx,
|
|
inline bool tls_set_verify_callback_ex(tls_ctx_t ctx,
|
|
|
TlsVerifyCallbackEx callback) {
|
|
TlsVerifyCallbackEx callback) {
|
|
|
if (!ctx) { return false; }
|
|
if (!ctx) { return false; }
|
|
|
- auto *mbed_ctx = static_cast<MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
+ auto *mbed_ctx = static_cast<httplib::MbedTlsContext *>(ctx);
|
|
|
|
|
|
|
|
get_mbedtls_verify_callback_ex() = std::move(callback);
|
|
get_mbedtls_verify_callback_ex() = std::move(callback);
|
|
|
mbed_ctx->has_verify_callback =
|
|
mbed_ctx->has_verify_callback =
|
|
@@ -15762,7 +15764,25 @@ inline std::string tls_verify_error_string(long error_code) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // namespace tls
|
|
} // namespace tls
|
|
|
-} // namespace detail
|
|
|
|
|
|
|
+
|
|
|
|
|
+// MbedTlsContext constructor/destructor implementations
|
|
|
|
|
+inline MbedTlsContext::MbedTlsContext() {
|
|
|
|
|
+ mbedtls_ssl_config_init(&conf);
|
|
|
|
|
+ mbedtls_entropy_init(&entropy);
|
|
|
|
|
+ mbedtls_ctr_drbg_init(&ctr_drbg);
|
|
|
|
|
+ mbedtls_x509_crt_init(&ca_chain);
|
|
|
|
|
+ mbedtls_x509_crt_init(&own_cert);
|
|
|
|
|
+ mbedtls_pk_init(&own_key);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+inline MbedTlsContext::~MbedTlsContext() {
|
|
|
|
|
+ mbedtls_pk_free(&own_key);
|
|
|
|
|
+ mbedtls_x509_crt_free(&own_cert);
|
|
|
|
|
+ mbedtls_x509_crt_free(&ca_chain);
|
|
|
|
|
+ mbedtls_ctr_drbg_free(&ctr_drbg);
|
|
|
|
|
+ mbedtls_entropy_free(&entropy);
|
|
|
|
|
+ mbedtls_ssl_config_free(&conf);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
inline SSLClient::SSLClient(const std::string &host)
|
|
inline SSLClient::SSLClient(const std::string &host)
|
|
|
: SSLClient(host, 443, std::string(), std::string()) {}
|
|
: SSLClient(host, 443, std::string(), std::string()) {}
|
|
@@ -15775,7 +15795,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
const std::string &client_key_path,
|
|
const std::string &client_key_path,
|
|
|
const std::string &private_key_password)
|
|
const std::string &private_key_password)
|
|
|
: ClientImpl(host, port, client_cert_path, client_key_path) {
|
|
: ClientImpl(host, port, client_cert_path, client_key_path) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
|
|
|
|
|
ctx_ = tls_create_client_context();
|
|
ctx_ = tls_create_client_context();
|
|
|
if (!ctx_) { return; }
|
|
if (!ctx_) { return; }
|
|
@@ -15803,7 +15823,7 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
inline SSLClient::SSLClient(const std::string &host, int port,
|
|
inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
const PemMemory &pem)
|
|
const PemMemory &pem)
|
|
|
: ClientImpl(host, port) {
|
|
: ClientImpl(host, port) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
|
|
|
|
|
ctx_ = tls_create_client_context();
|
|
ctx_ = tls_create_client_context();
|
|
|
if (!ctx_) { return; }
|
|
if (!ctx_) { return; }
|
|
@@ -15829,9 +15849,9 @@ inline SSLClient::SSLClient(const std::string &host, int port,
|
|
|
inline void SSLClient::set_ca_cert_store(void *ca_cert_store) {
|
|
inline void SSLClient::set_ca_cert_store(void *ca_cert_store) {
|
|
|
if (ca_cert_store && ctx_) {
|
|
if (ca_cert_store && ctx_) {
|
|
|
// tls_set_ca_store takes ownership of ca_cert_store
|
|
// tls_set_ca_store takes ownership of ca_cert_store
|
|
|
- detail::tls::tls_set_ca_store(ctx_, ca_cert_store);
|
|
|
|
|
|
|
+ tls::tls_set_ca_store(ctx_, ca_cert_store);
|
|
|
} else if (ca_cert_store) {
|
|
} else if (ca_cert_store) {
|
|
|
- detail::tls::tls_free_ca_store(ca_cert_store);
|
|
|
|
|
|
|
+ tls::tls_free_ca_store(ca_cert_store);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -15839,22 +15859,21 @@ inline void SSLClient::load_ca_cert_store(const char *ca_cert,
|
|
|
std::size_t size) {
|
|
std::size_t size) {
|
|
|
if (ctx_ && ca_cert && size > 0) {
|
|
if (ctx_ && ca_cert && size > 0) {
|
|
|
ca_cert_pem_.assign(ca_cert, size); // Store for redirect transfer
|
|
ca_cert_pem_.assign(ca_cert, size); // Store for redirect transfer
|
|
|
- detail::tls::tls_load_ca_pem(ctx_, ca_cert, size);
|
|
|
|
|
|
|
+ tls::tls_load_ca_pem(ctx_, ca_cert, size);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
inline void
|
|
|
SSLClient::set_server_certificate_verifier(TlsVerifyCallback verifier) {
|
|
SSLClient::set_server_certificate_verifier(TlsVerifyCallback verifier) {
|
|
|
if (!ctx_) { return; }
|
|
if (!ctx_) { return; }
|
|
|
- detail::tls::tls_set_verify_callback(
|
|
|
|
|
- ctx_, [verifier](detail::tls::tls_session_t session,
|
|
|
|
|
- detail::tls::tls_cert_t cert) {
|
|
|
|
|
|
|
+ tls::tls_set_verify_callback(
|
|
|
|
|
+ ctx_, [verifier](tls::tls_session_t session, tls::tls_cert_t cert) {
|
|
|
return verifier(session, cert);
|
|
return verifier(session, cert);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|
inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
|
|
|
|
|
// Load system certificates if no CA certs were explicitly set
|
|
// Load system certificates if no CA certs were explicitly set
|
|
|
if (ca_cert_file_path_.empty() && ca_cert_dir_path_.empty()) {
|
|
if (ca_cert_file_path_.empty() && ca_cert_dir_path_.empty()) {
|
|
@@ -15969,8 +15988,8 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
|
|
|
inline ClientConnection::~ClientConnection() {
|
|
inline ClientConnection::~ClientConnection() {
|
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
|
|
if (session) {
|
|
if (session) {
|
|
|
- detail::tls::tls_shutdown(session, true);
|
|
|
|
|
- detail::tls::tls_free_session(session);
|
|
|
|
|
|
|
+ tls::tls_shutdown(session, true);
|
|
|
|
|
+ tls::tls_free_session(session);
|
|
|
session = nullptr;
|
|
session = nullptr;
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
@@ -16160,7 +16179,7 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
|
|
|
const char *client_ca_cert_file_path,
|
|
const char *client_ca_cert_file_path,
|
|
|
const char *client_ca_cert_dir_path,
|
|
const char *client_ca_cert_dir_path,
|
|
|
const char *private_key_password) {
|
|
const char *private_key_password) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
|
|
|
|
|
ctx_ = tls_create_server_context();
|
|
ctx_ = tls_create_server_context();
|
|
|
if (!ctx_) { return; }
|
|
if (!ctx_) { return; }
|
|
@@ -16189,7 +16208,7 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline SSLServer::SSLServer(const PemMemory &pem) {
|
|
inline SSLServer::SSLServer(const PemMemory &pem) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
ctx_ = tls_create_server_context();
|
|
ctx_ = tls_create_server_context();
|
|
|
if (ctx_) {
|
|
if (ctx_) {
|
|
|
if (!tls_set_server_cert_pem(ctx_, pem.cert_pem, pem.key_pem,
|
|
if (!tls_set_server_cert_pem(ctx_, pem.cert_pem, pem.key_pem,
|
|
@@ -16211,7 +16230,7 @@ inline SSLServer::SSLServer(const PemMemory &pem) {
|
|
|
|
|
|
|
|
inline SSLServer::SSLServer(
|
|
inline SSLServer::SSLServer(
|
|
|
const std::function<bool(void *ctx)> &setup_callback) {
|
|
const std::function<bool(void *ctx)> &setup_callback) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
ctx_ = tls_create_server_context();
|
|
ctx_ = tls_create_server_context();
|
|
|
if (ctx_) {
|
|
if (ctx_) {
|
|
|
if (!setup_callback(ctx_)) {
|
|
if (!setup_callback(ctx_)) {
|
|
@@ -16222,13 +16241,13 @@ inline SSLServer::SSLServer(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline SSLServer::~SSLServer() {
|
|
inline SSLServer::~SSLServer() {
|
|
|
- if (ctx_) { detail::tls::tls_free_context(ctx_); }
|
|
|
|
|
|
|
+ if (ctx_) { tls::tls_free_context(ctx_); }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool SSLServer::is_valid() const { return ctx_ != nullptr; }
|
|
inline bool SSLServer::is_valid() const { return ctx_ != nullptr; }
|
|
|
|
|
|
|
|
inline bool SSLServer::process_and_close_socket(socket_t sock) {
|
|
inline bool SSLServer::process_and_close_socket(socket_t sock) {
|
|
|
- using namespace detail::tls;
|
|
|
|
|
|
|
+ using namespace tls;
|
|
|
|
|
|
|
|
// Create TLS session with mutex protection
|
|
// Create TLS session with mutex protection
|
|
|
tls_session_t session = nullptr;
|
|
tls_session_t session = nullptr;
|
|
@@ -16298,7 +16317,7 @@ inline bool SSLServer::process_and_close_socket(socket_t sock) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline SSLClient::~SSLClient() {
|
|
inline SSLClient::~SSLClient() {
|
|
|
- if (ctx_) { detail::tls::tls_free_context(ctx_); }
|
|
|
|
|
|
|
+ if (ctx_) { tls::tls_free_context(ctx_); }
|
|
|
// Make sure to shut down SSL since shutdown_ssl will resolve to the
|
|
// Make sure to shut down SSL since shutdown_ssl will resolve to the
|
|
|
// base function rather than the derived function once we get to the
|
|
// base function rather than the derived function once we get to the
|
|
|
// base class destructor, and won't free the SSL (causing a leak).
|
|
// base class destructor, and won't free the SSL (causing a leak).
|
|
@@ -16318,10 +16337,10 @@ inline void SSLClient::shutdown_ssl_impl(Socket &socket,
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (socket.ssl) {
|
|
if (socket.ssl) {
|
|
|
- detail::tls::tls_shutdown(socket.ssl, shutdown_gracefully);
|
|
|
|
|
|
|
+ tls::tls_shutdown(socket.ssl, shutdown_gracefully);
|
|
|
{
|
|
{
|
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
|
- detail::tls::tls_free_session(socket.ssl);
|
|
|
|
|
|
|
+ tls::tls_free_session(socket.ssl);
|
|
|
}
|
|
}
|
|
|
socket.ssl = nullptr;
|
|
socket.ssl = nullptr;
|
|
|
}
|
|
}
|
|
@@ -16452,13 +16471,13 @@ inline bool SSLServer::update_certs_pem(const char *cert_pem,
|
|
|
const char *password) {
|
|
const char *password) {
|
|
|
if (!ctx_) { return false; }
|
|
if (!ctx_) { return false; }
|
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
|
- return detail::tls::tls_update_server_cert(ctx_, cert_pem, key_pem, password);
|
|
|
|
|
|
|
+ return tls::tls_update_server_cert(ctx_, cert_pem, key_pem, password);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline bool SSLServer::update_client_ca_pem(const char *ca_pem) {
|
|
inline bool SSLServer::update_client_ca_pem(const char *ca_pem) {
|
|
|
if (!ctx_) { return false; }
|
|
if (!ctx_) { return false; }
|
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
|
|
- return detail::tls::tls_update_server_client_ca(ctx_, ca_pem);
|
|
|
|
|
|
|
+ return tls::tls_update_server_client_ca(ctx_, ca_pem);
|
|
|
}
|
|
}
|
|
|
#endif // CPPHTTPLIB_SSL_ENABLED
|
|
#endif // CPPHTTPLIB_SSL_ENABLED
|
|
|
|
|
|
|
@@ -17150,12 +17169,12 @@ inline void Client::set_ca_cert_store(void *ca_cert_store) {
|
|
|
if (is_ssl_) {
|
|
if (is_ssl_) {
|
|
|
static_cast<SSLClient &>(*cli_).set_ca_cert_store(ca_cert_store);
|
|
static_cast<SSLClient &>(*cli_).set_ca_cert_store(ca_cert_store);
|
|
|
} else if (ca_cert_store) {
|
|
} else if (ca_cert_store) {
|
|
|
- detail::tls::tls_free_ca_store(ca_cert_store);
|
|
|
|
|
|
|
+ tls::tls_free_ca_store(ca_cert_store);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) {
|
|
inline void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) {
|
|
|
- set_ca_cert_store(detail::tls::tls_create_ca_store(ca_cert, size));
|
|
|
|
|
|
|
+ set_ca_cert_store(tls::tls_create_ca_store(ca_cert, size));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
inline void
|