feature to encrypt peer connections with a secret AES-256 key stored in .torrent file
This commit is contained in:
@@ -37,6 +37,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <memory> // autp_ptr
|
||||
#endif
|
||||
|
||||
#include "libtorrent/bt_peer_connection.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/identify_client.hpp"
|
||||
@@ -127,6 +131,21 @@ namespace libtorrent
|
||||
m_in_constructor = false;
|
||||
#endif
|
||||
memset(m_reserved_bits, 0, sizeof(m_reserved_bits));
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
boost::shared_ptr<torrent> t = tor.lock();
|
||||
std::string const key = t->torrent_file().encryption_key();
|
||||
if (key.size() == 32)
|
||||
{
|
||||
m_enc_handler.reset(new aes256_handler);
|
||||
m_enc_handler->set_incoming_key((const unsigned char*)key.c_str(), key.size());
|
||||
m_encrypted = true;
|
||||
m_rc4_encrypted = true;
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
peer_log("*** encrypted torrent. enabling AES-256 encryption");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bt_peer_connection::bt_peer_connection(
|
||||
@@ -198,7 +217,19 @@ namespace libtorrent
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
|
||||
pe_settings::enc_policy const& out_enc_policy = m_ses.get_pe_settings().out_enc_policy;
|
||||
pe_settings::enc_policy out_enc_policy = m_ses.get_pe_settings().out_enc_policy;
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
// if this torrent is using AES-256 encryption, don't
|
||||
// also enable the normal encryption
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
std::string const key = t->torrent_file().encryption_key();
|
||||
if (key.size() == 32) out_enc_policy = pe_settings::disabled;
|
||||
#endif
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
char const* policy_name[] = {"forced", "enabled", "disabled"};
|
||||
peer_log("*** outgoing encryption policy: %s", policy_name[out_enc_policy]);
|
||||
#endif
|
||||
|
||||
if (out_enc_policy == pe_settings::forced)
|
||||
{
|
||||
@@ -2532,6 +2563,13 @@ namespace libtorrent
|
||||
for (i = m_ses.m_torrents.begin(); i != m_ses.m_torrents.end(); ++i)
|
||||
{
|
||||
torrent const& ti = *i->second;
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
// don't consider encrypted torrents (since that would
|
||||
// open up a hole to connecting to them without the key)
|
||||
if (ti.torrent_file().encryption_key().size() == 32) continue;
|
||||
#endif
|
||||
|
||||
sha1_hash const& skey_hash = ti.obfuscated_hash();
|
||||
sha1_hash obfs_hash = m_dh_key_exchange->get_hash_xor_mask();
|
||||
obfs_hash ^= skey_hash;
|
||||
@@ -2541,7 +2579,7 @@ namespace libtorrent
|
||||
{
|
||||
if (!t)
|
||||
{
|
||||
attach_to_torrent(ti.info_hash());
|
||||
attach_to_torrent(ti.info_hash(), false);
|
||||
if (is_disconnecting()) return;
|
||||
|
||||
t = associated_torrent().lock();
|
||||
@@ -2889,52 +2927,102 @@ namespace libtorrent
|
||||
recv_buffer = receive_buffer();
|
||||
|
||||
int packet_size = recv_buffer[0];
|
||||
const char protocol_string[] = "BitTorrent protocol";
|
||||
const char protocol_string[] = "\x13" "BitTorrent protocol";
|
||||
|
||||
if (packet_size != 19 ||
|
||||
!std::equal(recv_buffer.begin + 1, recv_buffer.begin + 19, protocol_string))
|
||||
memcmp(recv_buffer.begin, protocol_string, 20) != 0)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
if (!is_local() && m_ses.get_pe_settings().in_enc_policy == pe_settings::disabled)
|
||||
{
|
||||
disconnect(errors::no_incoming_encrypted);
|
||||
return;
|
||||
}
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
peer_log("*** unrecognized protocol header");
|
||||
#endif
|
||||
|
||||
// Don't attempt to perform an encrypted handshake
|
||||
// within an encrypted connection
|
||||
if (!m_encrypted && !is_local())
|
||||
bool found_encrypted_torrent = false;
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
if (!is_local())
|
||||
{
|
||||
std::auto_ptr<encryption_handler> handler(new aes256_handler);
|
||||
boost::uint8_t temp_pad[20];
|
||||
|
||||
for (std::set<boost::shared_ptr<torrent> >::iterator i = m_ses.m_encrypted_torrents.begin()
|
||||
, end(m_ses.m_encrypted_torrents.end()); i != end; ++i)
|
||||
{
|
||||
boost::shared_ptr<torrent> t = *i;
|
||||
std::string const key = t->torrent_file().encryption_key();
|
||||
TORRENT_ASSERT(key.size() == 32);
|
||||
handler->set_incoming_key((const unsigned char*)key.c_str(), key.size());
|
||||
std::memcpy(temp_pad, recv_buffer.begin, 20);
|
||||
handler->decrypt((char*)temp_pad, 20);
|
||||
if (memcmp(temp_pad, protocol_string, 20) != 0) continue;
|
||||
|
||||
// we found the key that could decrypt it
|
||||
m_rc4_encrypted = true;
|
||||
m_encrypted = true;
|
||||
m_enc_handler.reset(handler.release());
|
||||
found_encrypted_torrent = true;
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
peer_log("*** found encrypted torrent");
|
||||
#endif
|
||||
TORRENT_ASSERT(recv_buffer.left() == 20);
|
||||
// handler->decrypt((char*)recv_buffer.begin + 20, recv_buffer.left() - 20);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!found_encrypted_torrent)
|
||||
{
|
||||
|
||||
if (!is_local()
|
||||
&& m_ses.get_pe_settings().in_enc_policy == pe_settings::disabled)
|
||||
{
|
||||
disconnect(errors::no_incoming_encrypted);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't attempt to perform an encrypted handshake
|
||||
// within an encrypted connection. For local connections,
|
||||
// we're expected to already have passed the encrypted
|
||||
// handshake by this point
|
||||
if (m_encrypted || is_local())
|
||||
{
|
||||
disconnect(errors::invalid_info_hash, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
peer_log("*** attempting encrypted connection");
|
||||
#endif
|
||||
m_state = read_pe_dhkey;
|
||||
cut_receive_buffer(0, dh_key_len);
|
||||
TORRENT_ASSERT(!packet_finished());
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT((!is_local() && m_encrypted) || is_local());
|
||||
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
#else
|
||||
disconnect(errors::invalid_info_hash, 1);
|
||||
return;
|
||||
#endif // TORRENT_DISABLE_ENCRYPTION
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
TORRENT_ASSERT(m_state != read_pe_dhkey);
|
||||
|
||||
if (!is_local() &&
|
||||
(m_ses.get_pe_settings().in_enc_policy == pe_settings::forced) &&
|
||||
!m_encrypted)
|
||||
else
|
||||
{
|
||||
disconnect(errors::no_incoming_regular);
|
||||
return;
|
||||
}
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
TORRENT_ASSERT(m_state != read_pe_dhkey);
|
||||
|
||||
if (!is_local() &&
|
||||
(m_ses.get_pe_settings().in_enc_policy == pe_settings::forced) &&
|
||||
!m_encrypted)
|
||||
{
|
||||
disconnect(errors::no_incoming_regular);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
peer_log("<== BitTorrent protocol");
|
||||
peer_log("<== BitTorrent protocol");
|
||||
#endif
|
||||
}
|
||||
|
||||
m_state = read_info_hash;
|
||||
reset_recv_buffer(28);
|
||||
@@ -2990,7 +3078,7 @@ namespace libtorrent
|
||||
std::copy(recv_buffer.begin + 8, recv_buffer.begin + 28
|
||||
, (char*)info_hash.begin());
|
||||
|
||||
attach_to_torrent(info_hash);
|
||||
attach_to_torrent(info_hash, m_encrypted && m_rc4_encrypted);
|
||||
if (is_disconnecting()) return;
|
||||
}
|
||||
else
|
||||
|
Reference in New Issue
Block a user