aboutsummaryrefslogtreecommitdiffhomepage
path: root/tdnet
diff options
context:
space:
mode:
authorlevlam <levlam@telegram.org>2022-11-11 14:23:43 +0300
committerlevlam <levlam@telegram.org>2022-11-11 14:23:43 +0300
commit28d1dd02e92b58e9fdaf53941112faa40e91968a (patch)
tree24d99023a6ba9e5ae0f34242b6bbbc15b0a94828 /tdnet
parent32456872af2a143779527680bf431c0e4fed234e (diff)
Make SslCtx public.
Diffstat (limited to 'tdnet')
-rw-r--r--tdnet/CMakeLists.txt2
-rw-r--r--tdnet/td/net/GetHostByNameActor.cpp4
-rw-r--r--tdnet/td/net/SslCtx.cpp311
-rw-r--r--tdnet/td/net/SslCtx.h45
-rw-r--r--tdnet/td/net/SslStream.cpp201
-rw-r--r--tdnet/td/net/SslStream.h7
-rw-r--r--tdnet/td/net/Wget.cpp2
-rw-r--r--tdnet/td/net/Wget.h7
8 files changed, 378 insertions, 201 deletions
diff --git a/tdnet/CMakeLists.txt b/tdnet/CMakeLists.txt
index 0673961d6..e14f3500f 100644
--- a/tdnet/CMakeLists.txt
+++ b/tdnet/CMakeLists.txt
@@ -24,6 +24,7 @@ set(TDNET_SOURCE
td/net/HttpQuery.cpp
td/net/HttpReader.cpp
td/net/Socks5.cpp
+ td/net/SslCtx.cpp
td/net/SslStream.cpp
td/net/TcpListener.cpp
td/net/TransparentProxy.cpp
@@ -42,6 +43,7 @@ set(TDNET_SOURCE
td/net/HttpReader.h
td/net/NetStats.h
td/net/Socks5.h
+ td/net/SslCtx.h
td/net/SslStream.h
td/net/TcpListener.h
td/net/TransparentProxy.h
diff --git a/tdnet/td/net/GetHostByNameActor.cpp b/tdnet/td/net/GetHostByNameActor.cpp
index 609b084f6..8a720083c 100644
--- a/tdnet/td/net/GetHostByNameActor.cpp
+++ b/tdnet/td/net/GetHostByNameActor.cpp
@@ -7,7 +7,7 @@
#include "td/net/GetHostByNameActor.h"
#include "td/net/HttpQuery.h"
-#include "td/net/SslStream.h"
+#include "td/net/SslCtx.h"
#include "td/net/Wget.h"
#include "td/utils/common.h"
@@ -51,7 +51,7 @@ class GoogleDnsResolver final : public Actor {
"GoogleDnsResolver", std::move(wget_promise),
PSTRING() << "https://dns.google/resolve?name=" << url_encode(host_) << "&type=" << (prefer_ipv6_ ? 28 : 1),
std::vector<std::pair<string, string>>({{"Host", "dns.google"}}), timeout, ttl, prefer_ipv6_,
- SslStream::VerifyPeer::Off);
+ SslCtx::VerifyPeer::Off);
}
static Result<IPAddress> get_ip_address(Result<unique_ptr<HttpQuery>> r_http_query) {
diff --git a/tdnet/td/net/SslCtx.cpp b/tdnet/td/net/SslCtx.cpp
new file mode 100644
index 000000000..19bdd961a
--- /dev/null
+++ b/tdnet/td/net/SslCtx.cpp
@@ -0,0 +1,311 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include "td/net/SslStream.h"
+
+#include "td/utils/crypto.h"
+#include "td/utils/FlatHashMap.h"
+#include "td/utils/logging.h"
+#include "td/utils/port/wstring_convert.h"
+#include "td/utils/SliceBuilder.h"
+#include "td/utils/Time.h"
+
+#if !TD_EMSCRIPTEN
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include <cstring>
+#include <memory>
+#include <mutex>
+
+#if TD_PORT_WINDOWS
+#include <wincrypt.h>
+#endif
+
+namespace td {
+
+namespace detail {
+namespace {
+int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
+ if (!preverify_ok) {
+ char buf[256];
+ X509_NAME_oneline(X509_get_subject_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256);
+
+ int err = X509_STORE_CTX_get_error(ctx);
+ auto warning = PSTRING() << "verify error:num=" << err << ":" << X509_verify_cert_error_string(err)
+ << ":depth=" << X509_STORE_CTX_get_error_depth(ctx) << ":" << Slice(buf, std::strlen(buf));
+ double now = Time::now();
+
+ static std::mutex warning_mutex;
+ {
+ std::lock_guard<std::mutex> lock(warning_mutex);
+ static FlatHashMap<string, double> next_warning_time;
+ double &next = next_warning_time[warning];
+ if (next <= now) {
+ next = now + 300; // one warning per 5 minutes
+ LOG(WARNING) << warning;
+ }
+ }
+ }
+
+ return preverify_ok;
+}
+
+using SslCtxPtr = std::shared_ptr<SSL_CTX>;
+
+Result<SslCtxPtr> do_create_ssl_ctx(CSlice cert_file, SslCtx::VerifyPeer verify_peer) {
+ auto ssl_method =
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ TLS_client_method();
+#else
+ SSLv23_client_method();
+#endif
+ if (ssl_method == nullptr) {
+ return create_openssl_error(-6, "Failed to create an SSL client method");
+ }
+ auto ssl_ctx = SSL_CTX_new(ssl_method);
+ if (!ssl_ctx) {
+ return create_openssl_error(-7, "Failed to create an SSL context");
+ }
+ auto ssl_ctx_ptr = SslCtxPtr(ssl_ctx, SSL_CTX_free);
+ long options = 0;
+#ifdef SSL_OP_NO_SSLv2
+ options |= SSL_OP_NO_SSLv2;
+#endif
+#ifdef SSL_OP_NO_SSLv3
+ options |= SSL_OP_NO_SSLv3;
+#endif
+ SSL_CTX_set_options(ssl_ctx, options);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION);
+#endif
+ SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+ if (cert_file.empty()) {
+#if TD_PORT_WINDOWS
+ LOG(DEBUG) << "Begin to load system store";
+ auto flags = CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
+ HCERTSTORE system_store =
+ CertOpenStore(CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, HCRYPTPROV_LEGACY(), flags,
+ static_cast<const void *>(to_wstring("ROOT").ok().c_str()));
+
+ if (system_store) {
+ X509_STORE *store = X509_STORE_new();
+
+ for (PCCERT_CONTEXT cert_context = CertEnumCertificatesInStore(system_store, nullptr); cert_context != nullptr;
+ cert_context = CertEnumCertificatesInStore(system_store, cert_context)) {
+ const unsigned char *in = cert_context->pbCertEncoded;
+ X509 *x509 = d2i_X509(nullptr, &in, static_cast<long>(cert_context->cbCertEncoded));
+ if (x509 != nullptr) {
+ if (X509_STORE_add_cert(store, x509) != 1) {
+ auto error_code = ERR_peek_error();
+ auto error = create_openssl_error(-20, "Failed to add certificate");
+ if (ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+ LOG(ERROR) << error;
+ } else {
+ LOG(INFO) << error;
+ }
+ }
+
+ X509_free(x509);
+ } else {
+ LOG(ERROR) << create_openssl_error(-21, "Failed to load X509 certificate");
+ }
+ }
+
+ CertCloseStore(system_store, 0);
+
+ SSL_CTX_set_cert_store(ssl_ctx, store);
+ LOG(DEBUG) << "End to load system store";
+ } else {
+ LOG(ERROR) << create_openssl_error(-22, "Failed to open system certificate store");
+ }
+#else
+ if (SSL_CTX_set_default_verify_paths(ssl_ctx) == 0) {
+ auto error = create_openssl_error(-8, "Failed to load default verify paths");
+ if (verify_peer == SslCtx::VerifyPeer::On) {
+ return std::move(error);
+ } else {
+ LOG(ERROR) << error;
+ }
+ }
+#endif
+ } else {
+ if (SSL_CTX_load_verify_locations(ssl_ctx, cert_file.c_str(), nullptr) == 0) {
+ return create_openssl_error(-8, "Failed to set custom certificate file");
+ }
+ }
+
+ if (verify_peer == SslCtx::VerifyPeer::On) {
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);
+
+ constexpr int DEFAULT_VERIFY_DEPTH = 10;
+ SSL_CTX_set_verify_depth(ssl_ctx, DEFAULT_VERIFY_DEPTH);
+ } else {
+ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, nullptr);
+ }
+
+ string cipher_list;
+ if (SSL_CTX_set_cipher_list(ssl_ctx, cipher_list.empty() ? "DEFAULT" : cipher_list.c_str()) == 0) {
+ return create_openssl_error(-9, PSLICE() << "Failed to set cipher list \"" << cipher_list << '"');
+ }
+
+ return std::move(ssl_ctx_ptr);
+}
+
+Result<SslCtxPtr> get_default_ssl_ctx() {
+ static auto ctx = do_create_ssl_ctx(CSlice(), SslCtx::VerifyPeer::On);
+ if (ctx.is_error()) {
+ return ctx.error().clone();
+ }
+
+ return ctx.ok();
+}
+
+Result<SslCtxPtr> get_default_unverified_ssl_ctx() {
+ static auto ctx = do_create_ssl_ctx(CSlice(), SslCtx::VerifyPeer::Off);
+ if (ctx.is_error()) {
+ return ctx.error().clone();
+ }
+
+ return ctx.ok();
+}
+
+} // namespace
+
+class SslCtxImpl {
+ public:
+ Status init(CSlice cert_file, SslCtx::VerifyPeer verify_peer) {
+ SslCtx::init_openssl();
+
+ clear_openssl_errors("Before SslCtx::init");
+
+ if (cert_file.empty()) {
+ if (verify_peer == SslCtx::VerifyPeer::On) {
+ TRY_RESULT_ASSIGN(ssl_ctx_ptr_, get_default_ssl_ctx());
+ } else {
+ TRY_RESULT_ASSIGN(ssl_ctx_ptr_, get_default_unverified_ssl_ctx());
+ }
+ return Status::OK();
+ }
+
+ auto start_time = Time::now();
+ auto r_ssl_ctx_ptr = do_create_ssl_ctx(cert_file, verify_peer);
+ auto elapsed_time = Time::now() - start_time;
+ if (elapsed_time >= 0.1) {
+ LOG(ERROR) << "SSL context creation took " << elapsed_time << " seconds";
+ }
+ if (r_ssl_ctx_ptr.is_error()) {
+ return r_ssl_ctx_ptr.move_as_error();
+ }
+ ssl_ctx_ptr_ = r_ssl_ctx_ptr.move_as_ok();
+ return Status::OK();
+ }
+
+ void *get_openssl_ctx() const {
+ return static_cast<void *>(ssl_ctx_ptr_.get());
+ }
+
+ private:
+ SslCtxPtr ssl_ctx_ptr_;
+};
+
+} // namespace detail
+
+SslCtx::SslCtx() = default;
+
+SslCtx::SslCtx(const SslCtx &other) {
+ if (other.impl_) {
+ impl_ = make_unique<detail::SslCtxImpl>(*other.impl_);
+ }
+}
+
+SslCtx &SslCtx::operator=(const SslCtx &other) {
+ if (other.impl_) {
+ impl_ = make_unique<detail::SslCtxImpl>(*other.impl_);
+ } else {
+ impl_ = nullptr;
+ }
+ return *this;
+}
+
+SslCtx::SslCtx(SslCtx &&) noexcept = default;
+
+SslCtx &SslCtx::operator=(SslCtx &&) noexcept = default;
+
+SslCtx::~SslCtx() = default;
+
+void SslCtx::init_openssl() {
+ static bool is_inited = [] {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ return OPENSSL_init_ssl(0, nullptr) != 0;
+#else
+ OpenSSL_add_all_algorithms();
+ SSL_load_error_strings();
+ return OpenSSL_add_ssl_algorithms() != 0;
+#endif
+ }();
+ CHECK(is_inited);
+}
+
+Result<SslCtx> SslCtx::create(CSlice cert_file, VerifyPeer verify_peer) {
+ auto impl = make_unique<detail::SslCtxImpl>();
+ TRY_STATUS(impl->init(cert_file, verify_peer));
+ return SslCtx(std::move(impl));
+}
+
+void *SslCtx::get_openssl_ctx() const {
+ return impl_ == nullptr ? nullptr : impl_->get_openssl_ctx();
+}
+
+SslCtx::SslCtx(unique_ptr<detail::SslCtxImpl> impl) : impl_(std::move(impl)) {
+}
+
+} // namespace td
+
+#else
+
+namespace td {
+
+namespace detail {
+class SslCtxImpl {};
+} // namespace detail
+
+SslCtx::SslCtx() = default;
+
+SslCtx::SslCtx(const SslCtx &other) {
+ UNREACHABLE();
+}
+
+SslCtx &SslCtx::operator=(const SslCtx &other) {
+ UNREACHABLE();
+ return *this;
+}
+
+SslCtx::SslCtx(SslCtx &&) noexcept = default;
+
+SslCtx &SslCtx::operator=(SslCtx &&) noexcept = default;
+
+SslCtx::~SslCtx() = default;
+
+void SslCtx::init_openssl() {
+}
+
+Result<SslCtx> SslCtx::create(CSlice cert_file, VerifyPeer verify_peer) {
+ return Status::Error("Not supported in Emscripten");
+}
+
+void *SslCtx::get_openssl_ctx() const {
+ return nullptr;
+}
+
+SslCtx::SslCtx(unique_ptr<detail::SslCtxImpl> impl) : impl_(std::move(impl)) {
+}
+
+} // namespace td
+
+#endif
diff --git a/tdnet/td/net/SslCtx.h b/tdnet/td/net/SslCtx.h
new file mode 100644
index 000000000..5cd55925e
--- /dev/null
+++ b/tdnet/td/net/SslCtx.h
@@ -0,0 +1,45 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#pragma once
+
+#include "td/utils/Slice.h"
+#include "td/utils/Status.h"
+
+namespace td {
+
+namespace detail {
+class SslCtxImpl;
+} // namespace detail
+
+class SslCtx {
+ public:
+ SslCtx();
+ SslCtx(const SslCtx &other);
+ SslCtx &operator=(const SslCtx &other);
+ SslCtx(SslCtx &&) noexcept;
+ SslCtx &operator=(SslCtx &&) noexcept;
+ ~SslCtx();
+
+ static void init_openssl();
+
+ enum class VerifyPeer { On, Off };
+
+ static Result<SslCtx> create(CSlice cert_file, VerifyPeer verify_peer);
+
+ void *get_openssl_ctx() const;
+
+ explicit operator bool() const noexcept {
+ return static_cast<bool>(impl_);
+ }
+
+ private:
+ unique_ptr<detail::SslCtxImpl> impl_;
+
+ explicit SslCtx(unique_ptr<detail::SslCtxImpl> impl);
+};
+
+} // namespace td
diff --git a/tdnet/td/net/SslStream.cpp b/tdnet/td/net/SslStream.cpp
index 2cf402cfa..872bd6225 100644
--- a/tdnet/td/net/SslStream.cpp
+++ b/tdnet/td/net/SslStream.cpp
@@ -9,28 +9,18 @@
#if !TD_EMSCRIPTEN
#include "td/utils/common.h"
#include "td/utils/crypto.h"
-#include "td/utils/FlatHashMap.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/port/IPAddress.h"
-#include "td/utils/port/wstring_convert.h"
-#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/Time.h"
+#include <openssl/bio.h>
#include <openssl/err.h>
-#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
-#include <openssl/x509v3.h>
#include <cstring>
-#include <memory>
-#include <mutex>
-
-#if TD_PORT_WINDOWS
-#include <wincrypt.h>
-#endif
namespace td {
@@ -122,33 +112,6 @@ BIO_METHOD *BIO_s_sslstream() {
return result;
}
-int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
- if (!preverify_ok) {
- char buf[256];
- X509_NAME_oneline(X509_get_subject_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256);
-
- int err = X509_STORE_CTX_get_error(ctx);
- auto warning = PSTRING() << "verify error:num=" << err << ":" << X509_verify_cert_error_string(err)
- << ":depth=" << X509_STORE_CTX_get_error_depth(ctx) << ":" << Slice(buf, std::strlen(buf));
- double now = Time::now();
-
- static std::mutex warning_mutex;
- {
- std::lock_guard<std::mutex> lock(warning_mutex);
- static FlatHashMap<string, double> next_warning_time;
- double &next = next_warning_time[warning];
- if (next <= now) {
- next = now + 300; // one warning per 5 minutes
- LOG(WARNING) << warning;
- }
- }
- }
-
- return preverify_ok;
-}
-
-using SslCtx = std::shared_ptr<SSL_CTX>;
-
struct SslHandleDeleter {
void operator()(SSL *ssl_handle) {
auto start_time = Time::now();
@@ -168,162 +131,18 @@ struct SslHandleDeleter {
using SslHandle = std::unique_ptr<SSL, SslHandleDeleter>;
-Result<SslCtx> do_create_ssl_ctx(CSlice cert_file, SslStream::VerifyPeer verify_peer) {
- auto ssl_method =
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- TLS_client_method();
-#else
- SSLv23_client_method();
-#endif
- if (ssl_method == nullptr) {
- return create_openssl_error(-6, "Failed to create an SSL client method");
- }
- auto ssl_ctx = SSL_CTX_new(ssl_method);
- if (!ssl_ctx) {
- return create_openssl_error(-7, "Failed to create an SSL context");
- }
- auto ssl_ctx_ptr = SslCtx(ssl_ctx, SSL_CTX_free);
- long options = 0;
-#ifdef SSL_OP_NO_SSLv2
- options |= SSL_OP_NO_SSLv2;
-#endif
-#ifdef SSL_OP_NO_SSLv3
- options |= SSL_OP_NO_SSLv3;
-#endif
- SSL_CTX_set_options(ssl_ctx, options);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION);
-#endif
- SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
-
- if (cert_file.empty()) {
-#if TD_PORT_WINDOWS
- LOG(DEBUG) << "Begin to load system store";
- auto flags = CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
- HCERTSTORE system_store =
- CertOpenStore(CERT_STORE_PROV_SYSTEM_W, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, HCRYPTPROV_LEGACY(), flags,
- static_cast<const void *>(to_wstring("ROOT").ok().c_str()));
-
- if (system_store) {
- X509_STORE *store = X509_STORE_new();
-
- for (PCCERT_CONTEXT cert_context = CertEnumCertificatesInStore(system_store, nullptr); cert_context != nullptr;
- cert_context = CertEnumCertificatesInStore(system_store, cert_context)) {
- const unsigned char *in = cert_context->pbCertEncoded;
- X509 *x509 = d2i_X509(nullptr, &in, static_cast<long>(cert_context->cbCertEncoded));
- if (x509 != nullptr) {
- if (X509_STORE_add_cert(store, x509) != 1) {
- auto error_code = ERR_peek_error();
- auto error = create_openssl_error(-20, "Failed to add certificate");
- if (ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
- LOG(ERROR) << error;
- } else {
- LOG(INFO) << error;
- }
- }
-
- X509_free(x509);
- } else {
- LOG(ERROR) << create_openssl_error(-21, "Failed to load X509 certificate");
- }
- }
-
- CertCloseStore(system_store, 0);
-
- SSL_CTX_set_cert_store(ssl_ctx, store);
- LOG(DEBUG) << "End to load system store";
- } else {
- LOG(ERROR) << create_openssl_error(-22, "Failed to open system certificate store");
- }
-#else
- if (SSL_CTX_set_default_verify_paths(ssl_ctx) == 0) {
- auto error = create_openssl_error(-8, "Failed to load default verify paths");
- if (verify_peer == SslStream::VerifyPeer::On) {
- return std::move(error);
- } else {
- LOG(ERROR) << error;
- }
- }
-#endif
- } else {
- if (SSL_CTX_load_verify_locations(ssl_ctx, cert_file.c_str(), nullptr) == 0) {
- return create_openssl_error(-8, "Failed to set custom certificate file");
- }
- }
-
- if (verify_peer == SslStream::VerifyPeer::On) {
- SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);
-
- constexpr int DEFAULT_VERIFY_DEPTH = 10;
- SSL_CTX_set_verify_depth(ssl_ctx, DEFAULT_VERIFY_DEPTH);
- } else {
- SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, nullptr);
- }
-
- string cipher_list;
- if (SSL_CTX_set_cipher_list(ssl_ctx, cipher_list.empty() ? "DEFAULT" : cipher_list.c_str()) == 0) {
- return create_openssl_error(-9, PSLICE() << "Failed to set cipher list \"" << cipher_list << '"');
- }
-
- return std::move(ssl_ctx_ptr);
-}
-
-Result<SslCtx> get_default_ssl_ctx() {
- static auto ctx = do_create_ssl_ctx("", SslStream::VerifyPeer::On);
- if (ctx.is_error()) {
- return ctx.error().clone();
- }
-
- return ctx.ok();
-}
-
-Result<SslCtx> get_default_unverified_ssl_ctx() {
- static auto ctx = do_create_ssl_ctx("", SslStream::VerifyPeer::Off);
- if (ctx.is_error()) {
- return ctx.error().clone();
- }
-
- return ctx.ok();
-}
-
-Result<SslCtx> create_ssl_ctx(CSlice cert_file, SslStream::VerifyPeer verify_peer) {
- if (cert_file.empty()) {
- if (verify_peer == SslStream::VerifyPeer::On) {
- return get_default_ssl_ctx();
- } else {
- return get_default_unverified_ssl_ctx();
- }
- }
- auto start_time = Time::now();
- auto result = do_create_ssl_ctx(cert_file, verify_peer);
- auto elapsed_time = Time::now() - start_time;
- if (elapsed_time >= 0.1) {
- LOG(ERROR) << "SSL context creation took " << elapsed_time << " seconds";
- }
- return result;
-}
-
} // namespace
class SslStreamImpl {
public:
- Status init(CSlice host, CSlice cert_file, SslStream::VerifyPeer verify_peer, bool check_ip_address_as_host) {
- static bool init_openssl = [] {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- return OPENSSL_init_ssl(0, nullptr) != 0;
-#else
- OpenSSL_add_all_algorithms();
- SSL_load_error_strings();
- return OpenSSL_add_ssl_algorithms() != 0;
-#endif
- }();
- CHECK(init_openssl);
+ Status init(CSlice host, CSlice cert_file, SslCtx::VerifyPeer verify_peer, bool check_ip_address_as_host) {
+ SslCtx::init_openssl();
clear_openssl_errors("Before SslFd::init");
- TRY_RESULT(ssl_ctx, create_ssl_ctx(cert_file, verify_peer));
+ TRY_RESULT(ssl_ctx, SslCtx::create(cert_file, verify_peer));
- auto ssl_handle = SslHandle(SSL_new(ssl_ctx.get()));
+ auto ssl_handle = SslHandle(SSL_new(static_cast<SSL_CTX *>(ssl_ctx.get_openssl_ctx())));
if (!ssl_handle) {
return create_openssl_error(-13, "Failed to create an SSL handle");
}
@@ -537,7 +356,7 @@ SslStream::SslStream(SslStream &&) noexcept = default;
SslStream &SslStream::operator=(SslStream &&) noexcept = default;
SslStream::~SslStream() = default;
-Result<SslStream> SslStream::create(CSlice host, CSlice cert_file, VerifyPeer verify_peer,
+Result<SslStream> SslStream::create(CSlice host, CSlice cert_file, SslCtx::VerifyPeer verify_peer,
bool use_ip_address_as_host) {
auto impl = make_unique<detail::SslStreamImpl>();
TRY_STATUS(impl->init(host, cert_file, verify_peer, use_ip_address_as_host));
@@ -569,13 +388,13 @@ class SslStreamImpl {};
} // namespace detail
SslStream::SslStream() = default;
-SslStream::SslStream(SslStream &&) = default;
-SslStream &SslStream::operator=(SslStream &&) = default;
+SslStream::SslStream(SslStream &&) noexcept = default;
+SslStream &SslStream::operator=(SslStream &&) noexcept = default;
SslStream::~SslStream() = default;
-Result<SslStream> SslStream::create(CSlice host, CSlice cert_file, VerifyPeer verify_peer,
+Result<SslStream> SslStream::create(CSlice host, CSlice cert_file, SslCtx::VerifyPeer verify_peer,
bool check_ip_address_as_host) {
- return Status::Error("Not supported in emscripten");
+ return Status::Error("Not supported in Emscripten");
}
SslStream::SslStream(unique_ptr<detail::SslStreamImpl> impl) : impl_(std::move(impl)) {
diff --git a/tdnet/td/net/SslStream.h b/tdnet/td/net/SslStream.h
index 4af0da30e..069fa25d2 100644
--- a/tdnet/td/net/SslStream.h
+++ b/tdnet/td/net/SslStream.h
@@ -6,6 +6,8 @@
//
#pragma once
+#include "td/net/SslCtx.h"
+
#include "td/utils/ByteFlow.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
@@ -23,9 +25,8 @@ class SslStream {
SslStream &operator=(SslStream &&) noexcept;
~SslStream();
- enum class VerifyPeer { On, Off };
-
- static Result<SslStream> create(CSlice host, CSlice cert_file = CSlice(), VerifyPeer verify_peer = VerifyPeer::On,
+ static Result<SslStream> create(CSlice host, CSlice cert_file = CSlice(),
+ SslCtx::VerifyPeer verify_peer = SslCtx::VerifyPeer::On,
bool use_ip_address_as_host = false);
ByteFlowInterface &read_byte_flow();
diff --git a/tdnet/td/net/Wget.cpp b/tdnet/td/net/Wget.cpp
index 8d35bc584..208c3cb94 100644
--- a/tdnet/td/net/Wget.cpp
+++ b/tdnet/td/net/Wget.cpp
@@ -25,7 +25,7 @@
namespace td {
Wget::Wget(Promise<unique_ptr<HttpQuery>> promise, string url, std::vector<std::pair<string, string>> headers,
- int32 timeout_in, int32 ttl, bool prefer_ipv6, SslStream::VerifyPeer verify_peer, string content,
+ int32 timeout_in, int32 ttl, bool prefer_ipv6, SslCtx::VerifyPeer verify_peer, string content,
string content_type)
: promise_(std::move(promise))
, input_url_(std::move(url))
diff --git a/tdnet/td/net/Wget.h b/tdnet/td/net/Wget.h
index 9372b4d58..f3d225982 100644
--- a/tdnet/td/net/Wget.h
+++ b/tdnet/td/net/Wget.h
@@ -8,7 +8,7 @@
#include "td/net/HttpOutboundConnection.h"
#include "td/net/HttpQuery.h"
-#include "td/net/SslStream.h"
+#include "td/net/SslCtx.h"
#include "td/actor/actor.h"
@@ -24,8 +24,7 @@ class Wget final : public HttpOutboundConnection::Callback {
public:
explicit Wget(Promise<unique_ptr<HttpQuery>> promise, string url, std::vector<std::pair<string, string>> headers = {},
int32 timeout_in = 10, int32 ttl = 3, bool prefer_ipv6 = false,
- SslStream::VerifyPeer verify_peer = SslStream::VerifyPeer::On, string content = {},
- string content_type = {});
+ SslCtx::VerifyPeer verify_peer = SslCtx::VerifyPeer::On, string content = {}, string content_type = {});
private:
Status try_init();
@@ -46,7 +45,7 @@ class Wget final : public HttpOutboundConnection::Callback {
int32 timeout_in_;
int32 ttl_;
bool prefer_ipv6_ = false;
- SslStream::VerifyPeer verify_peer_;
+ SslCtx::VerifyPeer verify_peer_;
string content_;
string content_type_;
};