Skip to content

Commit

Permalink
merged RC_2_0 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
arvidn committed Apr 12, 2022
2 parents 2485348 + 07a5305 commit 61ab0eb
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 82 deletions.
7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -660,18 +660,21 @@ if (NOT Windows)
return 0;
}
]=])
string(REPLACE "std::atomic<int>" "std::atomic<std::int8_t>" ATOMICS8_TEST_SOURCE "${ATOMICS_TEST_SOURCE}")
string(REPLACE "std::atomic<int>" "std::atomic<std::int64_t>" ATOMICS64_TEST_SOURCE "${ATOMICS_TEST_SOURCE}")

if(APPLE)
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
endif()
check_cxx_source_compiles("${ATOMICS_TEST_SOURCE}" HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_cxx_source_compiles("${ATOMICS8_TEST_SOURCE}" HAVE_CXX_ATOMICS8_WITHOUT_LIB)
check_cxx_source_compiles("${ATOMICS64_TEST_SOURCE}" HAVE_CXX_ATOMICS64_WITHOUT_LIB)
if((NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) OR (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB))
if((NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) OR (NOT HAVE_CXX_ATOMICS8_WITHOUT_LIB) OR (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB))
set(CMAKE_REQUIRED_LIBRARIES "atomic")
check_cxx_source_compiles("${ATOMICS_TEST_SOURCE}" HAVE_CXX_ATOMICS_WITH_LIB)
check_cxx_source_compiles("${ATOMICS8_TEST_SOURCE}" HAVE_CXX_ATOMICS8_WITH_LIB)
check_cxx_source_compiles("${ATOMICS64_TEST_SOURCE}" HAVE_CXX_ATOMICS64_WITH_LIB)
if ((NOT HAVE_CXX_ATOMICS_WITH_LIB) OR (NOT HAVE_CXX_ATOMICS64_WITH_LIB))
if ((NOT HAVE_CXX_ATOMICS_WITH_LIB) OR (NOT HAVE_CXX_ATOMICS8_WITH_LIB) OR (NOT HAVE_CXX_ATOMICS64_WITH_LIB))
message(STATUS, "No native support for std::atomic, or libatomic not found! Build link step may fail")
else()
message(STATUS "Linking with libatomic for atomics support")
Expand Down
3 changes: 1 addition & 2 deletions Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,7 @@ rule linking ( properties * )
result += <framework>CoreFoundation <framework>SystemConfiguration ;
}

