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);