diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 6167960b..f174af20 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -709,7 +709,9 @@ namespace http { if (i2cpServer) { s << "I2CP " << tr("Local Destination") << ":
\r\n
\r\n"; - auto session = i2cpServer->FindSessionByID ((uint16_t)std::stoi (id)); + std::shared_ptr session; + try { session = i2cpServer->FindSessionByID ((uint16_t)std::stoi (id)); } + catch (std::exception&) {} if (session) ShowLeaseSetDestination (s, session->GetDestination (), 0); else @@ -1505,7 +1507,19 @@ namespace http { std::string redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=commands"; std::string token = params["token"]; - if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) + if (token.empty ()) + { + ShowError(s, tr("Invalid token")); + return; + } + int tokenValue; + try { tokenValue = std::stoi (token); } + catch (std::exception&) + { + ShowError(s, tr("Invalid token")); + return; + } + if (m_Tokens.find (tokenValue) == m_Tokens.end ()) { ShowError(s, tr("Invalid token")); return; diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 13ecb372..a1bc9594 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -260,6 +260,11 @@ namespace client LogPrint (eLogError, "I2PControl: Malformed request, HTTP header expected"); return; // TODO: } + if (contentLength > I2P_CONTROL_MAX_CONTENT_LENGTH) + { + LogPrint (eLogError, "I2PControl: Content-Length ", contentLength, " exceeds maximum allowed size"); + return; + } std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read while (rem > 0) // read in chunks to prevent buffer overflow { diff --git a/daemon/I2PControl.h b/daemon/I2PControl.h index d39d3130..2b2f0f37 100644 --- a/daemon/I2PControl.h +++ b/daemon/I2PControl.h @@ -28,6 +28,7 @@ namespace client { const size_t I2P_CONTROL_MAX_REQUEST_SIZE = 1024; typedef std::array I2PControlBuffer; + const size_t I2P_CONTROL_MAX_CONTENT_LENGTH = 65536; // sanity limit on declared HTTP Content-Length const uint64_t I2P_CONTROL_TOKEN_LIFETIME = 60*60; // 1 hour, in seconds const long I2P_CONTROL_CERTIFICATE_VALIDITY = 365*10; // 10 years diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index becd4439..66ff402a 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -556,6 +556,7 @@ namespace data if (allzeros) { // offline information + if (ret + 6 > len) return 0; // expires(4) + key type(2) const uint8_t * offlineInfo = buf + ret; uint32_t expires = bufbe32toh (buf + ret); ret += 4; // expires timestamp if (expires < i2p::util::GetSecondsSinceEpoch ()) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 036a0fb5..14249d07 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -1419,6 +1419,7 @@ namespace data void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); + std::lock_guard lock(m_LeaseSetsMutex); for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();) { if (!it->second->IsValid () || ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 26a2bcb6..f775011e 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -270,7 +270,7 @@ namespace data if (it != m_SigningKeys.end ()) { // TODO: implement all signature types - if (signatureType == SIGNING_KEY_TYPE_RSA_SHA512_4096) + if (signatureType == SIGNING_KEY_TYPE_RSA_SHA512_4096 && signatureLength >= SHA512_DIGEST_LENGTH) { size_t pos = s.tellg (); size_t tbsLen = pos + contentLength; @@ -282,7 +282,7 @@ namespace data // RSA-raw { // calculate digest - uint8_t digest[64]; + uint8_t digest[SHA512_DIGEST_LENGTH]; SHA512 (tbs, tbsLen, digest); // encrypt signature BN_CTX * bnctx = BN_CTX_new (); @@ -294,7 +294,7 @@ namespace data i2p::crypto::bn2buf (s, enSigBuf, signatureLength); // digest is right aligned // we can't use RSA_verify due wrong padding in SU3 - if (memcmp (enSigBuf + (signatureLength - 64), digest, 64)) + if (memcmp (enSigBuf + (signatureLength - SHA512_DIGEST_LENGTH), digest, SHA512_DIGEST_LENGTH)) LogPrint (eLogWarning, "Reseed: SU3 signature verification failed"); else verify = false; // verified diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 43fbc6ca..ca207083 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -644,11 +644,12 @@ namespace data std::string_view RouterInfo::ExtractString (const uint8_t * buf, size_t len) const { + if (!len) return {}; uint8_t l = buf[0]; - if (l > len) + if (l > len - 1) { LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len); - l = len; + l = len - 1; } return { (const char *)(buf + 1), l }; } diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index d618cc0f..9cbb6ff9 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -272,7 +272,7 @@ namespace util { if (!len) return { }; uint8_t l = buf[0]; - if (l > len) l = len; + if (l > len - 1) l = len - 1; return { (const char *)(buf + 1), l }; } diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 1da57f7c..cd2a78be 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -882,6 +882,11 @@ namespace client void I2CPSession::CreateLeaseSet2MessageHandler (const uint8_t * buf, size_t len) { + if (len < 3) + { + LogPrint (eLogError, "I2CP: CreateLeaseSet2Message is too short ", len); + return; + } uint16_t sessionID = bufbe16toh (buf); if (sessionID == m_SessionID) { @@ -897,6 +902,11 @@ namespace client } offset += ls.GetBufferLen (); // private keys + if (offset >= len) + { + LogPrint (eLogError, "I2CP: CreateLeaseSet2Message is too short for private keys"); + return; + } int numPrivateKeys = buf[offset]; offset++; for (int i = 0; i < numPrivateKeys; i++) { @@ -1074,6 +1084,11 @@ namespace client void I2CPSession::DestLookupMessageHandler (const uint8_t * buf, size_t len) { + if (len < 32) + { + LogPrint (eLogError, "I2CP: DestLookupMessage is too short ", len); + return; + } if (m_Destination) { auto ls = m_Destination->FindLeaseSet (buf);