if ( <toolset>gcc in $(properties)
|| <toolset>clang in $(properties) )
if <toolset>gcc in $(properties)
&& <target-os>linux in $(properties)
&& ( <asserts>on in $(properties)
|| <asserts>production in $(properties)
Expand Down
5 changes: 4 additions & 1 deletion include/libtorrent/aux_/bt_peer_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,10 @@ namespace libtorrent::aux {

private:

#if !defined TORRENT_DISABLE_ENCRYPTION
void init_bt_handshake();
#endif

enum class state_t : std::uint8_t
{
#if !defined TORRENT_DISABLE_ENCRYPTION
Expand All @@ -351,7 +355,6 @@ namespace libtorrent::aux {
read_pe_cryptofield,
read_pe_pad,
read_pe_ia,
init_bt_handshake,
#endif
read_protocol_identifier,
read_info_hash,
Expand Down
1 change: 0 additions & 1 deletion include/libtorrent/aux_/pe_crypto.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ namespace libtorrent::aux {
{
public:
dh_key_exchange();
bool good() const { return true; }

// Get local public key
key_t const& get_local_key() const { return m_dh_local_key; }
Expand Down
2 changes: 2 additions & 0 deletions include/libtorrent/aux_/torrent_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ struct torrent_list
#endif

TORRENT_ASSERT(all_torrents == all_indexed_torrents);
#if !defined TORRENT_DISABLE_ENCRYPTION
TORRENT_ASSERT(all_torrents == all_obf_indexed_torrents);
#endif
}
#endif

Expand Down
155 changes: 79 additions & 76 deletions src/bt_peer_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ namespace {
#endif

m_dh_key_exchange.reset(new (std::nothrow) dh_key_exchange);
if (!m_dh_key_exchange || !m_dh_key_exchange->good())
if (!m_dh_key_exchange)
{
disconnect(errors::no_memory, operation_t::encryption);
return;
Expand Down Expand Up @@ -2714,6 +2714,44 @@ namespace {
on_receive_impl(bytes_transferred);
}

#if !defined TORRENT_DISABLE_ENCRYPTION
void bt_peer_connection::init_bt_handshake()
{
m_encrypted = true;
if (m_rc4_encrypted)
{
switch_send_crypto(m_rc4);
switch_recv_crypto(m_rc4);
}

// decrypt remaining received bytes
if (m_rc4_encrypted)
{
span<char> const remaining = m_recv_buffer.mutable_buffer()
.subspan(m_recv_buffer.packet_size());
rc4_decrypt(remaining);

#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION"
, "decrypted remaining %d bytes", int(remaining.size()));
#endif
}
m_rc4.reset();

// encrypted portion of handshake completed, toggle
// peer_info pe_support flag back to true
if (is_outgoing() &&
m_settings.get_int(settings_pack::out_enc_policy)
== settings_pack::pe_enabled)
{
torrent_peer* pi = peer_info_struct();
TORRENT_ASSERT(pi);

pi->pe_support = true;
}
}
#endif

void bt_peer_connection::on_receive_impl(std::size_t bytes_transferred)
{
auto t = associated_torrent().lock();
Expand Down Expand Up @@ -3104,30 +3142,28 @@ namespace {
m_rc4_encrypted = true;
}

int const len_pad = aux::read_int16(recv_buffer);
int len_pad = aux::read_int16(recv_buffer);
if (len_pad < 0 || len_pad > 512)
{
disconnect(errors::invalid_pad_size, operation_t::encryption, peer_error);
return;
}

m_state = state_t::read_pe_pad;
// len(IA) at the end of pad
if (!is_outgoing())
m_recv_buffer.reset(len_pad + 2); // len(IA) at the end of pad
len_pad += 2;

if (len_pad > 0)
{
m_state = state_t::read_pe_pad;
m_recv_buffer.reset(len_pad);
}
else
{
if (len_pad == 0)
{
m_encrypted = true;
if (m_rc4_encrypted)
{
switch_send_crypto(m_rc4);
switch_recv_crypto(m_rc4);
}
m_state = state_t::init_bt_handshake;
}
else
m_recv_buffer.reset(len_pad);
TORRENT_ASSERT(len_pad == 0);
init_bt_handshake();
m_state = state_t::read_protocol_identifier;
m_recv_buffer.reset(20);
}
}

Expand All @@ -3149,55 +3185,51 @@ namespace {
recv_buffer = recv_buffer.subspan(pad_size);
int const len_ia = aux::read_int16(recv_buffer);

if (len_ia < 0)
#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "len(IA) : %d", len_ia);
#endif
if (len_ia < 0 || len_ia > 68)
{
disconnect(errors::invalid_encrypt_handshake, operation_t::encryption, peer_error);
return;
}

#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION", "len(IA) : %d", len_ia);
#endif
if (len_ia == 0)
{
// everything after this is Encrypt2
m_encrypted = true;
if (m_rc4_encrypted)
{
switch_send_crypto(m_rc4);
switch_recv_crypto(m_rc4);
}
m_state = state_t::init_bt_handshake;
// everything after this is encrypted
init_bt_handshake();
m_state = state_t::read_protocol_identifier;
m_recv_buffer.reset(20);
}
else
{
// The other peer indicated that a non-zero bytes will be
// encrypted at the start of the underlying bittorrent
// protocol. This number of bytes, len_ia, is not
// necessarily aligned to message boundaries. We first read
// that many bytes, decrypt it, and then pass it back into
// the regular protocol parser
m_state = state_t::read_pe_ia;
m_recv_buffer.reset(len_ia);
}
}
else // is_outgoing()
{
// everything that arrives after this is Encrypt2
m_encrypted = true;
if (m_rc4_encrypted)
{
switch_send_crypto(m_rc4);
switch_recv_crypto(m_rc4);
}
m_state = state_t::init_bt_handshake;
// everything that arrives after this is encrypted
init_bt_handshake();
m_state = state_t::read_protocol_identifier;
m_recv_buffer.reset(20);
}
}

if (m_state == state_t::read_pe_ia)
{
received_bytes(0, int(bytes_transferred));
bytes_transferred = 0;
TORRENT_ASSERT(!is_outgoing());
TORRENT_ASSERT(!m_encrypted);

if (!m_recv_buffer.packet_finished()) return;

// ia is always rc4, so decrypt it
// the IA bytes are always rc4, so decrypt it
rc4_decrypt(m_recv_buffer.mutable_buffer().first(m_recv_buffer.packet_size()));

#ifndef TORRENT_DISABLE_LOGGING
Expand All @@ -3214,47 +3246,14 @@ namespace {
}
m_rc4.reset();

// now that we have decrypted IA length of bytes, we
// reinterpret the receive buffer as the very start of a normal
// connection. First we expect to find the protocol identifier
// (i.e. "BitTorrent Protocol")
m_state = state_t::read_protocol_identifier;
m_recv_buffer.cut(0, 20);
}

if (m_state == state_t::init_bt_handshake)
{
received_bytes(0, int(bytes_transferred));
bytes_transferred = 0;
TORRENT_ASSERT(m_encrypted);

// decrypt remaining received bytes
if (m_rc4_encrypted)
{
span<char> const remaining = m_recv_buffer.mutable_buffer()
.subspan(m_recv_buffer.packet_size());
rc4_decrypt(remaining);

#ifndef TORRENT_DISABLE_LOGGING
peer_log(peer_log_alert::info, "ENCRYPTION"
, "decrypted remaining %d bytes", int(remaining.size()));
#endif
}
m_rc4.reset();

// payload stream, start with 20 handshake bytes
m_state = state_t::read_protocol_identifier;
m_recv_buffer.reset(20);

// encrypted portion of handshake completed, toggle
// peer_info pe_support flag back to true
if (is_outgoing() &&
m_settings.get_int(settings_pack::out_enc_policy)
== settings_pack::pe_enabled)
{
torrent_peer* pi = peer_info_struct();
TORRENT_ASSERT(pi);

pi->pe_support = true;
}
}

#endif // #if !defined TORRENT_DISABLE_ENCRYPTION

if (m_state == state_t::read_protocol_identifier)
Expand Down Expand Up @@ -3312,6 +3311,10 @@ namespace {
peer_log(peer_log_alert::info, "ENCRYPTION", "attempting encrypted connection");
#endif
m_state = state_t::read_pe_dhkey;
// we're "cutting" off 0 bytes from the receive buffer here
// because we want to interpret it as something else. It didn't
// contain the expected bittorrent handshake string, so let's
// try again to interpret it as an encrypted handshake
m_recv_buffer.cut(0, dh_key_len);
TORRENT_ASSERT(!m_recv_buffer.packet_finished());
return;
Expand Down

0 comments on commit 61ab0eb

Please sign in to comment.