chore: fix memory safety issues

This commit is contained in:
jpk68
2026-08-18 15:43:44 -04:00
parent 4fa515b4fe
commit 67404cd82f
7 changed files with 85 additions and 15 deletions
+15 -3
View File
@@ -276,9 +276,21 @@ namespace client
auto it = m_MethodHandlers.find (method);
if (it != m_MethodHandlers.end ())
{
response << "{\"id\":" << id << ",\"result\":{";
(this->*(it->second))(pt.get_child ("params"), response);
response << "},\"jsonrpc\":\"2.0\"}\n";
auto params = pt.get_child ("params");
if (method != "Authenticate" &&
!m_Tokens.count (params.get<std::string> ("Token", "")))
{
LogPrint (eLogWarning, "I2PControl: Invalid or missing token for method ", method);
response << "{\"id\":null,\"error\":";
response << "{\"code\":-32602,\"message\":\"Invalid or missing token\"},";
response << "\"jsonrpc\":\"2.0\"}\n";
}
else
{
response << "{\"id\":" << id << ",\"result\":{";
(this->*(it->second))(params, response);
response << "},\"jsonrpc\":\"2.0\"}\n";
}
}
else
{
+13 -1
View File
@@ -81,6 +81,18 @@ namespace data
LogPrint (eLogError, "Blinding: Unknown signature type ", (int)m_SigType, " in b33");
}
bool BlindedPublicKey::IsValid () const
{
switch (m_SigType)
{
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
return true;
default:
return false;
}
}
std::string BlindedPublicKey::ToB33 () const
{
if (m_PublicKey.size () > 32) return ""; // assume 25519
@@ -183,7 +195,7 @@ namespace data
i2p::data::IdentHash BlindedPublicKey::GetStoreHash (const char * date) const
{
i2p::data::IdentHash hash;
i2p::data::IdentHash hash{};
uint8_t blinded[i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH]; // 32 max
size_t publicKeyLength = 0;
if (date)
+1 -1
View File
@@ -32,7 +32,7 @@ namespace data
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
bool IsValid () const; // signature type must be blindable
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length
+23 -6
View File
@@ -575,6 +575,11 @@ namespace garlic
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{
if (len < 2)
{
LogPrint (eLogError, "Garlic: AES block length ", len, " is too short");
return;
}
uint16_t tagCount = bufbe16toh (buf);
buf += 2; len -= 2;
if (tagCount > 0)
@@ -590,18 +595,30 @@ namespace garlic
}
buf += tagCount*32;
len -= tagCount*32;
if (len < 37) // 4 (payload size) + 32 (payload hash) + 1 (flag)
{
LogPrint (eLogError, "Garlic: AES block is too short for payload header, length ", len);
return;
}
uint32_t payloadSize = bufbe32toh (buf);
buf += 4; len -= 4;
uint8_t * payloadHash = buf;
buf += 32; len -= 32; // payload hash.
if (*buf) // session key?
{
if (len < 33) // 32 (new session key) + 1 (flag)
{
LogPrint (eLogError, "Garlic: AES block is too short for session key, length ", len);
return;
}
buf += 32; len -= 32; // new session key
}
buf++; len--; // flag
if (payloadSize > len)
{
LogPrint (eLogError, "Garlic: Unexpected payload size ", payloadSize);
return;
}
buf += 4;
uint8_t * payloadHash = buf;
buf += 32;// payload hash.
if (*buf) // session key?
buf += 32; // new session key
buf++; // flag
// payload
uint8_t digest[32];
+26
View File
@@ -661,12 +661,18 @@ namespace data
size_t LeaseSet2::ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const
{
if (len < 1) return 0;
size_t offset = 0;
uint8_t flag = buf[offset]; offset++; // flag
if (flag & 0x01) // client auth
{
if (!(flag & 0x0E)) // DH, bit 1-3 all zeroes
{
if (offset + 34 > len) // ephemeralPublicKey(32) + numClients(2)
{
LogPrint (eLogError, "LeaseSet2: Buffer too short for DH auth data header");
return 0;
}
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
@@ -693,6 +699,11 @@ namespace data
}
else if (flag & 0x02) // PSK, bit 1 is set to 1
{
if (offset + 34 > len) // authSalt(32) + numClients(2)
{
LogPrint (eLogError, "LeaseSet2: Buffer too short for PSK auth data header");
return 0;
}
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
@@ -854,6 +865,11 @@ namespace data
size += 256;
// signing key (unused)
size += ident.GetSigningPublicKeyLen ();
if (size + 1 > sz)
{
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", sz);
return false;
}
uint8_t numLeases = ptr[size];
++size;
if (!numLeases || numLeases > MAX_NUM_LEASES)
@@ -861,6 +877,11 @@ namespace data
LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)numLeases);
return false;
}
if (size + numLeases*LEASE_SIZE > sz)
{
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", sz);
return false;
}
const uint8_t * leases = ptr + size;
expires = 0;
/** find lease with the max expiration timestamp */
@@ -872,6 +893,11 @@ namespace data
if(endDate > expires)
expires = endDate;
}
if ((size_t)(leases - ptr) + ident.GetSignatureLen () > sz)
{
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", sz);
return false;
}
return ident.Verify(ptr, leases - ptr, leases);
}
+6 -3
View File
@@ -2283,7 +2283,8 @@ namespace transport
if (!r) LogPrint (eLogWarning, "SSU2: RelayRequest Alice's router info not found");
auto packet = m_Server.GetSentPacketsPool ().AcquireShared ();
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0;
size_t riMaxLen = (len + 32 < m_MaxPayloadSize) ? m_MaxPayloadSize - len - 32 : 0;
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, riMaxLen, r) : 0;
if (!packet->payloadSize && r)
session->SendFragmentedMessage (CreateDatabaseStoreMsg (r));
packet->payloadSize += CreateRelayIntroBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize, buf + 1, len - 1);
@@ -2526,7 +2527,8 @@ namespace transport
// Alice's RouterInfo
auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ());
if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr;
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0;
size_t riMaxLen = (len + 32 < m_MaxPayloadSize) ? m_MaxPayloadSize - len - 32 : 0;
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, riMaxLen, r) : 0;
if (!packet->payloadSize && r)
session->SendFragmentedMessage (CreateDatabaseStoreMsg (r));
if (packet->payloadSize + len + 48 > m_MaxPayloadSize)
@@ -2645,7 +2647,8 @@ namespace transport
// Charlie's RouterInfo
auto r = i2p::data::netdb.FindRouter (GetRemoteIdentity ()->GetIdentHash ());
if (r && (r->IsUnreachable () || !i2p::data::netdb.PopulateRouterInfoBuffer (r))) r = nullptr;
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0;
size_t riMaxLen = (len + 32 < m_MaxPayloadSize) ? m_MaxPayloadSize - len - 32 : 0;
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, riMaxLen, r) : 0;
if (!packet->payloadSize && r)
aliceSession->SendFragmentedMessage (CreateDatabaseStoreMsg (r));
if (packet->payloadSize + len + 16 > m_MaxPayloadSize)
+1 -1
View File
@@ -779,7 +779,7 @@ namespace client
auto res = std::from_chars(sizeStr.data(), sizeStr.data() + sizeStr.size(), size);
if (res.ec != std::errc()) size = 0;
size_t offset = data - buf;
if (offset + size <= len)
if (offset <= len && size <= len - offset)
{
auto session = m_Owner.FindSession(m_ID);
if (session)