From 47460d86b2a6a60398028abfd6bc1550b95e03fc Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Jun 2022 12:55:58 -0400 Subject: [PATCH] verify signature and send peer test msg 5 --- libi2pd/SSU2.cpp | 8 +++++++ libi2pd/SSU2.h | 3 ++- libi2pd/SSU2Session.cpp | 49 ++++++++++++++++++++++++++++++++++++----- libi2pd/SSU2Session.h | 3 +-- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/libi2pd/SSU2.cpp b/libi2pd/SSU2.cpp index 83653d8f..6e0a7d79 100644 --- a/libi2pd/SSU2.cpp +++ b/libi2pd/SSU2.cpp @@ -237,6 +237,14 @@ namespace transport m_PendingOutgoingSessions.emplace (session->GetRemoteEndpoint (), session); } + std::shared_ptr SSU2Server::FindSession (const i2p::data::IdentHash& ident) const + { + auto it = m_SessionsByRouterHash.find (ident); + if (it != m_SessionsByRouterHash.end ()) + return it->second; + return nullptr; + } + void SSU2Server::AddRelay (uint32_t tag, std::shared_ptr relay) { m_Relays.emplace (tag, relay); diff --git a/libi2pd/SSU2.h b/libi2pd/SSU2.h index c52322df..d5939a31 100644 --- a/libi2pd/SSU2.h +++ b/libi2pd/SSU2.h @@ -53,7 +53,8 @@ namespace transport void RemoveSession (uint64_t connID); void AddSessionByRouterHash (std::shared_ptr session); void AddPendingOutgoingSession (std::shared_ptr session); - + std::shared_ptr FindSession (const i2p::data::IdentHash& ident) const; + void AddRelay (uint32_t tag, std::shared_ptr relay); void RemoveRelay (uint32_t tag); std::shared_ptr FindRelaySession (uint32_t tag); diff --git a/libi2pd/SSU2Session.cpp b/libi2pd/SSU2Session.cpp index 4ad34b74..45edf729 100644 --- a/libi2pd/SSU2Session.cpp +++ b/libi2pd/SSU2Session.cpp @@ -839,8 +839,7 @@ namespace transport return true; } - void SSU2Session::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, - const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey) + void SSU2Session::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey) { Header header; uint8_t h[32], payload[SSU2_MAX_PAYLOAD_SIZE]; @@ -859,7 +858,7 @@ namespace transport htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ()); size_t payloadSize = 7; if (msg == 6 || msg == 7) - payloadSize += CreateAddressBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, ep); + payloadSize += CreateAddressBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, m_RemoteEndpoint); payloadSize += CreatePeerTestBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize, msg, eSSU2PeerTestCodeAccept, nullptr, signedData, signedDataLen); payloadSize += CreatePaddingBlock (payload + payloadSize, SSU2_MAX_PAYLOAD_SIZE - payloadSize); @@ -873,7 +872,7 @@ namespace transport memset (n, 0, 12); i2p::crypto::ChaCha20 (h + 16, 16, introKey, n, h + 16); // send - m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep); + m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint); } bool SSU2Session::ProcessPeerTest (uint8_t * buf, size_t len) @@ -1348,7 +1347,43 @@ namespace transport auto r = i2p::data::netdb.FindRouter (buf + 3); // find Alice if (r) { - // TODO: send msg 5 to Alice + size_t signatureLen = r->GetIdentity ()->GetSignatureLen (); + if (len >= 35 + signatureLen) + { + SignedData s; + s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue + s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash + s.Insert (buf + 35 + signatureLen, len - 35 - signatureLen); // signed data + if (s.Verify (r->GetIdentity (), buf + (len - signatureLen))) + { + if (!m_Server.FindSession (r->GetIdentity ()->GetIdentHash ())) + { + boost::asio::ip::udp::endpoint ep; + std::shared_ptr addr; + if (ExtractEndpoint (buf + 44, len - 44, ep)) + addr = ep.address ().is_v4 () ? r->GetSSU2V4Address () : r->GetSSU2V6Address (); + if (addr) + { + // TODO: compare ep with addr + // send msg 5 to Alice + auto session = std::make_shared (m_Server, r, addr); + session->SetState (eSSU2SessionStatePeerTest); + session->m_DestConnID = htobe64 (((uint64_t)nonce << 32) | nonce); + session->m_SourceConnID = ~session->m_SourceConnID; + m_Server.AddSession (session); + session->SendPeerTest (5, buf + 35, len - 35, addr->i); + } + else + code = eSSU2PeerTestCodeCharlieUnsupportedAddress; + } + else + code = eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected; + } + else + code = eSSU2PeerTestCodeCharlieSignatureFailure; + } + else // maformed message + code = eSSU2PeerTestCodeCharlieReasonUnspecified; } else code = eSSU2PeerTestCodeCharlieAliceIsUnknown; @@ -1393,9 +1428,11 @@ namespace transport if (htobe64 (((uint64_t)nonce << 32) | nonce) != m_SourceConnID) LogPrint (eLogWarning, "SSU2: Peer test 5 nonce mismatch ", nonce); break; - case 6: // Chralie from Alice + case 6: // Charlie from Alice + m_Server.RemoveSession (~htobe64 (((uint64_t)nonce << 32) | nonce)); break; case 7: // Alice from Charlie 2 + m_Server.RemoveSession (htobe64 (((uint64_t)nonce << 32) | nonce)); break; default: LogPrint (eLogWarning, "SSU2: PeerTest unexpected msg num ", buf[0]); diff --git a/libi2pd/SSU2Session.h b/libi2pd/SSU2Session.h index df7480b1..6be69080 100644 --- a/libi2pd/SSU2Session.h +++ b/libi2pd/SSU2Session.h @@ -205,8 +205,7 @@ namespace transport void SendQuickAck (); void SendTermination (); void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey); - void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, - const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey); // PeerTest message + void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message void HandlePayload (const uint8_t * buf, size_t len); void HandleAck (const uint8_t * buf, size_t len);