mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-10 10:52:31 -05:00
net: detect wrong-network V1 talking to V2Transport
This commit is contained in:
parent
91e1ef8684
commit
db9888feec
3 changed files with 46 additions and 3 deletions
22
src/net.cpp
22
src/net.cpp
|
@ -1109,12 +1109,29 @@ void V2Transport::ProcessReceivedMaybeV1Bytes() noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V2Transport::ProcessReceivedKeyBytes() noexcept
|
bool V2Transport::ProcessReceivedKeyBytes() noexcept
|
||||||
{
|
{
|
||||||
AssertLockHeld(m_recv_mutex);
|
AssertLockHeld(m_recv_mutex);
|
||||||
AssertLockNotHeld(m_send_mutex);
|
AssertLockNotHeld(m_send_mutex);
|
||||||
Assume(m_recv_state == RecvState::KEY);
|
Assume(m_recv_state == RecvState::KEY);
|
||||||
Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());
|
Assume(m_recv_buffer.size() <= EllSwiftPubKey::size());
|
||||||
|
|
||||||
|
// As a special exception, if bytes 4-16 of the key on a responder connection match the
|
||||||
|
// corresponding bytes of a V1 version message, but bytes 0-4 don't match the network magic
|
||||||
|
// (if they did, we'd have switched to V1 state already), assume this is a peer from
|
||||||
|
// another network, and disconnect them. They will almost certainly disconnect us too when
|
||||||
|
// they receive our uniformly random key and garbage, but detecting this case specially
|
||||||
|
// means we can log it.
|
||||||
|
static constexpr std::array<uint8_t, 12> MATCH = {'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 0, 0, 0, 0};
|
||||||
|
static constexpr size_t OFFSET = sizeof(CMessageHeader::MessageStartChars);
|
||||||
|
if (!m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) {
|
||||||
|
if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) {
|
||||||
|
LogPrint(BCLog::NET, "V2 transport error: V1 peer with wrong MessageStart %s\n",
|
||||||
|
HexStr(Span(m_recv_buffer).first(OFFSET)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_recv_buffer.size() == EllSwiftPubKey::size()) {
|
if (m_recv_buffer.size() == EllSwiftPubKey::size()) {
|
||||||
// Other side's key has been fully received, and can now be Diffie-Hellman combined with
|
// Other side's key has been fully received, and can now be Diffie-Hellman combined with
|
||||||
// our key to initialize the encryption ciphers.
|
// our key to initialize the encryption ciphers.
|
||||||
|
@ -1157,6 +1174,7 @@ void V2Transport::ProcessReceivedKeyBytes() noexcept
|
||||||
} else {
|
} else {
|
||||||
// We still have to receive more key bytes.
|
// We still have to receive more key bytes.
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool V2Transport::ProcessReceivedGarbageBytes() noexcept
|
bool V2Transport::ProcessReceivedGarbageBytes() noexcept
|
||||||
|
@ -1378,7 +1396,7 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecvState::KEY:
|
case RecvState::KEY:
|
||||||
ProcessReceivedKeyBytes();
|
if (!ProcessReceivedKeyBytes()) return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RecvState::GARB_GARBTERM:
|
case RecvState::GARB_GARBTERM:
|
||||||
|
|
|
@ -617,7 +617,7 @@ private:
|
||||||
/** Process bytes in m_recv_buffer, while in KEY_MAYBE_V1 state. */
|
/** Process bytes in m_recv_buffer, while in KEY_MAYBE_V1 state. */
|
||||||
void ProcessReceivedMaybeV1Bytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);
|
void ProcessReceivedMaybeV1Bytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);
|
||||||
/** Process bytes in m_recv_buffer, while in KEY state. */
|
/** Process bytes in m_recv_buffer, while in KEY state. */
|
||||||
void ProcessReceivedKeyBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);
|
bool ProcessReceivedKeyBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);
|
||||||
/** Process bytes in m_recv_buffer, while in GARB_GARBTERM state. */
|
/** Process bytes in m_recv_buffer, while in GARB_GARBTERM state. */
|
||||||
bool ProcessReceivedGarbageBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);
|
bool ProcessReceivedGarbageBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);
|
||||||
/** Process bytes in m_recv_buffer, while in GARBAUTH/VERSION/APP state. */
|
/** Process bytes in m_recv_buffer, while in GARBAUTH/VERSION/APP state. */
|
||||||
|
|
|
@ -1104,6 +1104,15 @@ public:
|
||||||
m_to_send.insert(m_to_send.end(), data.begin(), data.end());
|
m_to_send.insert(m_to_send.end(), data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Send V1 version message header to the transport. */
|
||||||
|
void SendV1Version(const CMessageHeader::MessageStartChars& magic)
|
||||||
|
{
|
||||||
|
CMessageHeader hdr(magic, "version", 126 + InsecureRandRange(11));
|
||||||
|
CDataStream ser(SER_NETWORK, CLIENT_VERSION);
|
||||||
|
ser << hdr;
|
||||||
|
m_to_send.insert(m_to_send.end(), UCharCast(ser.data()), UCharCast(ser.data() + ser.size()));
|
||||||
|
}
|
||||||
|
|
||||||
/** Schedule bytes to be sent to the transport. */
|
/** Schedule bytes to be sent to the transport. */
|
||||||
void Send(Span<const std::byte> data) { Send(MakeUCharSpan(data)); }
|
void Send(Span<const std::byte> data) { Send(MakeUCharSpan(data)); }
|
||||||
|
|
||||||
|
@ -1505,6 +1514,22 @@ BOOST_AUTO_TEST_CASE(v2transport_test)
|
||||||
BOOST_CHECK((*ret)[1] && (*ret)[1]->m_type == "block" && Span{(*ret)[1]->m_recv} == MakeByteSpan(msg_data_1));
|
BOOST_CHECK((*ret)[1] && (*ret)[1]->m_type == "block" && Span{(*ret)[1]->m_recv} == MakeByteSpan(msg_data_1));
|
||||||
tester.ReceiveMessage(uint8_t(3), msg_data_2); // "blocktxn" short id
|
tester.ReceiveMessage(uint8_t(3), msg_data_2); // "blocktxn" short id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send correct network's V1 header
|
||||||
|
{
|
||||||
|
V2TransportTester tester(false);
|
||||||
|
tester.SendV1Version(Params().MessageStart());
|
||||||
|
auto ret = tester.Interact();
|
||||||
|
BOOST_CHECK(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send wrong network's V1 header
|
||||||
|
{
|
||||||
|
V2TransportTester tester(false);
|
||||||
|
tester.SendV1Version(CChainParams::Main()->MessageStart());
|
||||||
|
auto ret = tester.Interact();
|
||||||
|
BOOST_CHECK(!ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
Loading…
Add table
Reference in a new issue