From 7b00d828b2b26862920542f7dd428793869931ce Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 1 Jan 2018 08:28:42 -0500 Subject: [PATCH 01/10] fix lambda capture, don't capture copy --- libi2pd/Streaming.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 93cf2a9f..6c933752 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -334,7 +334,7 @@ namespace stream void Stream::AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout) { auto s = shared_from_this(); - m_Service.post ([=](void) + m_Service.post ([s, buffer, handler, timeout](void) { if (!s->m_ReceiveQueue.empty () || s->m_Status == eStreamStatusReset) s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); From 938d5d901ace83d785cd546d74c068aa6a3f002b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 11:34:58 -0500 Subject: [PATCH 02/10] implement i2cp session reconfigure --- libi2pd/Destination.cpp | 40 ++++++++++++++++++++++++++++++ libi2pd/Destination.h | 4 +++ libi2pd/TunnelPool.cpp | 12 +++++++++ libi2pd/TunnelPool.h | 5 ++++ libi2pd_client/I2CP.cpp | 55 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 114 insertions(+), 2 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index cb42e480..160b95e6 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -169,6 +169,46 @@ namespace client return false; } + bool LeaseSetDestination::Reconfigure(std::map params) + { + + auto itr = params.find("i2cp.dontPublishLeaseSet"); + if (itr != params.end()) + { + m_IsPublic = itr->second != "true"; + } + + int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency; + std::map intOpts = { + {I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen}, + {I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen}, + {I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant}, + {I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQuant}, + {I2CP_PARAM_TAGS_TO_SEND, numTags}, + {I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency}, + {I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency} + }; + + auto pool = GetTunnelPool(); + inLen = pool->GetNumInboundHops(); + outLen = pool->GetNumOutboundHops(); + inQuant = pool->GetNumInboundTunnels(); + outQuant = pool->GetNumOutboundTunnels(); + minLatency = 0; + maxLatency = 0; + + for (auto opt : intOpts) + { + itr = params.find(opt.first); + if(itr != params.end()) + { + opt.second = std::stoi(itr->second); + } + } + pool->RequireLatency(minLatency, maxLatency); + return pool->Reconfigure(inLen, outLen, inQuant, outQuant); + } + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::shared_ptr remoteLS; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 17daecb5..f93577e6 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -96,6 +96,10 @@ namespace client virtual bool Start (); virtual bool Stop (); + + /** i2cp reconfigure */ + virtual bool Reconfigure(std::map i2cpOpts); + bool IsRunning () const { return m_IsRunning; }; boost::asio::io_service& GetService () { return m_Service; }; std::shared_ptr GetTunnelPool () { return m_Pool; }; diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a3592708..dd163993 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -69,6 +69,18 @@ namespace tunnel m_Tests.clear (); } + bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) { + if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0) + { + m_NumInboundHops = inHops; + m_NumOutboundHops = outHops; + m_NumInboundTunnels = inQuant; + m_NumOutboundTunnels = outQuant; + return true; + } + return false; + } + void TunnelPool::TunnelCreated (std::shared_ptr createdTunnel) { if (!m_IsActive) return; diff --git a/libi2pd/TunnelPool.h b/libi2pd/TunnelPool.h index 07c3024e..fc46930c 100644 --- a/libi2pd/TunnelPool.h +++ b/libi2pd/TunnelPool.h @@ -78,7 +78,12 @@ namespace tunnel int GetNumInboundTunnels () const { return m_NumInboundTunnels; }; int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; }; + int GetNumInboundHops() const { return m_NumInboundHops; }; + int GetNumOutboundHops() const { return m_NumOutboundHops; }; + /** i2cp reconfigure */ + bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant); + void SetCustomPeerSelector(ITunnelPeerSelector * selector); void UnsetCustomPeerSelector(); bool HasCustomPeerSelector(); diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index f98b1af3..293f4067 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -416,8 +416,59 @@ namespace client void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len) { - // TODO: implement actual reconfiguration - SendSessionStatusMessage (2); // updated + uint8_t status = 3; // rejected + if(len > sizeof(uint16_t)) + { + uint16_t sessionID = bufbe16toh(buf); + if(sessionID == m_SessionID) + { + buf += sizeof(uint16_t); + const uint8_t * body = buf; + i2p::data::IdentityEx ident; + if(ident.FromBuffer(buf, len - sizeof(uint16_t))) + { + if (ident == *m_Destination->GetIdentity()) + { + size_t identsz = ident.GetFullLen(); + buf += identsz; + uint16_t optssize = bufbe16toh(buf); + if (optssize <= len - sizeof(uint16_t) - sizeof(uint64_t) - identsz - ident.GetSignatureLen() - sizeof(uint16_t)) + { + buf += sizeof(uint16_t); + std::map opts; + ExtractMapping(buf, optssize, opts); + buf += optssize; + //uint64_t date = bufbe64toh(buf); + buf += sizeof(uint64_t); + const uint8_t * sig = buf; + if(ident.Verify(body, len - sizeof(uint16_t), sig)) + { + if(m_Destination->Reconfigure(opts)) + { + LogPrint(eLogInfo, "I2CP: reconfigured destination"); + status = 2; // updated + } + else + LogPrint(eLogWarning, "I2CP: failed to reconfigure destination"); + } + else + LogPrint(eLogError, "I2CP: invalid reconfigure message signature"); + } + else + LogPrint(eLogError, "I2CP: mapping size missmatch"); + } + else + LogPrint(eLogError, "I2CP: destination missmatch"); + } + else + LogPrint(eLogError, "I2CP: malfromed destination"); + } + else + LogPrint(eLogError, "I2CP: session missmatch"); + } + else + LogPrint(eLogError, "I2CP: short message"); + SendSessionStatusMessage (status); } void I2CPSession::SendSessionStatusMessage (uint8_t status) From 254bf313a2e5cbc6fbcff656ea6c4da2c0eea24a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 11:48:38 -0500 Subject: [PATCH 03/10] fix previous commit --- libi2pd_client/I2CP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 293f4067..5717ab50 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -441,7 +441,7 @@ namespace client //uint64_t date = bufbe64toh(buf); buf += sizeof(uint64_t); const uint8_t * sig = buf; - if(ident.Verify(body, len - sizeof(uint16_t), sig)) + if(ident.Verify(body, len - sizeof(uint16_t) - ident.GetSignatureLen(), sig)) { if(m_Destination->Reconfigure(opts)) { From ab80def94b3c5c53e3a250135922589dbda90d1f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 12:06:10 -0500 Subject: [PATCH 04/10] use reference instead of copy --- libi2pd/Destination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 160b95e6..642be1f9 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -197,7 +197,7 @@ namespace client minLatency = 0; maxLatency = 0; - for (auto opt : intOpts) + for (auto & opt : intOpts) { itr = params.find(opt.first); if(itr != params.end()) From 1967dee50c48b474979aa6e532f5677182c86d0d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Tue, 2 Jan 2018 12:59:16 -0500 Subject: [PATCH 05/10] don't recreate tunnels of different size --- libi2pd/Tunnel.cpp | 11 ++++++++--- libi2pd/TunnelPool.cpp | 28 ++++++++++++++++++---------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 6ae1e119..e39c4fd4 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -670,10 +670,12 @@ namespace tunnel { if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); - if (pool) + if (pool && tunnel->GetPeers().size() == pool->GetNumOutboundHops()) + { + tunnel->SetIsRecreated (); pool->RecreateOutboundTunnel (tunnel); + } } if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) tunnel->SetState (eTunnelStateExpiring); @@ -723,8 +725,11 @@ namespace tunnel { tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); - if (pool) + if (pool && tunnel->GetPeers().size() == pool->GetNumInboundHops()) + { + tunnel->SetIsRecreated (); pool->RecreateInboundTunnel (tunnel); + } } if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index dd163993..7fc2592c 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -491,11 +491,14 @@ namespace tunnel outboundTunnel = tunnels.GetNextOutboundTunnel (); LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel..."); std::shared_ptr config; - if (m_NumInboundHops > 0) config = std::make_shared(tunnel->GetPeers ()); - auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel); - newTunnel->SetTunnelPool (shared_from_this()); - if (newTunnel->IsEstablished ()) // zero hops - TunnelCreated (newTunnel); + if (m_NumInboundHops > 0 && tunnel->GetPeers().size() > 0) config = std::make_shared(tunnel->GetPeers ()); + if (m_NumInboundHops == 0 || config) + { + auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel); + newTunnel->SetTunnelPool (shared_from_this()); + if (newTunnel->IsEstablished ()) // zero hops + TunnelCreated (newTunnel); + } } void TunnelPool::CreateOutboundTunnel () @@ -533,12 +536,17 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel..."); std::shared_ptr config; - if (m_NumOutboundHops > 0) + if (tunnel->GetPeers().size() > 0 && m_NumOutboundHops > 0) + { config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()); - auto newTunnel = tunnels.CreateOutboundTunnel (config); - newTunnel->SetTunnelPool (shared_from_this ()); - if (newTunnel->IsEstablished ()) // zero hops - TunnelCreated (newTunnel); + } + if(m_NumOutboundHops == 0 || config) + { + auto newTunnel = tunnels.CreateOutboundTunnel (config); + newTunnel->SetTunnelPool (shared_from_this ()); + if (newTunnel->IsEstablished ()) // zero hops + TunnelCreated (newTunnel); + } } else LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found"); From 80149342f252c1cb96c50c7835a53da12c9c2adb Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 3 Jan 2018 10:02:11 -0500 Subject: [PATCH 06/10] proper bounds check --- libi2pd/Garlic.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3212da01..f9c297f6 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -538,7 +538,7 @@ namespace garlic { case eGarlicDeliveryTypeLocal: LogPrint (eLogDebug, "Garlic: type local"); - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -549,7 +549,7 @@ namespace garlic LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // destination. check it later or for multiple destinations offset = buf1 - buf; - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -563,7 +563,7 @@ namespace garlic uint8_t * gwHash = buf; buf += 32; offset = buf1 - buf; - if (offset + 4 > (int)len) + if (offset + 4 > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -594,7 +594,7 @@ namespace garlic offset = buf1 - buf; if (!from) // received directly { - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -609,7 +609,7 @@ namespace garlic default: LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType); } - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -619,7 +619,7 @@ namespace garlic buf += 8; // Date buf += 3; // Certificate offset = buf1 - buf; - if (offset > (int)len) + if (offset > (int)len || offset <= 0) { LogPrint (eLogError, "Garlic: clove is too long"); break; From 0f77b4810ded4941f523b58c789738ece0e1a169 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 26 Feb 2018 08:00:07 -0500 Subject: [PATCH 07/10] revert --- libi2pd_client/I2CP.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index 1a1026b4..361d9f94 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -434,14 +434,14 @@ namespace client uint16_t optssize = bufbe16toh(buf); if (optssize <= len - sizeof(uint16_t) - sizeof(uint64_t) - identsz - ident.GetSignatureLen() - sizeof(uint16_t)) { - buf += 2 + buf += sizeof(uint16_t); std::map opts; ExtractMapping(buf, optssize, opts); buf += optssize; //uint64_t date = bufbe64toh(buf); - buf += 8; + buf += sizeof(uint64_t); const uint8_t * sig = buf; - if(ident.Verify(body, len - 2 - ident.GetSignatureLen(), sig)) + if(ident.Verify(body, len - sizeof(uint16_t) - ident.GetSignatureLen(), sig)) { if(m_Destination->Reconfigure(opts)) { From 82a4630061ab6250dbcb9c5d6d482bb2d4c8a56c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 26 Feb 2018 08:09:26 -0500 Subject: [PATCH 08/10] use correct function --- libi2pd/Tunnel.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 33a0bffe..73abc1a7 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -671,7 +671,8 @@ namespace tunnel if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { auto pool = tunnel->GetTunnelPool (); - if (pool && tunnel->GetPeers().size() == pool->GetNumOutboundHops()) + // let it die if the tunnel pool has been reconfigured and this is old + if (pool && tunnel->GetTunnelConfig()->GetNumHops() == pool->GetNumOutboundHops()) { tunnel->SetIsRecreated (); pool->RecreateOutboundTunnel (tunnel); @@ -723,9 +724,9 @@ namespace tunnel { if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) { - tunnel->SetIsRecreated (); auto pool = tunnel->GetTunnelPool (); - if (pool && tunnel->GetPeers().size() == pool->GetNumInboundHops()) + // let it die if the tunnel pool was reconfigured and has different number of hops + if (pool && tunnel->GetTunnelConfig()->GetNumHops() == pool->GetNumInboundHops()) { tunnel->SetIsRecreated (); pool->RecreateInboundTunnel (tunnel); From 008a0647640acc64a29209b5abb7adad4cdef768 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 26 Feb 2018 08:12:15 -0500 Subject: [PATCH 09/10] revert --- libi2pd/Garlic.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index f3e946b6..59089072 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -538,7 +538,7 @@ namespace garlic { case eGarlicDeliveryTypeLocal: LogPrint (eLogDebug, "Garlic: type local"); - if (offset > (int)len || offset <= 0) + if (offset > (int)len) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -594,7 +594,7 @@ namespace garlic offset = buf - buf1; if (!from) // received directly { - if (offset > (int)len || offset <= 0) + if (offset > (int)len) { LogPrint (eLogError, "Garlic: message is too short"); break; @@ -609,7 +609,7 @@ namespace garlic default: LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType); } - if (offset > (int)len || offset <= 0) + if (offset > (int)len) { LogPrint (eLogError, "Garlic: message is too short"); break; From 7b4fc19fca254e16047a1297fa3f8088e0ccc5b8 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 26 Feb 2018 08:18:01 -0500 Subject: [PATCH 10/10] be concise --- libi2pd/TunnelPool.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index 197d1ebd..4f740a09 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -491,7 +491,10 @@ namespace tunnel outboundTunnel = tunnels.GetNextOutboundTunnel (); LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel..."); std::shared_ptr config; - if (m_NumInboundHops > 0 && tunnel->GetPeers().size() > 0) config = std::make_shared(tunnel->GetPeers ()); + if (m_NumInboundHops > 0 && tunnel->GetPeers().size()) + { + config = std::make_shared(tunnel->GetPeers ()); + } if (m_NumInboundHops == 0 || config) { auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel); @@ -536,7 +539,7 @@ namespace tunnel { LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel..."); std::shared_ptr config; - if (tunnel->GetPeers().size() > 0 && m_NumOutboundHops > 0) + if (m_NumOutboundHops > 0 && tunnel->GetPeers().size()) { config = std::make_shared(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()); }