include user-agent in tracker announces in anonymous_mode for private torrents

This commit is contained in:
arvidn 2017-03-12 12:49:41 -04:00 committed by Arvid Norberg
parent 4ded26de33
commit e37e4bfe8a
8 changed files with 94 additions and 18 deletions

View File

@ -1,3 +1,4 @@
* include user-agent in tracker announces in anonymous_mode for private torrents
* add support for IPv6 peers from udp trackers
* correctly URL encode the IPv6 argument to trackers
* fix default file pool size on windows

View File

@ -99,6 +99,7 @@ namespace libtorrent
, key(0)
, num_want(0)
, send_stats(true)
, private_torrent(false)
, triggered_manually(false)
#ifdef TORRENT_USE_OPENSSL
, ssl_ctx(0)
@ -159,6 +160,10 @@ namespace libtorrent
bool send_stats;
// set to true if the .torrent file this tracker announce is for is marked
// as private (i.e. has the "priv": 1 key)
bool private_torrent;
// this is set to true if this request was triggered by a "manual" call to
// scrape_tracker() or force_reannounce()
bool triggered_manually;

View File

@ -813,6 +813,61 @@ TORRENT_TEST(tracker_ipv6_argument_privacy_mode)
TEST_EQUAL(got_ipv6, false);
}
TORRENT_TEST(tracker_user_agent_privacy_mode_public_torrent)
{
bool got_announce = false;
tracker_test(
[](lt::add_torrent_params& p, lt::session& ses)
{
settings_pack pack;
pack.set_bool(settings_pack::anonymous_mode, true);
pack.set_str(settings_pack::user_agent, "test_agent/1.2.3");
ses.apply_settings(pack);
p.ti = make_torrent(false);
return 60;
},
[&](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
got_announce = true;
// in anonymous mode we should not send a user agent
TEST_CHECK(headers["user-agent"] == "");
return sim::send_response(200, "OK", 11) + "d5:peers0:e";
}
, [](torrent_handle h) {}
, [](torrent_handle h) {});
TEST_EQUAL(got_announce, true);
}
TORRENT_TEST(tracker_user_agent_privacy_mode_private_torrent)
{
bool got_announce = false;
tracker_test(
[](lt::add_torrent_params& p, lt::session& ses)
{
settings_pack pack;
pack.set_bool(settings_pack::anonymous_mode, true);
pack.set_str(settings_pack::user_agent, "test_agent/1.2.3");
ses.apply_settings(pack);
p.ti = make_torrent(true);
return 60;
},
[&](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
got_announce = true;
// in anonymous mode we should still send the user agent for private
// torrents (since private trackers sometimes require it)
TEST_CHECK(headers["user-agent"] == "test_agent/1.2.3");
return sim::send_response(200, "OK", 11) + "d5:peers0:e";
}
, [](torrent_handle h) {}
, [](torrent_handle h) {});
TEST_EQUAL(got_announce, true);
}
// TODO: test external IP
// TODO: test with different queuing settings
// TODO: test when a torrent transitions from downloading to finished and

View File

