forked from premiere/premiere-libtorrent
generate random keys for use in tracker announces. keys are unique for each torrent and the listen interface they announce via
This commit is contained in:
parent
f2681412e7
commit
a6656aeb93
|
@ -1,3 +1,4 @@
|
||||||
|
* make tracker keys multi-homed. remove set_key() function on session.
|
||||||
* add API to query whether alerts have been dropped or not
|
* add API to query whether alerts have been dropped or not
|
||||||
* add flags()/set_flags()/unset_flags() to torrent_handle, deprecate individual functions
|
* add flags()/set_flags()/unset_flags() to torrent_handle, deprecate individual functions
|
||||||
* added alert for block being sent to the send buffer
|
* added alert for block being sent to the send buffer
|
||||||
|
|
|
@ -198,6 +198,10 @@ namespace aux {
|
||||||
// which alias the listen_socket_t shared_ptr
|
// which alias the listen_socket_t shared_ptr
|
||||||
std::shared_ptr<tcp::acceptor> sock;
|
std::shared_ptr<tcp::acceptor> sock;
|
||||||
std::shared_ptr<aux::session_udp_socket> udp_sock;
|
std::shared_ptr<aux::session_udp_socket> udp_sock;
|
||||||
|
|
||||||
|
// the key is an id that is used to identify the
|
||||||
|
// client with the tracker only.
|
||||||
|
std::uint32_t tracker_key = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXTRA_EXPORT listen_endpoint_t
|
struct TORRENT_EXTRA_EXPORT listen_endpoint_t
|
||||||
|
@ -583,6 +587,8 @@ namespace aux {
|
||||||
std::uint16_t ssl_listen_port() const override;
|
std::uint16_t ssl_listen_port() const override;
|
||||||
std::uint16_t ssl_listen_port(listen_socket_t* sock) const;
|
std::uint16_t ssl_listen_port(listen_socket_t* sock) const;
|
||||||
|
|
||||||
|
std::uint32_t get_tracker_key(address const& iface) const;
|
||||||
|
|
||||||
void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) override
|
void for_each_listen_socket(std::function<void(aux::listen_socket_handle const&)> f) override
|
||||||
{
|
{
|
||||||
for (auto& s : m_listen_sockets)
|
for (auto& s : m_listen_sockets)
|
||||||
|
@ -906,11 +912,6 @@ namespace aux {
|
||||||
// the peer id that is generated at the start of the session
|
// the peer id that is generated at the start of the session
|
||||||
peer_id m_peer_id;
|
peer_id m_peer_id;
|
||||||
|
|
||||||
// the key is an id that is used to identify the
|
|
||||||
// client with the tracker only. It is randomized
|
|
||||||
// at startup
|
|
||||||
std::uint32_t m_key = 0;
|
|
||||||
|
|
||||||
// posts a notification when the set of local IPs changes
|
// posts a notification when the set of local IPs changes
|
||||||
std::unique_ptr<ip_change_notifier> m_ip_notifier;
|
std::unique_ptr<ip_change_notifier> m_ip_notifier;
|
||||||
|
|
||||||
|
|
|
@ -586,10 +586,13 @@ namespace libtorrent {
|
||||||
// the peer ID is randomized per peer.
|
// the peer ID is randomized per peer.
|
||||||
peer_id id() const;
|
peer_id id() const;
|
||||||
|
|
||||||
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
|
// deprecated in 1.2
|
||||||
// sets the key sent to trackers. If it's not set, it is initialized
|
// sets the key sent to trackers. If it's not set, it is initialized
|
||||||
// by libtorrent. The key may be used by the tracker to identify the
|
// by libtorrent. The key may be used by the tracker to identify the
|
||||||
// peer potentially across you changing your IP.
|
// peer potentially across you changing your IP.
|
||||||
void set_key(std::uint32_t key);
|
void set_key(std::uint32_t key);
|
||||||
|
#endif
|
||||||
|
|
||||||
// built-in peer classes
|
// built-in peer classes
|
||||||
static constexpr peer_class_t global_peer_class_id{0};
|
static constexpr peer_class_t global_peer_class_id{0};
|
||||||
|
|
|
@ -43,6 +43,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/file_storage.hpp"
|
#include "libtorrent/file_storage.hpp"
|
||||||
#include "libtorrent/torrent_info.hpp"
|
#include "libtorrent/torrent_info.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace lt;
|
using namespace lt;
|
||||||
using namespace sim;
|
using namespace sim;
|
||||||
|
|
||||||
|
@ -989,6 +991,30 @@ TORRENT_TEST(tracker_ipv6_argument)
|
||||||
TEST_EQUAL(got_ipv6, true);
|
TEST_EQUAL(got_ipv6, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(tracker_key_argument)
|
||||||
|
{
|
||||||
|
std::set<std::string> keys;
|
||||||
|
tracker_test(
|
||||||
|
[](lt::add_torrent_params& p, lt::session& ses)
|
||||||
|
{
|
||||||
|
p.ti = make_torrent(true);
|
||||||
|
return 60;
|
||||||
|
},
|
||||||
|
[&](std::string method, std::string req
|
||||||
|
, std::map<std::string, std::string>& headers)
|
||||||
|
{
|
||||||
|
auto const pos = req.find("&key=");
|
||||||
|
TEST_CHECK(pos != std::string::npos);
|
||||||
|
keys.insert(req.substr(pos + 5, req.find_first_of('&', pos + 5) - pos - 5));
|
||||||
|
return sim::send_response(200, "OK", 11) + "d5:peers0:e";
|
||||||
|
}
|
||||||
|
, [](torrent_handle h) {}
|
||||||
|
, [](torrent_handle h) {});
|
||||||
|
|
||||||
|
// make sure we got two separate keys, one for each listen socket interface
|
||||||
|
TEST_EQUAL(keys.size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
// make sure we do _not_ send our IPv6 address to trackers for non-private
|
// make sure we do _not_ send our IPv6 address to trackers for non-private
|
||||||
// torrents
|
// torrents
|
||||||
TORRENT_TEST(tracker_ipv6_argument_non_private)
|
TORRENT_TEST(tracker_ipv6_argument_non_private)
|
||||||
|
|
|
@ -802,6 +802,13 @@ namespace {
|
||||||
p.set_str(settings_pack::peer_fingerprint, id.to_string());
|
p.set_str(settings_pack::peer_fingerprint, id.to_string());
|
||||||
apply_settings(std::move(p));
|
apply_settings(std::move(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session_handle::set_key(std::uint32_t)
|
||||||
|
{
|
||||||
|
// this is just a dummy function now, as we generate the key automatically
|
||||||
|
// per listen interface
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
peer_id session_handle::id() const
|
peer_id session_handle::id() const
|
||||||
|
@ -809,11 +816,6 @@ namespace {
|
||||||
return sync_call_ret<peer_id>(&session_impl::get_peer_id);
|
return sync_call_ret<peer_id>(&session_impl::get_peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_handle::set_key(std::uint32_t key)
|
|
||||||
{
|
|
||||||
async_call(&session_impl::set_key, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short session_handle::listen_port() const
|
unsigned short session_handle::listen_port() const
|
||||||
{
|
{
|
||||||
return sync_call_ret<unsigned short, unsigned short(session_impl::*)() const>
|
return sync_call_ret<unsigned short, unsigned short(session_impl::*)() const>
|
||||||
|
|
|
@ -1134,8 +1134,6 @@ namespace {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_key) req.key = m_key;
|
|
||||||
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
bool use_ssl = req.ssl_ctx != nullptr;
|
bool use_ssl = req.ssl_ctx != nullptr;
|
||||||
req.ssl_ctx = &m_ssl_ctx;
|
req.ssl_ctx = &m_ssl_ctx;
|
||||||
|
@ -1144,22 +1142,34 @@ namespace {
|
||||||
if (req.outgoing_socket)
|
if (req.outgoing_socket)
|
||||||
{
|
{
|
||||||
auto ls = req.outgoing_socket.get();
|
auto ls = req.outgoing_socket.get();
|
||||||
req.listen_port = listen_port(ls);
|
|
||||||
|
req.key ^= ls->tracker_key;
|
||||||
|
|
||||||
|
req.listen_port =
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
// SSL torrents use the SSL listen port
|
// SSL torrents use the SSL listen port
|
||||||
if (use_ssl) req.listen_port = ssl_listen_port(ls);
|
use_ssl ? ssl_listen_port(ls) :
|
||||||
#endif
|
#endif
|
||||||
|
listen_port(ls);
|
||||||
m_tracker_manager.queue_request(get_io_service(), req, c);
|
m_tracker_manager.queue_request(get_io_service(), req, c);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (auto& ls : m_listen_sockets)
|
for (auto& ls : m_listen_sockets)
|
||||||
{
|
{
|
||||||
req.listen_port = listen_port(ls.get());
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
if ((ls->ssl == transport::ssl) != use_ssl) continue;
|
||||||
|
#endif
|
||||||
|
req.listen_port =
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
// SSL torrents use the SSL listen port
|
// SSL torrents use the SSL listen port
|
||||||
if (use_ssl) req.listen_port = ssl_listen_port(ls.get());
|
use_ssl ? ssl_listen_port(ls.get()) :
|
||||||
#endif
|
#endif
|
||||||
|
listen_port(ls.get());
|
||||||
|
|
||||||
|
// we combine the per-torrent key with the per-interface key to make
|
||||||
|
// them consistent and uniqiue per torrent and interface
|
||||||
|
req.key ^= ls->tracker_key;
|
||||||
req.outgoing_socket = ls;
|
req.outgoing_socket = ls;
|
||||||
m_tracker_manager.queue_request(get_io_service(), req, c);
|
m_tracker_manager.queue_request(get_io_service(), req, c);
|
||||||
}
|
}
|
||||||
|
@ -1384,6 +1394,25 @@ namespace {
|
||||||
reopen_outgoing_sockets();
|
reopen_outgoing_sockets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::uint32_t session_impl::get_tracker_key(address const& iface) const
|
||||||
|
{
|
||||||
|
uintptr_t const ses = reinterpret_cast<uintptr_t>(this);
|
||||||
|
hasher h(reinterpret_cast<char const*>(&ses), sizeof(ses));
|
||||||
|
if (iface.is_v4())
|
||||||
|
{
|
||||||
|
auto const b = iface.to_v4().to_bytes();
|
||||||
|
h.update({reinterpret_cast<char const*>(b.data()), b.size()});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto const b = iface.to_v6().to_bytes();
|
||||||
|
h.update({reinterpret_cast<char const*>(b.data()), b.size()});
|
||||||
|
}
|
||||||
|
sha1_hash const hash = h.final();
|
||||||
|
unsigned char const* ptr = &hash[0];
|
||||||
|
return detail::read_uint32(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<listen_socket_t> session_impl::setup_listener(
|
std::shared_ptr<listen_socket_t> session_impl::setup_listener(
|
||||||
listen_endpoint_t const& lep, error_code& ec)
|
listen_endpoint_t const& lep, error_code& ec)
|
||||||
{
|
{
|
||||||
|
@ -1591,6 +1620,8 @@ namespace {
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
ret->tracker_key = get_tracker_key(ret->local_endpoint.address());
|
||||||
|
|
||||||
ret->tcp_external_port = ret->local_endpoint.port();
|
ret->tcp_external_port = ret->local_endpoint.port();
|
||||||
TORRENT_ASSERT(ret->tcp_external_port == bind_ep.port()
|
TORRENT_ASSERT(ret->tcp_external_port == bind_ep.port()
|
||||||
|| bind_ep.port() == 0);
|
|| bind_ep.port() == 0);
|
||||||
|
@ -3006,11 +3037,6 @@ namespace {
|
||||||
m_peer_id = id;
|
m_peer_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::set_key(std::uint32_t key)
|
|
||||||
{
|
|
||||||
m_key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
int session_impl::next_port() const
|
int session_impl::next_port() const
|
||||||
{
|
{
|
||||||
int start = m_settings.get_int(settings_pack::outgoing_port);
|
int start = m_settings.get_int(settings_pack::outgoing_port);
|
||||||
|
@ -5394,6 +5420,8 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 2 this function should be removed and users need to deal with the
|
||||||
|
// more generic case of having multiple listen ports
|
||||||
std::uint16_t session_impl::listen_port() const
|
std::uint16_t session_impl::listen_port() const
|
||||||
{
|
{
|
||||||
return listen_port(nullptr);
|
return listen_port(nullptr);
|
||||||
|
|
Loading…
Reference in New Issue