From e5e613d948e458ff2b3de9e284b1b92fe5be634e Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 19 Oct 2017 14:32:35 +0200 Subject: [PATCH 1/3] Ability to set a sni_hostname at the request level --- .../http/client/connection/async_normal.hpp | 16 +++---- .../client/connection/connection_delegate.hpp | 3 +- .../client/connection/normal_delegate.hpp | 2 +- .../client/connection/normal_delegate.ipp | 2 +- .../http/client/connection/ssl_delegate.hpp | 2 +- .../http/client/connection/ssl_delegate.ipp | 10 ++++- boost/network/protocol/http/impl/request.hpp | 24 +++++++---- libs/network/test/http/client_get_test.cpp | 42 +++++++++++++++++++ 8 files changed, 80 insertions(+), 21 deletions(-) diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index 19c15590f..5cfcbb561 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -101,12 +101,14 @@ struct http_async_connection string_type host_ = host(request); std::uint16_t source_port = request.source_port(); + auto sni_hostname = request.sni_hostname(); + auto self = this->shared_from_this(); resolve_(resolver_, host_, port_, request_strand_.wrap( [=] (boost::system::error_code const &ec, resolver_iterator_pair endpoint_range) { - self->handle_resolved(host_, port_, source_port, get_body, + self->handle_resolved(host_, port_, source_port, sni_hostname, get_body, callback, generator, ec, endpoint_range); })); if (timeout_ > 0) { @@ -139,7 +141,7 @@ struct http_async_connection } void handle_resolved(string_type host, std::uint16_t port, - std::uint16_t source_port, bool get_body, + std::uint16_t source_port, optional sni_hostname, bool get_body, body_callback_function_type callback, body_generator_function_type generator, boost::system::error_code const& ec, @@ -151,10 +153,10 @@ struct http_async_connection boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); auto self = this->shared_from_this(); delegate_->connect( - endpoint, host, source_port, + endpoint, host, source_port, sni_hostname, request_strand_.wrap([=] (boost::system::error_code const &ec) { auto iter_copy = iter; - self->handle_connected(host, port, source_port, get_body, callback, + self->handle_connected(host, port, source_port, sni_hostname, get_body, callback, generator, std::make_pair(++iter_copy, resolver_iterator()), ec); })); } else { @@ -163,7 +165,7 @@ struct http_async_connection } void handle_connected(string_type host, std::uint16_t port, - std::uint16_t source_port, bool get_body, + std::uint16_t source_port, optional sni_hostname, bool get_body, body_callback_function_type callback, body_generator_function_type generator, resolver_iterator_pair endpoint_range, @@ -186,10 +188,10 @@ struct http_async_connection boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); auto self = this->shared_from_this(); delegate_->connect( - endpoint, host, source_port, + endpoint, host, source_port, sni_hostname, request_strand_.wrap([=] (boost::system::error_code const &ec) { auto iter_copy = iter; - self->handle_connected(host, port, source_port, get_body, callback, + self->handle_connected(host, port, source_port, sni_hostname, get_body, callback, generator, std::make_pair(++iter_copy, resolver_iterator()), ec); })); diff --git a/boost/network/protocol/http/client/connection/connection_delegate.hpp b/boost/network/protocol/http/client/connection/connection_delegate.hpp index 4e223864e..6bbf4d32c 100644 --- a/boost/network/protocol/http/client/connection/connection_delegate.hpp +++ b/boost/network/protocol/http/client/connection/connection_delegate.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace boost { namespace network { @@ -19,7 +20,7 @@ namespace impl { struct connection_delegate { virtual void connect(boost::asio::ip::tcp::endpoint &endpoint, std::string host, - std::uint16_t source_port, + std::uint16_t source_port, optional sni_hostname, std::function handler) = 0; virtual void write( boost::asio::streambuf &command_streambuf, diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp index a4187f7fc..24955cd05 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.hpp +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -25,7 +25,7 @@ struct normal_delegate : connection_delegate { explicit normal_delegate(boost::asio::io_service &service); void connect(boost::asio::ip::tcp::endpoint &endpoint, std::string host, - std::uint16_t source_port, + std::uint16_t source_port, optional sni_hostname, std::function handler) override; void write(boost::asio::streambuf &command_streambuf, std::function handler) diff --git a/boost/network/protocol/http/client/connection/normal_delegate.ipp b/boost/network/protocol/http/client/connection/normal_delegate.ipp index 552f50417..027f04a8c 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.ipp +++ b/boost/network/protocol/http/client/connection/normal_delegate.ipp @@ -21,7 +21,7 @@ boost::network::http::impl::normal_delegate::normal_delegate( void boost::network::http::impl::normal_delegate::connect( boost::asio::ip::tcp::endpoint &endpoint, std::string host, - std::uint16_t source_port, + std::uint16_t source_port, optional sni_hostname, std::function handler) { // TODO(dberris): review parameter necessity. diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.hpp b/boost/network/protocol/http/client/connection/ssl_delegate.hpp index 63adc1818..6ad298dcb 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.hpp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.hpp @@ -33,7 +33,7 @@ struct ssl_delegate : public connection_delegate, optional sni_hostname, long ssl_options); void connect(boost::asio::ip::tcp::endpoint &endpoint, std::string host, - std::uint16_t source_port, + std::uint16_t source_port, optional sni_hostname, std::function handler) override; void write( boost::asio::streambuf &command_streambuf, diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp index e94a43994..7575b12b4 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -30,8 +30,9 @@ boost::network::http::impl::ssl_delegate::ssl_delegate( void boost::network::http::impl::ssl_delegate::connect( boost::asio::ip::tcp::endpoint &endpoint, std::string host, - std::uint16_t source_port, + std::uint16_t source_port, optional sni_hostname, std::function handler) { + context_.reset( new boost::asio::ssl::context(boost::asio::ssl::context::method::sslv23_client)); if (ciphers_) { @@ -71,8 +72,13 @@ void boost::network::http::impl::ssl_delegate::connect( socket_.reset(new boost::asio::ssl::stream( *(tcp_socket_.get()), *context_)); - if (sni_hostname_) + if (sni_hostname) { // at request level + SSL_set_tlsext_host_name(socket_->native_handle(), sni_hostname->c_str()); + } else if (sni_hostname_) { // at client level SSL_set_tlsext_host_name(socket_->native_handle(), sni_hostname_->c_str()); + } + + if (always_verify_peer_) socket_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); auto self = this->shared_from_this(); diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 85ab0f3ae..04d0b8562 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -50,29 +50,32 @@ namespace http { */ template struct basic_request : public basic_message { - mutable boost::network::uri::uri uri_; - std::uint16_t source_port_; - typedef basic_message base_type; - public: typedef Tag tag; typedef typename string::type string_type; typedef std::uint16_t port_type; + private: + mutable boost::network::uri::uri uri_; + std::uint16_t source_port_; + optional sni_hostname_; + typedef basic_message base_type; + + public: explicit basic_request(string_type const& uri_) - : uri_(uri_), source_port_(0) {} + : uri_(uri_), source_port_(0), sni_hostname_() {} explicit basic_request(boost::network::uri::uri const& uri_) - : uri_(uri_), source_port_(0) {} + : uri_(uri_), source_port_(0), sni_hostname_() {} void uri(string_type const& new_uri) { uri_ = new_uri; } void uri(boost::network::uri::uri const& new_uri) { uri_ = new_uri; } - basic_request() : base_type(), source_port_(0) {} + basic_request() : base_type(), source_port_(0), sni_hostname_() {} basic_request(basic_request const& other) - : base_type(other), uri_(other.uri_), source_port_(other.source_port_) {} + : base_type(other), uri_(other.uri_), source_port_(other.source_port_), sni_hostname_(other.sni_hostname_) {} basic_request& operator=(basic_request rhs) { rhs.swap(*this); @@ -85,6 +88,7 @@ struct basic_request : public basic_message { base_ref.swap(this_ref); boost::swap(other.uri_, this->uri_); boost::swap(other.source_port_, this->source_port_); + boost::swap(other.sni_hostname_, this->sni_hostname_); } string_type const host() const { return uri_.host(); } @@ -114,6 +118,10 @@ struct basic_request : public basic_message { void source_port(const std::uint16_t port) { source_port_ = port; } std::uint16_t source_port() const { return source_port_; } + + void sni_hostname(string_type const &sni_hostname) { sni_hostname_ = sni_hostname; } + + const optional &sni_hostname() const { return sni_hostname_; } }; /** This is the implementation of a POD request type diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index b5eb5b77b..4197b0efd 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -65,3 +65,45 @@ TYPED_TEST(HTTPClientTest, TemporaryClientObjectTest) { EXPECT_TRUE(response.status() == 200u || (response.status() >= 300 && response.status() < 400)); } + + +typedef boost::network::http::basic_client async_client; +#define EXC_PTR(cmd) try { cmd } catch (const std::exception_ptr& ex) { std::rethrow_exception(ex); } + +TYPED_TEST(HTTPClientTest, ReuseResponse) { + + async_client client; + + async_client::request req("https://static.deepomatic.com/compass/NVR_ch2_J_20161209122514_20161209122514_orig.jpg"); + + req.sni_hostname(req.host()); + + auto response = client.get(req); + + while (!ready(response)); + + EXC_PTR(response.status();); + + // we get the expected headers and body + auto hdrs = headers(response); + + for (auto &h : hdrs) { + std::cout << h.first << ": " << h.second << std::endl; + } + + std::cout << "---" << std::endl; + + req.uri("http://example.com"); // changing the url + + response = client.get(req); + + while (!ready(response)); + + // here the headers are the same as the previous response, they should be those from example.com + auto hdrs2 = headers(response); + + for (auto &h : hdrs2) { + std::cout << h.first << ": " << h.second << std::endl; + } + +} From 336fa627e0cccd4eb9afcb4e4639359e0b179ca4 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 19 Oct 2017 14:53:11 +0200 Subject: [PATCH 2/3] Better test --- libs/network/test/http/client_get_test.cpp | 49 ++++++++-------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index 4197b0efd..57b6bd9b5 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -70,40 +70,27 @@ TYPED_TEST(HTTPClientTest, TemporaryClientObjectTest) { typedef boost::network::http::basic_client async_client; #define EXC_PTR(cmd) try { cmd } catch (const std::exception_ptr& ex) { std::rethrow_exception(ex); } -TYPED_TEST(HTTPClientTest, ReuseResponse) { - - async_client client; - - async_client::request req("https://static.deepomatic.com/compass/NVR_ch2_J_20161209122514_20161209122514_orig.jpg"); - - req.sni_hostname(req.host()); - - auto response = client.get(req); - - while (!ready(response)); - - EXC_PTR(response.status();); - - // we get the expected headers and body - auto hdrs = headers(response); - - for (auto &h : hdrs) { - std::cout << h.first << ": " << h.second << std::endl; - } - - std::cout << "---" << std::endl; - - req.uri("http://example.com"); // changing the url - - response = client.get(req); +TYPED_TEST(HTTPClientTest, GetRequestSNI) { + using client = TypeParam; + // need sni_hostname to be set + typename client::request request("https://www.guide-du-chien.com/wp-content/uploads/2016/10/Beagle.jpg"); + typename client::response response; - while (!ready(response)); + // trying without setting sni_hostname + ASSERT_NO_THROW(response = client().get(request)); + // raise "tlsv1 alert internal error" + ASSERT_THROW(response.status(), std::exception_ptr); - // here the headers are the same as the previous response, they should be those from example.com - auto hdrs2 = headers(response); + // setting sni_hostname + request.sni_hostname(request.host()); + ASSERT_NO_THROW(response = client().get(request)); + EXPECT_EQ(200u, response.status()); - for (auto &h : hdrs2) { - std::cout << h.first << ": " << h.second << std::endl; + try { + auto data = body(response); + std::cout << "Body size: " << data.size() << std::endl; + } catch (...) { + FAIL() << "Caught exception while retrieving body from GET request"; } } From 70ea80eaa92df1c772e510a03f923bf63e84f324 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 19 Oct 2017 14:54:37 +0200 Subject: [PATCH 3/3] Test only if https enabled --- libs/network/test/http/client_get_test.cpp | 44 ++++++++++------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index 57b6bd9b5..f456f93a9 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -46,30 +46,6 @@ TYPED_TEST(HTTPClientTest, GetHTTPSTest) { } } -#endif - -TYPED_TEST(HTTPClientTest, TemporaryClientObjectTest) { - using client = TypeParam; - typename client::request request("http://cpp-netlib.org/"); - typename client::response response; - ASSERT_NO_THROW(response = client().get(request)); - auto range = headers(response); - ASSERT_TRUE(!boost::empty(range)); - try { - auto data = body(response); - std::cout << data; - } catch (...) { - FAIL() << "Caught exception while retrieving body from GET request"; - } - EXPECT_EQ("HTTP/1.", response.version().substr(0, 7)); - EXPECT_TRUE(response.status() == 200u || - (response.status() >= 300 && response.status() < 400)); -} - - -typedef boost::network::http::basic_client async_client; -#define EXC_PTR(cmd) try { cmd } catch (const std::exception_ptr& ex) { std::rethrow_exception(ex); } - TYPED_TEST(HTTPClientTest, GetRequestSNI) { using client = TypeParam; // need sni_hostname to be set @@ -94,3 +70,23 @@ TYPED_TEST(HTTPClientTest, GetRequestSNI) { } } + +#endif + +TYPED_TEST(HTTPClientTest, TemporaryClientObjectTest) { + using client = TypeParam; + typename client::request request("http://cpp-netlib.org/"); + typename client::response response; + ASSERT_NO_THROW(response = client().get(request)); + auto range = headers(response); + ASSERT_TRUE(!boost::empty(range)); + try { + auto data = body(response); + std::cout << data; + } catch (...) { + FAIL() << "Caught exception while retrieving body from GET request"; + } + EXPECT_EQ("HTTP/1.", response.version().substr(0, 7)); + EXPECT_TRUE(response.status() == 200u || + (response.status() >= 300 && response.status() < 400)); +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy