From 64b2a32c9af74ea016dc76294a35647d4066d33d Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 2 Feb 2016 11:55:38 -0500 Subject: [PATCH] #343. check for malformed messages --- Identity.cpp | 3 ++- LeaseSet.cpp | 13 ++++++++++++- LeaseSet.h | 3 ++- RouterInfo.cpp | 28 +++++++++++++++++++++------- RouterInfo.h | 2 +- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Identity.cpp b/Identity.cpp index 7c8e38be..ac49b711 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -199,7 +199,7 @@ namespace data } memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE); - delete[] m_ExtendedBuffer; + delete[] m_ExtendedBuffer; m_ExtendedBuffer = nullptr; m_ExtendedLen = bufbe16toh (m_StandardIdentity.certificate + 1); if (m_ExtendedLen) { @@ -211,6 +211,7 @@ namespace data else { LogPrint (eLogError, "Identity: Certificate length ", m_ExtendedLen, " exceeds buffer length ", len - DEFAULT_IDENTITY_SIZE); + m_ExtendedLen = 0; return 0; } } diff --git a/LeaseSet.cpp b/LeaseSet.cpp index fb6ac60b..716ee6d2 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -85,13 +85,24 @@ namespace data if (readIdentity || !m_Identity) m_Identity = std::make_shared(m_Buffer, m_BufferLen); size_t size = m_Identity->GetFullLen (); + if (size > m_BufferLen) + { + LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", m_BufferLen); + m_IsValid = false; + return; + } memcpy (m_EncryptionKey, m_Buffer + size, 256); size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key uint8_t num = m_Buffer[size]; size++; // num LogPrint (eLogDebug, "LeaseSet: read num=", (int)num); - if (!num) m_IsValid = false; + if (!num || num > MAX_NUM_LEASES) + { + LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num); + m_IsValid = false; + return; + } // process leases const uint8_t * leases = m_Buffer + size; diff --git a/LeaseSet.h b/LeaseSet.h index 8135a7a1..aa9b73ad 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -31,7 +31,8 @@ namespace data } }; - const int MAX_LS_BUFFER_SIZE = 3072; + const int MAX_LS_BUFFER_SIZE = 3072; + const uint8_t MAX_NUM_LEASES = 16; class LeaseSet: public RoutingDestination { public: diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 8f2b7bfe..64b675a7 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -81,7 +81,7 @@ namespace data { s.seekg (0,std::ios::end); m_BufferLen = s.tellg (); - if (m_BufferLen < 40) + if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE) { LogPrint(eLogError, "RouterInfo: File", m_FullPath, " is malformed"); return false; @@ -109,13 +109,25 @@ namespace data { m_RouterIdentity = std::make_shared(m_Buffer, m_BufferLen); size_t identityLen = m_RouterIdentity->GetFullLen (); + if (identityLen >= m_BufferLen) + { + LogPrint (eLogError, "RouterInfo: identity length ", identityLen, " exceeds buffer size ", m_BufferLen); + m_IsUnreachable = true; + return; + } std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen)); ReadFromStream (str); + if (!str) + { + LogPrint (eLogError, "RouterInfo: malformed message"); + m_IsUnreachable = true; + return; + } if (verifySignature) { // verify signature - int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); - if (!m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l)) + int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); + if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l)) { LogPrint (eLogError, "RouterInfo: signature verification failed"); m_IsUnreachable = true; @@ -130,7 +142,7 @@ namespace data m_Timestamp = be64toh (m_Timestamp); // read addresses uint8_t numAddresses; - s.read ((char *)&numAddresses, sizeof (numAddresses)); + s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return; bool introducers = false; for (int i = 0; i < numAddresses; i++) { @@ -149,7 +161,7 @@ namespace data address.port = 0; address.mtu = 0; uint16_t size, r = 0; - s.read ((char *)&size, sizeof (size)); + s.read ((char *)&size, sizeof (size)); if (!s) return; size = be16toh (size); while (r < size) { @@ -214,17 +226,18 @@ namespace data else if (!strcmp (key, "ikey")) Base64ToByteStream (value, strlen (value), introducer.iKey, 32); } + if (!s) return; } if (isValidAddress) m_Addresses.push_back(address); } // read peers uint8_t numPeers; - s.read ((char *)&numPeers, sizeof (numPeers)); + s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; s.seekg (numPeers*32, std::ios_base::cur); // TODO: read peers // read properties uint16_t size, r = 0; - s.read ((char *)&size, sizeof (size)); + s.read ((char *)&size, sizeof (size)); if (!s) return; size = be16toh (size); while (r < size) { @@ -250,6 +263,7 @@ namespace data LogPrint (eLogError, "Unexpected netid=", value); m_IsUnreachable = true; } + if (!s) return; } if (!m_SupportedTransports || !m_Addresses.size() || (UsesIntroducer () && !introducers)) diff --git a/RouterInfo.h b/RouterInfo.h index a750cfea..2d32edef 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -182,7 +182,7 @@ namespace data std::string m_FullPath; std::shared_ptr m_RouterIdentity; uint8_t * m_Buffer; - int m_BufferLen; + size_t m_BufferLen; uint64_t m_Timestamp; std::vector
m_Addresses; std::map m_Properties;