diff --git a/webcc/client.cc b/webcc/client.cc index 4ddd25c..19a1e96 100644 --- a/webcc/client.cc +++ b/webcc/client.cc @@ -101,7 +101,7 @@ void Client::DoClose() { void Client::AsyncConnect() { if (request_->url().scheme() == "https") { #if WEBCC_ENABLE_SSL - socket_.reset(new SslSocket{ io_context_, ssl_context_, ssl_verify_ }); + socket_.reset(new SslSocket{ io_context_, ssl_context_ }); AsyncResolve("443"); #else LOG_ERRO("SSL/HTTPS support is not enabled."); diff --git a/webcc/client.h b/webcc/client.h index f94cb9b..62e9516 100644 --- a/webcc/client.h +++ b/webcc/client.h @@ -36,10 +36,6 @@ public: ~Client() = default; - void set_ssl_verify(bool ssl_verify) { - ssl_verify_ = ssl_verify; - } - void set_buffer_size(std::size_t buffer_size) { if (buffer_size > 0) { buffer_size_ = buffer_size; @@ -142,9 +138,6 @@ private: // The buffer for reading response. std::vector buffer_; - // Verify the certificate of the peer or not (for HTTPS). - bool ssl_verify_ = true; - // The size of the buffer for reading response. // 0 means default value will be used. std::size_t buffer_size_ = kBufferSize; @@ -166,6 +159,7 @@ private: // Progress callback (optional). ProgressCallback progress_callback_; + // Current error. Error error_; }; diff --git a/webcc/client_session.cc b/webcc/client_session.cc index 83309ad..355b130 100644 --- a/webcc/client_session.cc +++ b/webcc/client_session.cc @@ -41,7 +41,7 @@ namespace webcc { static bool UseSystemCertificateStore(SSL_CTX* ssl_ctx) { // NOTE: Cannot use nullptr to replace NULL. - HCERTSTORE cert_store = ::CertOpenSystemStoreW(NULL, L"ROOT"); + HCERTSTORE cert_store = CertOpenSystemStoreW(NULL, L"ROOT"); if (cert_store == nullptr) { LOG_ERRO("Cannot open Windows system certificate store."); return false; @@ -71,17 +71,15 @@ static bool UseSystemCertificateStore(SSL_CTX* ssl_ctx) { #endif // defined(_WIN32) || defined(_WIN64) #endif // WEBCC_ENABLE_SSL -ClientSession::ClientSession(bool ssl_verify, std::size_t buffer_size) +ClientSession::ClientSession(std::size_t buffer_size) : work_guard_(boost::asio::make_work_guard(io_context_)), #if WEBCC_ENABLE_SSL ssl_context_(boost::asio::ssl::context::sslv23), #endif - ssl_verify_(ssl_verify), buffer_size_(buffer_size) { + buffer_size_(buffer_size) { #if WEBCC_ENABLE_SSL #if (defined(_WIN32) || defined(_WIN64)) - // if (ssl_verify_) { UseSystemCertificateStore(ssl_context_.native_handle()); - // } #else // Use the default paths for finding CA certificates. ssl_context_.set_default_verify_paths(); @@ -252,7 +250,6 @@ ResponsePtr ClientSession::DoSend(RequestPtr request, bool stream, reuse = true; } - client->set_ssl_verify(ssl_verify_); client->set_buffer_size(buffer_size_); client->set_connect_timeout(connect_timeout_); client->set_read_timeout(read_timeout_); diff --git a/webcc/client_session.h b/webcc/client_session.h index a545a21..8a1d67e 100644 --- a/webcc/client_session.h +++ b/webcc/client_session.h @@ -15,12 +15,12 @@ namespace webcc { -// HTTP requests session providing connection-pooling, configuration and more. -// NOTE: If a session is shared by multiple threads, the requests sent through -// it will be serialized by using a mutex. +// Client session provides connection-pooling, configuration and more. +// If a client session is shared by multiple threads, the requests sent through +// it will be serialized by using a mutex. class ClientSession { public: - explicit ClientSession(bool ssl_verify = true, std::size_t buffer_size = 0); + explicit ClientSession(std::size_t buffer_size = 0); ~ClientSession(); @@ -45,10 +45,6 @@ public: } } - void set_ssl_verify(bool ssl_verify) { - ssl_verify_ = ssl_verify; - } - void set_buffer_size(std::size_t buffer_size) { buffer_size_ = buffer_size; } @@ -140,20 +136,17 @@ private: // Timeout (seconds) for reading response. int read_timeout_ = 0; - // Verify the certificate of the peer or not. - bool ssl_verify_ = true; - // The size of the buffer for reading response. // 0 means default value will be used. std::size_t buffer_size_; - // Keep-Alive client connections. + // Persistent (keep-alive) client connections. ClientPool pool_; // Current requested client. ClientPtr client_; - // The mutex to guard the request. + // The mutex to serialize the requests. std::mutex mutex_; }; diff --git a/webcc/socket.cc b/webcc/socket.cc index f6f0bf4..98872bf 100644 --- a/webcc/socket.cc +++ b/webcc/socket.cc @@ -60,9 +60,8 @@ bool Socket::Close() { namespace ssl = boost::asio::ssl; SslSocket::SslSocket(boost::asio::io_context& io_context, - ssl::context& ssl_context, bool ssl_verify) - : ssl_socket_(io_context, ssl_context), - ssl_verify_(ssl_verify) { + ssl::context& ssl_context) + : ssl_stream_(io_context, ssl_context) { } void SslSocket::AsyncConnect(const std::string& host, @@ -70,37 +69,35 @@ void SslSocket::AsyncConnect(const std::string& host, ConnectHandler&& handler) { connect_handler_ = std::move(handler); - - if (ssl_verify_) { - ssl_socket_.set_verify_mode(ssl::verify_peer); - } else { - ssl_socket_.set_verify_mode(ssl::verify_none); - } + // Modes `ssl::verify_fail_if_no_peer_cert` and `ssl::verify_client_once` are + // for server only. `ssl::verify_none` is not secure. + // See: https://stackoverflow.com/a/12621528 + ssl_stream_.set_verify_mode(ssl::verify_peer); // ssl::host_name_verification has been added since Boost 1.73 to replace // ssl::rfc2818_verification. #if BOOST_VERSION < 107300 - ssl_socket_.set_verify_callback(ssl::rfc2818_verification(host)); + ssl_stream_.set_verify_callback(ssl::rfc2818_verification(host)); #else - ssl_socket_.set_verify_callback(ssl::host_name_verification(host)); + ssl_stream_.set_verify_callback(ssl::host_name_verification(host)); #endif // BOOST_VERSION < 107300 - boost::asio::async_connect(ssl_socket_.lowest_layer(), endpoints, + boost::asio::async_connect(ssl_stream_.lowest_layer(), endpoints, std::bind(&SslSocket::OnConnect, this, _1, _2)); } void SslSocket::AsyncWrite(const Payload& payload, WriteHandler&& handler) { - boost::asio::async_write(ssl_socket_, payload, std::move(handler)); + boost::asio::async_write(ssl_stream_, payload, std::move(handler)); } void SslSocket::AsyncReadSome(ReadHandler&& handler, std::vector* buffer) { - ssl_socket_.async_read_some(boost::asio::buffer(*buffer), std::move(handler)); + ssl_stream_.async_read_some(boost::asio::buffer(*buffer), std::move(handler)); } bool SslSocket::Shutdown() { boost::system::error_code ec; - ssl_socket_.lowest_layer().shutdown(tcp::socket::shutdown_both, ec); + ssl_stream_.lowest_layer().shutdown(tcp::socket::shutdown_both, ec); if (ec) { LOG_WARN("Socket shutdown error (%s)", ec.message().c_str()); @@ -112,7 +109,7 @@ bool SslSocket::Shutdown() { bool SslSocket::Close() { boost::system::error_code ec; - ssl_socket_.lowest_layer().close(ec); + ssl_stream_.lowest_layer().close(ec); if (ec) { LOG_WARN("Socket close error (%s)", ec.message().c_str()); @@ -132,7 +129,7 @@ void SslSocket::OnConnect(boost::system::error_code ec, // Backup endpoint endpoint_ = std::move(endpoint); - ssl_socket_.async_handshake(ssl::stream_base::client, + ssl_stream_.async_handshake(ssl::stream_base::client, [this](boost::system::error_code ec) { if (ec) { LOG_ERRO("Handshake error (%s)", ec.message().c_str()); diff --git a/webcc/socket.h b/webcc/socket.h index 1982c51..1a798a5 100644 --- a/webcc/socket.h +++ b/webcc/socket.h @@ -72,8 +72,7 @@ private: class SslSocket : public SocketBase { public: SslSocket(boost::asio::io_context& io_context, - boost::asio::ssl::context& ssl_context, - bool ssl_verify = true); + boost::asio::ssl::context& ssl_context); void AsyncConnect(const std::string& host, const Endpoints& endpoints, ConnectHandler&& handler) override; @@ -93,10 +92,7 @@ private: ConnectHandler connect_handler_; boost::asio::ip::tcp::endpoint endpoint_; - boost::asio::ssl::stream ssl_socket_; - - // Verify the certificate of the peer (remote server) or not. - bool ssl_verify_ = true; + boost::asio::ssl::stream ssl_stream_; }; #endif // WEBCC_ENABLE_SSL