@ -209,10 +209,16 @@ namespace libtorrent
#endif
));
int timeout = tracker_req().event==tracker_request::stopped
int const timeout = tracker_req().event==tracker_request::stopped
?settings.get_int(settings_pack::stop_tracker_timeout)
:settings.get_int(settings_pack::tracker_completion_timeout);
// in anonymous mode we omit the user agent to mitigate fingerprinting of
// the client. Private torrents is an exception because some private
// trackers may requre the user agent
std::string const user_agent = settings.get_bool(settings_pack::anonymous_mode)
&& !tracker_req().private_torrent ? "" : settings.get_str(settings_pack::user_agent);
// when sending stopped requests, prefer the cached DNS entry
// to avoid being blocked for slow or failing responses. Chances
// are that we're shutting down, and this should be a best-effort
@ -221,9 +227,7 @@ namespace libtorrent
m_tracker_connection->get(url, seconds(timeout)
, tracker_req().event == tracker_request::stopped ? 2 : 1
, ps.proxy_tracker_connections ? &ps : NULL
, 5, settings.get_bool(settings_pack::anonymous_mode)
? "" : settings.get_str(settings_pack::user_agent)
, bind_interface()
, 5, user_agent, bind_interface()
, tracker_req().event == tracker_request::stopped
? resolver_interface::prefer_cache
: resolver_interface::abort_on_shutdown

View File

@ -629,9 +629,10 @@ int feed::update_feed()
, boost::bind(&feed::on_feed, shared_from_this()
, _1, _2, _3, _4)));
std::string const user_agent = m_ses.settings().get_bool(settings_pack::anonymous_mode)
? "" : m_ses.settings().get_str(settings_pack::user_agent);
m_updating = true;
feed->get(m_settings.url, seconds(30), 0, 0, 5
, m_ses.settings().get_str(settings_pack::user_agent));
feed->get(m_settings.url, seconds(30), 0, 0, 5, user_agent);
return 60 + m_failures * m_failures * 60;
}

View File

@ -6555,9 +6555,7 @@ retry:
return;
}
if (m_upnp)
m_upnp->set_user_agent("");
m_settings.set_str(settings_pack::user_agent, "");
if (m_upnp) m_upnp->set_user_agent("");
url_random(m_peer_id.data(), m_peer_id.data() + 20);
}

View File

@ -3137,6 +3137,8 @@ namespace libtorrent
&& m_apply_ip_filter)
req.filter = m_ip_filter;
req.private_torrent = m_torrent_file->priv();
req.info_hash = m_torrent_file->info_hash();
req.pid = m_ses.get_peer_id();
req.downloaded = m_stat.total_payload_download() - m_total_failed_bytes;
@ -3342,6 +3344,7 @@ namespace libtorrent
req.info_hash = m_torrent_file->info_hash();
req.kind |= tracker_request::scrape_request;
req.url = m_trackers[idx].url;
req.private_torrent = m_torrent_file->priv();
#ifndef TORRENT_NO_DEPRECATE
req.auth = tracker_login();
#endif
@ -3639,6 +3642,9 @@ namespace libtorrent
// and they should be announced to in parallel
tracker_request req = r;
req.private_torrent = m_torrent_file->priv();
// tell the tracker to bind to the opposite protocol type
req.bind_ip = tracker_ip.is_v4()
? m_ses.get_ipv6_interface().address()

View File

@ -145,28 +145,34 @@ namespace libtorrent
request += "Host: ";
request += m_host;
if ((m_first_request || m_settings.get_bool(settings_pack::always_send_user_agent))
&& !m_settings.get_bool(settings_pack::anonymous_mode)) {
&& !m_settings.get_bool(settings_pack::anonymous_mode))
{
request += "\r\nUser-Agent: ";
request += m_settings.get_str(settings_pack::user_agent);
}
if (!m_external_auth.empty()) {
if (!m_external_auth.empty())
{
request += "\r\nAuthorization: ";
request += m_external_auth;
} else if (!m_basic_auth.empty()) {
}
else if (!m_basic_auth.empty())
{
request += "\r\nAuthorization: Basic ";
request += m_basic_auth;
}
if (sett.get_int(settings_pack::proxy_type) == settings_pack::http_pw) {
if (sett.get_int(settings_pack::proxy_type) == settings_pack::http_pw)
{
request += "\r\nProxy-Authorization: Basic ";
request += base64encode(sett.get_str(settings_pack::proxy_username)
+ ":" + sett.get_str(settings_pack::proxy_password));
}
for (web_seed_entry::headers_t::const_iterator it = m_extra_headers.begin();
it != m_extra_headers.end(); ++it) {
request += "\r\n";
request += it->first;
request += ": ";
request += it->second;
it != m_extra_headers.end(); ++it)
{
request += "\r\n";
request += it->first;
request += ": ";
request += it->second;
}
if (using_proxy) {
request += "\r\nProxy-Connection: keep-alive";