mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-08-28 00:44:42 +00:00
Merge pull request #2490 from jpk68/size-checks
libi2pd: add missing size checks
This commit is contained in:
@@ -355,6 +355,11 @@ namespace client
|
||||
|
||||
void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < I2NP_HEADER_SIZE)
|
||||
{
|
||||
LogPrint (eLogWarning, "Destination: I2NP message is too short ", len);
|
||||
return;
|
||||
}
|
||||
I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]);
|
||||
uint32_t msgID = bufbe32toh (buf + I2NP_HEADER_MSGID_OFFSET);
|
||||
LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE,
|
||||
@@ -1205,6 +1210,11 @@ namespace client
|
||||
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len,
|
||||
i2p::garlic::ECIESX25519AEADRatchetSession * from)
|
||||
{
|
||||
if (len < 14) // 4-byte length prefix, then fromPort/toPort/protocol read at offsets up to 9 past it
|
||||
{
|
||||
LogPrint (eLogWarning, "Destination: Data message is too short ", len);
|
||||
return;
|
||||
}
|
||||
uint32_t length = bufbe32toh (buf);
|
||||
if(length > len - 4)
|
||||
{
|
||||
|
||||
@@ -465,7 +465,17 @@ namespace garlic
|
||||
|
||||
void ECIESX25519AEADRatchetSession::HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset)
|
||||
{
|
||||
if (len < 3)
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Next key block is too short ", len);
|
||||
return;
|
||||
}
|
||||
uint8_t flag = buf[0]; buf++; // flag
|
||||
if ((flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) && len < 35)
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Next key block with key is too short ", len);
|
||||
return;
|
||||
}
|
||||
if (flag & ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG)
|
||||
{
|
||||
if (!m_SendForwardKey || !m_NextSendRatchet) return;
|
||||
|
||||
@@ -1007,6 +1007,11 @@ namespace garlic
|
||||
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len,
|
||||
ECIESX25519AEADRatchetSession * from)
|
||||
{
|
||||
if (!len)
|
||||
{
|
||||
LogPrint (eLogError, "Garlic: Clove is empty");
|
||||
return;
|
||||
}
|
||||
const uint8_t * buf1 = buf;
|
||||
uint8_t flag = buf[0]; buf++; // flag
|
||||
GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
|
||||
@@ -1014,12 +1019,22 @@ namespace garlic
|
||||
{
|
||||
case eGarlicDeliveryTypeDestination:
|
||||
LogPrint (eLogDebug, "Garlic: Type destination");
|
||||
if (len < 33) // flag + 32-byte destination hash
|
||||
{
|
||||
LogPrint (eLogError, "Garlic: Message is too short");
|
||||
break;
|
||||
}
|
||||
buf += 32; // TODO: check destination
|
||||
[[fallthrough]];
|
||||
// no break here
|
||||
case eGarlicDeliveryTypeLocal:
|
||||
{
|
||||
LogPrint (eLogDebug, "Garlic: Type local");
|
||||
if ((size_t)(buf - buf1) + 9 > len) // typeid(1) + msgID(4) + expiration(4)
|
||||
{
|
||||
LogPrint (eLogError, "Garlic: Message is too short");
|
||||
break;
|
||||
}
|
||||
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
||||
uint32_t msgID = bufbe32toh (buf); buf += 4; // msgID
|
||||
buf += 4; // expiration
|
||||
|
||||
@@ -944,6 +944,11 @@ namespace data
|
||||
void NetDb::HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg)
|
||||
{
|
||||
const uint8_t * buf = msg->GetPayload ();
|
||||
if (msg->GetPayloadLength () < 65)
|
||||
{
|
||||
LogPrint (eLogWarning, "NetDb: DatabaseLookup message is too short ", msg->GetPayloadLength ());
|
||||
return;
|
||||
}
|
||||
IdentHash ident (buf);
|
||||
if (ident.IsZero ())
|
||||
{
|
||||
|
||||
+22
-9
@@ -1865,9 +1865,12 @@ namespace transport
|
||||
m_IsDataReceived = true;
|
||||
break;
|
||||
case eSSU2BlkPeerTest:
|
||||
LogPrint (eLogDebug, "SSU2: PeerTest msg=", (int)buf[offset], " code=", (int)buf[offset+1]);
|
||||
if (size >= 2)
|
||||
LogPrint (eLogDebug, "SSU2: PeerTest msg=", (int)buf[offset], " code=", (int)buf[offset+1]);
|
||||
else
|
||||
LogPrint (eLogWarning, "SSU2: PeerTest block is too short ", size);
|
||||
HandlePeerTest (buf + offset, size);
|
||||
if (buf[offset] < 5)
|
||||
if (size >= 1 && buf[offset] < 5)
|
||||
m_IsDataReceived = true;
|
||||
break;
|
||||
case eSSU2BlkNextNonce:
|
||||
@@ -1899,14 +1902,22 @@ namespace transport
|
||||
break;
|
||||
case eSSU2BlkRelayTag:
|
||||
LogPrint (eLogDebug, "SSU2: RelayTag");
|
||||
m_RelayTag = bufbe32toh (buf + offset);
|
||||
if (size >= 4)
|
||||
m_RelayTag = bufbe32toh (buf + offset);
|
||||
else
|
||||
LogPrint (eLogWarning, "SSU2: RelayTag block is too short ", size);
|
||||
break;
|
||||
case eSSU2BlkNewToken:
|
||||
{
|
||||
LogPrint (eLogDebug, "SSU2: New token");
|
||||
uint64_t token;
|
||||
memcpy (&token, buf + offset + 4, 8);
|
||||
m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, bufbe32toh (buf + offset));
|
||||
if (size >= 12)
|
||||
{
|
||||
uint64_t token;
|
||||
memcpy (&token, buf + offset + 4, 8);
|
||||
m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, bufbe32toh (buf + offset));
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "SSU2: NewToken block is too short ", size);
|
||||
break;
|
||||
}
|
||||
case eSSU2BlkPathChallenge:
|
||||
@@ -1916,7 +1927,7 @@ namespace transport
|
||||
case eSSU2BlkPathResponse:
|
||||
{
|
||||
LogPrint (eLogDebug, "SSU2: Path response");
|
||||
if (m_PathChallenge)
|
||||
if (size >= 8 && m_PathChallenge)
|
||||
{
|
||||
if (buf64toh (buf + offset) == m_PathChallenge->first)
|
||||
{
|
||||
@@ -1940,6 +1951,7 @@ namespace transport
|
||||
|
||||
void SSU2Session::HandleDateTime (const uint8_t * buf, size_t len)
|
||||
{
|
||||
if (len < 4) return;
|
||||
int64_t offset = (int64_t)i2p::util::GetSecondsSinceEpoch () - (int64_t)bufbe32toh (buf);
|
||||
switch (m_State)
|
||||
{
|
||||
@@ -2503,6 +2515,7 @@ namespace transport
|
||||
{
|
||||
case 1: // Bob from Alice
|
||||
{
|
||||
if (len < 13) return;
|
||||
auto session = m_Server.GetRandomPeerTestSession ((buf[12] == 6) ? i2p::data::RouterInfo::eSSU2V4 : i2p::data::RouterInfo::eSSU2V6,
|
||||
GetRemoteIdentity ()->GetIdentHash ());
|
||||
if (session) // session with Charlie
|
||||
@@ -2552,7 +2565,7 @@ namespace transport
|
||||
case 2: // Charlie from Bob
|
||||
{
|
||||
// sign with Charlie's key
|
||||
if (len < offset + 9) return;
|
||||
if (len < offset + 10) return;
|
||||
uint8_t asz = buf[offset + 9];
|
||||
size_t l = asz + 10 + i2p::context.GetIdentity ()->GetSignatureLen ();
|
||||
if (len < offset + l) return;
|
||||
@@ -2666,7 +2679,7 @@ namespace transport
|
||||
if (GetRouterStatus () == eRouterStatusUnknown)
|
||||
SetTestingState (true);
|
||||
auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie
|
||||
if (r && len >= offset + 9)
|
||||
if (r && len >= offset + 10)
|
||||
{
|
||||
uint8_t asz = buf[offset + 9];
|
||||
if (len < offset + asz + 10 + r->GetIdentity ()->GetSignatureLen ())
|
||||
|
||||
@@ -95,6 +95,13 @@ namespace tunnel
|
||||
uint16_t size = bufbe16toh (fragment);
|
||||
fragment += 2;
|
||||
|
||||
if (fragment + size > decrypted + TUNNEL_DATA_ENCRYPTED_SIZE)
|
||||
{
|
||||
LogPrint (eLogError, "TunnelMessage: Fragment size ", size, " exceeds tunnel data message, message dropped");
|
||||
m_CurrentMsgID = 0; m_CurrentMessage.data = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// handle fragment
|
||||
if (isFollowOnFragment)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user