From d0ea59c5682e9d3bb0d78015998ed732d9ce7a35 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 5 Feb 2016 08:44:09 -0500 Subject: [PATCH] add base64 buffer encoding bounds checking --- Base.h | 5 +++++ Identity.cpp | 25 +++++++++++++++++-------- SAM.cpp | 11 ++++++++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Base.h b/Base.h index 0c59ef03..d598542b 100644 --- a/Base.h +++ b/Base.h @@ -17,6 +17,11 @@ namespace data size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); + /** + Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes + */ + size_t Base64EncodingBufferSize(const size_t input_size); + template class Tag { diff --git a/Identity.cpp b/Identity.cpp index ac49b711..648c996d 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -228,26 +228,35 @@ namespace data } size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const - { + { + size_t fullLen = GetFullLen(); + if (fullLen > len) { + // buffer is too small and may overflow somewhere else + return 0; + } memcpy (buf, &m_StandardIdentity, DEFAULT_IDENTITY_SIZE); if (m_ExtendedLen > 0 && m_ExtendedBuffer) memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen); - return GetFullLen (); + return fullLen; } size_t IdentityEx::FromBase64(const std::string& s) { - uint8_t buf[1024]; - auto len = Base64ToByteStream (s.c_str(), s.length(), buf, 1024); + const size_t slen = s.length(); + const size_t bufLen = Base64EncodingBufferSize(slen); + uint8_t buf[bufLen]; + auto len = Base64ToByteStream (s.c_str(), slen, buf, 1024); return FromBuffer (buf, len); } std::string IdentityEx::ToBase64 () const { - uint8_t buf[1024]; - char str[1536]; - size_t l = ToBuffer (buf, 1024); - size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, 1536); + const size_t bufLen = GetFullLen(); + const size_t strLen = Base64EncodingBufferSize(bufLen); + uint8_t buf[bufLen]; + char str[strLen]; + size_t l = ToBuffer (buf, bufLen); + size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, strLen); str[l1] = 0; return std::string (str); } diff --git a/SAM.cpp b/SAM.cpp index a20de13d..d331a035 100644 --- a/SAM.cpp +++ b/SAM.cpp @@ -631,10 +631,15 @@ namespace client m_SocketType = eSAMSocketTypeStream; if (!m_IsSilent) { - // send remote peer address - uint8_t ident[1024]; - size_t l = stream->GetRemoteIdentity ()->ToBuffer (ident, 1024); + // get remote peer address + auto ident_ptr = stream->GetRemoteIdentity(); + size_t ident_len = ident_ptr->GetFullLen(); + uint8_t* ident = new uint8_t[ident_len]; + + // send remote peer address as base64 + size_t l = ident_ptr->ToBuffer (ident, ident_len); size_t l1 = i2p::data::ByteStreamToBase64 (ident, l, (char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); + delete[] ident; m_StreamBuffer[l1] = '\n'; HandleI2PReceive (boost::system::error_code (), l1 +1); // we send identity like it has been received from stream }