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 flags()/set_flags()/unset_flags() to torrent_handle, deprecate individual functions
|
||||
* added alert for block being sent to the send buffer
|
||||
|
|
|
@ -198,6 +198,10 @@ namespace aux {
|
|||
// which alias the listen_socket_t shared_ptr
|
||||
std::shared_ptr<tcp::acceptor> 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
|
||||
|
@ -583,6 +587,8 @@ namespace aux {
|
|||
std::uint16_t ssl_listen_port() const override;
|
||||
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
|
||||
{
|
||||
for (auto& s : m_listen_sockets)
|
||||
|
@ -906,11 +912,6 @@ namespace aux {
|
|||
// the peer id that is generated at the start of the session
|
||||
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
|
||||
std::unique_ptr<ip_change_notifier> m_ip_notifier;
|
||||
|
||||
|
|
|
@ -586,10 +586,13 @@ namespace libtorrent {
|
|||
// the peer ID is randomized per peer.
|
||||
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
|
||||
// by libtorrent. The key may be used by the tracker to identify the
|
||||
// peer potentially across you changing your IP.
|
||||
void set_key(std::uint32_t key);
|
||||
#endif
|
||||
|
||||
// built-in peer classes
|
||||
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/torrent_info.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace lt;
|
||||
using namespace sim;
|
||||
|
||||
|
@ -989,6 +991,30 @@ TORRENT_TEST(tracker_ipv6_argument)
|
|||
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
|
||||
// torrents
|
||||
TORRENT_TEST(tracker_ipv6_argument_non_private)
|
||||
|
|
|
@ -802,6 +802,13 @@ namespace {
|
|||
p.set_str(settings_pack::peer_fingerprint, id.to_string());
|
||||
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
|
||||
|
||||
peer_id session_handle::id() const
|
||||
|
@ -809,11 +816,6 @@ namespace {
|
|||
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
|
||||
{
|
||||
return sync_call_ret<unsigned short, unsigned short(session_impl::*)() const>
|
||||
|
|
|
@ -1134,8 +1134,6 @@ namespace {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (m_key) req.key = m_key;
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
bool use_ssl = req.ssl_ctx != nullptr;
|
||||
req.ssl_ctx = &m_ssl_ctx;
|
||||
|
@ -1144,22 +1142,34 @@ namespace {
|
|||
if (req.outgoing_socket)
|
||||
{
|
||||
auto ls = req.outgoing_socket.get();
|
||||
req.listen_port = listen_port(ls);
|
||||
|
||||
req.key ^= ls->tracker_key;
|
||||
|
||||
req.listen_port =
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
// SSL torrents use the SSL listen port
|
||||
if (use_ssl) req.listen_port = ssl_listen_port(ls);
|
||||
use_ssl ? ssl_listen_port(ls) :
|
||||
#endif
|
||||
listen_port(ls);
|
||||
m_tracker_manager.queue_request(get_io_service(), req, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
// 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
|
||||
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;
|
||||
m_tracker_manager.queue_request(get_io_service(), req, c);
|
||||
}
|
||||
|
@ -1384,6 +1394,25 @@ namespace {
|
|||
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(
|
||||
listen_endpoint_t const& lep, error_code& ec)
|
||||
{
|
||||
|
@ -1591,6 +1620,8 @@ namespace {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
ret->tracker_key = get_tracker_key(ret->local_endpoint.address());
|
||||
|
||||
ret->tcp_external_port = ret->local_endpoint.port();
|
||||
TORRENT_ASSERT(ret->tcp_external_port == bind_ep.port()
|
||||
|| bind_ep.port() == 0);
|
||||
|
@ -3006,11 +3037,6 @@ namespace {
|
|||
m_peer_id = id;
|
||||
}
|
||||
|
||||
void session_impl::set_key(std::uint32_t key)
|
||||
{
|
||||
m_key = key;
|
||||
}
|
||||
|
||||
int session_impl::next_port() const
|
||||
{
|
||||
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
|
||||
{
|
||||
return listen_port(nullptr);
|
||||
|
|
Loading…
Reference in New Issue