From b3815c5533deadfc3d3fbc850ee945ca5af457c1 Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Mon, 8 May 2017 17:04:17 +0200 Subject: [PATCH] HTTP proxy: avoid connecting to itself (#1978) --- ChangeLog | 1 + include/libtorrent/proxy_base.hpp | 4 +-- simulation/libsimulator | 2 +- simulation/test_http_connection.cpp | 55 ++++++++++++++++++++++++++--- src/http_stream.cpp | 10 +----- 5 files changed, 56 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index ba72f7f9f..e7a31afbf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * fix proxying of https connections * fix race condition in disk I/O storage class * fix http connection timeout on multi-homed hosts * removed depdendency on boost::uintptr_t for better compatibility diff --git a/include/libtorrent/proxy_base.hpp b/include/libtorrent/proxy_base.hpp index 8bed55e6e..00246af76 100644 --- a/include/libtorrent/proxy_base.hpp +++ b/include/libtorrent/proxy_base.hpp @@ -252,8 +252,8 @@ protected: bool handle_error(error_code const& e, boost::shared_ptr const& h); tcp::socket m_sock; - std::string m_hostname; - int m_port; + std::string m_hostname; // proxy host + int m_port; // proxy port endpoint_type m_remote_endpoint; diff --git a/simulation/libsimulator b/simulation/libsimulator index 0e8d74baf..70feadef8 160000 --- a/simulation/libsimulator +++ b/simulation/libsimulator @@ -1 +1 @@ -Subproject commit 0e8d74baf1f6d9db19857eaa87734faecd530f94 +Subproject commit 70feadef80dc76ae6d5e7c2f92334377d698dd7d diff --git a/simulation/test_http_connection.cpp b/simulation/test_http_connection.cpp index 74de4c777..0fde8936f 100644 --- a/simulation/test_http_connection.cpp +++ b/simulation/test_http_connection.cpp @@ -489,8 +489,8 @@ TORRENT_TEST(http_connection_timeout_server_stalls) error_code e; sim.run(e); TEST_CHECK(!e); - TEST_EQUAL(2, connect_counter); // both endpoints are connected to - TEST_EQUAL(1, handler_counter); // the handler only gets called once with error_code == timed_out + TEST_EQUAL(connect_counter, 2); // both endpoints are connected to + TEST_EQUAL(handler_counter, 1); // the handler only gets called once with error_code == timed_out } // tests the error scenario of a http server listening on two sockets (ipv4/ipv6) neither of which @@ -541,8 +541,8 @@ TORRENT_TEST(http_connection_timeout_server_does_not_accept) error_code e; sim.run(e); TEST_CHECK(!e); - TEST_EQUAL(0, connect_counter); // no connection takes place - TEST_EQUAL(1, handler_counter); // the handler only gets called once with error_code == timed_out + TEST_EQUAL(connect_counter, 0); // no connection takes place + TEST_EQUAL(handler_counter, 1); // the handler only gets called once with error_code == timed_out } void test_proxy_failure(lt::settings_pack::proxy_type_t proxy_type) @@ -598,6 +598,53 @@ TORRENT_TEST(http_connection_http_error) test_proxy_failure(settings_pack::http); } +// Requests a proxied SSL connection. This test just ensures that the correct CONNECT request +// is sent to the proxy server. +TORRENT_TEST(http_connection_ssl_proxy) +{ + using sim::asio::ip::address_v4; + sim_config network_cfg; + sim::simulation sim{network_cfg}; + + sim::asio::io_service client_ios(sim, address_v4::from_string("10.0.0.1")); + sim::asio::io_service proxy_ios(sim, address_v4::from_string("50.50.50.50")); + lt::resolver res(client_ios); + + sim::http_server http_proxy(proxy_ios, 4445); + + lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::http); + + int client_counter = 0; + int proxy_counter = 0; + + http_proxy.register_handler("10.0.0.2:8080" + , [&proxy_counter](std::string method, std::string req, std::map& headers) + { + proxy_counter++; + TEST_EQUAL(method, "CONNECT"); + return sim::send_response(403, "Not supported", 1337); + }); + + auto h = boost::make_shared(client_ios + , res + , [&client_counter](error_code const& ec, http_parser const& parser + , char const* data, const int size, http_connection& c) + { + client_counter++; + TEST_EQUAL(ec, boost::asio::error::operation_not_supported); + }); + + h->start("10.0.0.2", 8080, seconds(1), 0, &ps, true /*ssl*/); + + error_code e; + sim.run(e); + + TEST_EQUAL(client_counter, 1); + TEST_EQUAL(proxy_counter, 1); + if (e) std::cerr << " run failed: " << e.message() << std::endl; + TEST_EQUAL(e, error_code()); +} + // TODO: test http proxy with password // TODO: test socks5 with password // TODO: test SSL diff --git a/src/http_stream.cpp b/src/http_stream.cpp index 5cfc983dd..9729ffa18 100644 --- a/src/http_stream.cpp +++ b/src/http_stream.cpp @@ -61,15 +61,7 @@ namespace libtorrent // send CONNECT std::back_insert_iterator > p(m_buffer); - std::string endpoint; - if (!m_hostname.empty()) - { - endpoint = m_hostname + ':' + to_string(m_remote_endpoint.port()).elems; - } - else - { - endpoint = print_endpoint(m_remote_endpoint); - } + std::string endpoint = print_endpoint(m_remote_endpoint); write_string("CONNECT " + endpoint + " HTTP/1.0\r\n", p); if (!m_user.empty()) {