From 4a77a030338a8bc8f41617f3466cafcb551ecf06 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 10:16:51 -0500 Subject: [PATCH] * Add LeaseSetBufferValidate which checks lease validity and extracts timestamp * check for leases with LeaseSetBufferValidate before update in floodfill code as to prevent malicous nodes removing good LS --- libi2pd/LeaseSet.cpp | 34 ++++++++++++++++++++++++++++++++++ libi2pd/LeaseSet.h | 6 ++++++ libi2pd/NetDb.cpp | 14 ++++++-------- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d1a70ba5..02fdafb6 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -265,5 +265,39 @@ namespace data auto ts = i2p::util::GetMillisecondsSinceEpoch (); return ts > m_ExpirationTime; } + + bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires) + { + IdentityEx ident(ptr, sz); + size_t size = ident.GetFullLen (); + if (size > sz) + { + LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", sz); + return false; + } + // encryption key + size += 256; + // signing key (unused) + size += ident.GetSigningPublicKeyLen (); + uint8_t numLeases = ptr[size]; + ++size; + if (!numLeases || numLeases > MAX_NUM_LEASES) + { + LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)numLeases); + return false; + } + const uint8_t * leases = ptr + size; + expires = 0; + /** find lease with the max expiration timestamp */ + for (int i = 0; i < numLeases; i++) + { + leases += 36; // gateway + tunnel ID + uint64_t endDate = bufbe64toh (leases); + leases += 8; // end date + if(endDate > expires) + expires = endDate; + } + return ident.Verify(ptr, leases - ptr, leases); + } } } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index c7d2066e..4c2903aa 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -95,6 +95,12 @@ namespace data size_t m_BufferLen; }; + /** + validate lease set buffer signature and extract expiration timestamp + @returns true if the leaseset is well formed and signature is valid + */ + bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires); + class LocalLeaseSet { public: diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0215c570..b5e20628 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,22 +237,20 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - if (it->second->IsNewer (buf, len)) + uint64_t expires; + if(LeaseSetBufferValidate(buf, len, expires)) { - it->second->Update (buf, len); - if (it->second->IsValid ()) + if(it->second->GetExpirationTime() < expires) { + it->second->Update (buf, len); LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } else - { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); - m_LeaseSets.erase (it); - } + LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else - LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); + LogPrint(eLogError, "NetDb: LeaseSet is invalid: ", ident.ToBase32()); } else {