From e070ce4e3493dd06c9572f7b79e3bbfb2cf30d34 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 09:35:24 -0500 Subject: [PATCH 1/3] check for valid LS before updating --- libi2pd/NetDb.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0215c570..afe2fdde 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,19 +237,17 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - if (it->second->IsNewer (buf, len)) + /* make sure LS is valid before updating */ + LeaseSet ls(buf, len, false); + if(!ls.IsValid()) + { + LogPrint(eLogInfo, "NetDb: Updated LeaseSet is Invalid: ", ident.ToBase32()); + } + else if (it->second->IsNewer (buf, len)) { it->second->Update (buf, len); - if (it->second->IsValid ()) - { - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; - } - else - { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); - m_LeaseSets.erase (it); - } + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + updated = true; } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); From 3820b51960c5532aa53f29607f82866b92ff9c8b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 09:44:55 -0500 Subject: [PATCH 2/3] Revert "check for valid LS before updating" This reverts commit e070ce4e3493dd06c9572f7b79e3bbfb2cf30d34. --- libi2pd/NetDb.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index afe2fdde..0215c570 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,17 +237,19 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - /* make sure LS is valid before updating */ - LeaseSet ls(buf, len, false); - if(!ls.IsValid()) - { - LogPrint(eLogInfo, "NetDb: Updated LeaseSet is Invalid: ", ident.ToBase32()); - } - else if (it->second->IsNewer (buf, len)) + if (it->second->IsNewer (buf, len)) { it->second->Update (buf, len); - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; + if (it->second->IsValid ()) + { + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + updated = true; + } + else + { + LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); + m_LeaseSets.erase (it); + } } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); From 4a77a030338a8bc8f41617f3466cafcb551ecf06 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 10:16:51 -0500 Subject: [PATCH 3/3] * 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 {