Make SslCtx public.

This commit is contained in:
levlam 2022-11-11 14:23:43 +03:00
parent 32456872af
commit 28d1dd02e9
9 changed files with 380 additions and 203 deletions

View File

@ -35,7 +35,7 @@
#include "td/mtproto/TransportType.h" #include "td/mtproto/TransportType.h"
#if !TD_EMSCRIPTEN //FIXME #if !TD_EMSCRIPTEN //FIXME
#include "td/net/SslStream.h" #include "td/net/SslCtx.h"
#include "td/net/Wget.h" #include "td/net/Wget.h"
#endif #endif
@ -239,7 +239,7 @@ static ActorOwn<> get_simple_config_impl(Promise<SimpleConfigResult> promise, in
return std::move(res); return std::move(res);
}()); }());
}), }),
std::move(url), std::move(headers), timeout, ttl, prefer_ipv6, SslStream::VerifyPeer::Off, std::move(content), std::move(url), std::move(headers), timeout, ttl, prefer_ipv6, SslCtx::VerifyPeer::Off, std::move(content),
std::move(content_type))); std::move(content_type)));
#endif #endif
} }

View File

@ -24,6 +24,7 @@ set(TDNET_SOURCE
td/net/HttpQuery.cpp td/net/HttpQuery.cpp
td/net/HttpReader.cpp td/net/HttpReader.cpp
td/net/Socks5.cpp td/net/Socks5.cpp
td/net/SslCtx.cpp
td/net/SslStream.cpp td/net/SslStream.cpp
td/net/TcpListener.cpp td/net/TcpListener.cpp
td/net/TransparentProxy.cpp td/net/TransparentProxy.cpp
@ -42,6 +43,7 @@ set(TDNET_SOURCE
td/net/HttpReader.h td/net/HttpReader.h
td/net/NetStats.h td/net/NetStats.h
td/net/Socks5.h td/net/Socks5.h
td/net/SslCtx.h
td/net/SslStream.h td/net/SslStream.h
td/net/TcpListener.h td/net/TcpListener.h
td/net/TransparentProxy.h td/net/TransparentProxy.h

View File

@ -7,7 +7,7 @@
#include "td/net/GetHostByNameActor.h" #include "td/net/GetHostByNameActor.h"
#include "td/net/HttpQuery.h" #include "td/net/HttpQuery.h"
#include "td/net/SslStream.h" #include "td/net/SslCtx.h"
#include "td/net/Wget.h" #include "td/net/Wget.h"
#include "td/utils/common.h" #include "td/utils/common.h"
@ -51,7 +51,7 @@ class GoogleDnsResolver final : public Actor {
"GoogleDnsResolver", std::move(wget_promise), "GoogleDnsResolver", std::move(wget_promise),
PSTRING() << "https://dns.google/resolve?name=" << url_encode(host_) << "&type=" << (prefer_ipv6_ ? 28 : 1), 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_, 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) { static Result<IPAddress> get_ip_address(Result<unique_ptr<HttpQuery>> r_http_query) {

311
tdnet/td/net/SslCtx.cpp Normal file
View File

@ -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

45
tdnet/td/net/SslCtx.h Normal file
View File

@ -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

View File

@ -9,28 +9,18 @@
#if !TD_EMSCRIPTEN #if !TD_EMSCRIPTEN
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/crypto.h" #include "td/utils/crypto.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include "td/utils/port/IPAddress.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/Status.h"
#include "td/utils/Time.h" #include "td/utils/Time.h"
#include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <cstring> #include <cstring>
#include <memory>
#include <mutex>
#if TD_PORT_WINDOWS
#include <wincrypt.h>
#endif
namespace td { namespace td {
@ -122,33 +112,6 @@ BIO_METHOD *BIO_s_sslstream() {
return result; 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 { struct SslHandleDeleter {
void operator()(SSL *ssl_handle) { void operator()(SSL *ssl_handle) {
auto start_time = Time::now(); auto start_time = Time::now();
@ -168,162 +131,18 @@ struct SslHandleDeleter {
using SslHandle = std::unique_ptr<SSL, 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 } // namespace
class SslStreamImpl { class SslStreamImpl {
public: public:
Status init(CSlice host, CSlice cert_file, SslStream::VerifyPeer verify_peer, bool check_ip_address_as_host) { Status init(CSlice host, CSlice cert_file, SslCtx::VerifyPeer verify_peer, bool check_ip_address_as_host) {
static bool init_openssl = [] { SslCtx::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);
clear_openssl_errors("Before SslFd::init"); 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) { if (!ssl_handle) {
return create_openssl_error(-13, "Failed to create an 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::operator=(SslStream &&) noexcept = default;
SslStream::~SslStream() = 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) { bool use_ip_address_as_host) {
auto impl = make_unique<detail::SslStreamImpl>(); auto impl = make_unique<detail::SslStreamImpl>();
TRY_STATUS(impl->init(host, cert_file, verify_peer, use_ip_address_as_host)); TRY_STATUS(impl->init(host, cert_file, verify_peer, use_ip_address_as_host));
@ -569,13 +388,13 @@ class SslStreamImpl {};
} // namespace detail } // namespace detail
SslStream::SslStream() = default; SslStream::SslStream() = default;
SslStream::SslStream(SslStream &&) = default; SslStream::SslStream(SslStream &&) noexcept = default;
SslStream &SslStream::operator=(SslStream &&) = default; SslStream &SslStream::operator=(SslStream &&) noexcept = default;
SslStream::~SslStream() = 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) { 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)) { SslStream::SslStream(unique_ptr<detail::SslStreamImpl> impl) : impl_(std::move(impl)) {

View File

@ -6,6 +6,8 @@
// //
#pragma once #pragma once
#include "td/net/SslCtx.h"
#include "td/utils/ByteFlow.h" #include "td/utils/ByteFlow.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Status.h" #include "td/utils/Status.h"
@ -23,9 +25,8 @@ class SslStream {
SslStream &operator=(SslStream &&) noexcept; SslStream &operator=(SslStream &&) noexcept;
~SslStream(); ~SslStream();
enum class VerifyPeer { On, Off }; static Result<SslStream> create(CSlice host, CSlice cert_file = CSlice(),
SslCtx::VerifyPeer verify_peer = SslCtx::VerifyPeer::On,
static Result<SslStream> create(CSlice host, CSlice cert_file = CSlice(), VerifyPeer verify_peer = VerifyPeer::On,
bool use_ip_address_as_host = false); bool use_ip_address_as_host = false);
ByteFlowInterface &read_byte_flow(); ByteFlowInterface &read_byte_flow();

View File

@ -25,7 +25,7 @@
namespace td { namespace td {
Wget::Wget(Promise<unique_ptr<HttpQuery>> promise, string url, std::vector<std::pair<string, string>> headers, 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) string content_type)
: promise_(std::move(promise)) : promise_(std::move(promise))
, input_url_(std::move(url)) , input_url_(std::move(url))

View File

@ -8,7 +8,7 @@
#include "td/net/HttpOutboundConnection.h" #include "td/net/HttpOutboundConnection.h"
#include "td/net/HttpQuery.h" #include "td/net/HttpQuery.h"
#include "td/net/SslStream.h" #include "td/net/SslCtx.h"
#include "td/actor/actor.h" #include "td/actor/actor.h"
@ -24,8 +24,7 @@ class Wget final : public HttpOutboundConnection::Callback {
public: public:
explicit Wget(Promise<unique_ptr<HttpQuery>> promise, string url, std::vector<std::pair<string, string>> headers = {}, 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, int32 timeout_in = 10, int32 ttl = 3, bool prefer_ipv6 = false,
SslStream::VerifyPeer verify_peer = SslStream::VerifyPeer::On, string content = {}, SslCtx::VerifyPeer verify_peer = SslCtx::VerifyPeer::On, string content = {}, string content_type = {});
string content_type = {});
private: private:
Status try_init(); Status try_init();
@ -46,7 +45,7 @@ class Wget final : public HttpOutboundConnection::Callback {
int32 timeout_in_; int32 timeout_in_;
int32 ttl_; int32 ttl_;
bool prefer_ipv6_ = false; bool prefer_ipv6_ = false;
SslStream::VerifyPeer verify_peer_; SslCtx::VerifyPeer verify_peer_;
string content_; string content_;
string content_type_; string content_type_;
}; };