From 426fbcbfa3811f1893a62944cba4b72eea189ec0 Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Sun, 18 Jul 2021 14:22:57 -0400 Subject: [PATCH] Prop 157 updates - Fix registration of reply key/tag with SKM - Allow OTBRM down client tunnel - Disable tunnel hop throttles for allowLocal - Various cleanups --- .../tunnel/InboundMessageDistributor.java | 3 +- .../router/tunnel/TunnelCreatorConfig.java | 3 + .../i2p/router/tunnel/pool/BuildHandler.java | 19 +++--- .../router/tunnel/pool/BuildRequestor.java | 61 ++++++++----------- 4 files changed, 37 insertions(+), 49 deletions(-) diff --git a/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java b/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java index e393105d23..1131f20a3e 100644 --- a/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java +++ b/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java @@ -318,7 +318,8 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver { _context.statManager().addRateData("tunnel.handleLoadClove", 1); data = null; //_context.inNetMessagePool().add(data, null, null); - } else if (_client != null && type != DeliveryStatusMessage.MESSAGE_TYPE) { + } else if (_client != null && type != DeliveryStatusMessage.MESSAGE_TYPE && + type != OutboundTunnelBuildReplyMessage.MESSAGE_TYPE) { // drop it, since the data we receive shouldn't include other stuff, // as that might open an attack vector _context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, diff --git a/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java b/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java index 47364a8563..4553f2f406 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java @@ -421,6 +421,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo { buf.append("\nHop ").append(i); buf.append(": ").append(_config[i]); } + if (_garlicReplyKeys != null) { + buf.append("\nGarlic reply key: ").append(_garlicReplyKeys.key).append(" tag: ").append(_garlicReplyKeys.rtag); + } return buf.toString(); } } diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java index 9cf128ae5e..cdf51362e8 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java @@ -13,7 +13,6 @@ import net.i2p.data.EmptyProperties; import net.i2p.data.Hash; import net.i2p.data.router.RouterIdentity; import net.i2p.data.router.RouterInfo; -import net.i2p.data.SessionKey; import net.i2p.data.TunnelId; import net.i2p.data.i2np.BuildRequestRecord; import net.i2p.data.i2np.BuildResponseRecord; @@ -32,9 +31,7 @@ import net.i2p.router.Job; import net.i2p.router.JobImpl; import net.i2p.router.OutNetMessage; import net.i2p.router.RouterContext; -import net.i2p.router.crypto.ratchet.RatchetSessionTag; import net.i2p.router.networkdb.kademlia.MessageWrapper; -import net.i2p.router.networkdb.kademlia.MessageWrapper.OneTimeSession; import net.i2p.router.peermanager.TunnelHistory; import net.i2p.router.tunnel.HopConfig; import net.i2p.router.tunnel.TunnelDispatcher; @@ -161,9 +158,10 @@ class BuildHandler implements Runnable { _processor = new BuildMessageProcessor(ctx); // used for previous hop, for all requests - _requestThrottler = new RequestThrottler(ctx); + boolean testMode = ctx.getBooleanProperty("i2np.allowLocal"); + _requestThrottler = testMode ? null : new RequestThrottler(ctx); // used for previous and next hops, for successful builds only - _throttler = new ParticipatingThrottler(ctx); + _throttler = testMode ? null : new ParticipatingThrottler(ctx); _buildReplyHandler = new BuildReplyHandler(ctx); _buildMessageHandlerJob = new TunnelBuildMessageHandlerJob(ctx); _buildReplyMessageHandlerJob = new TunnelBuildReplyMessageHandlerJob(ctx); @@ -854,7 +852,7 @@ class BuildHandler implements Runnable { // Check participating throttle counters for previous and next hops // This is at the end as it compares to a percentage of created tunnels. // We may need another counter above for requests. - if (response == 0 && !isInGW) { + if (response == 0 && !isInGW && _throttler != null) { if (from != null && _throttler.shouldThrottle(from)) { if (_log.shouldLog(Log.WARN)) _log.warn("Rejecting tunnel (hop throttle), previous hop: " + from + ": " + req); @@ -864,7 +862,7 @@ class BuildHandler implements Runnable { } } if (response == 0 && (!isOutEnd) && - _throttler.shouldThrottle(nextPeer)) { + _throttler != null && _throttler.shouldThrottle(nextPeer)) { if (_log.shouldLog(Log.WARN)) _log.warn("Rejecting tunnel (hop throttle), next hop: " + req); _context.statManager().addRateData("tunnel.rejectHopThrottle", 1); @@ -1020,10 +1018,7 @@ class BuildHandler implements Runnable { I2NPMessage outMessage; if (state.msg.getType() == ShortTunnelBuildMessage.MESSAGE_TYPE) { // garlic encrypt - OneTimeSession ots = req.readGarlicKeys(); - SessionKey sk = ots.key; - RatchetSessionTag st = ots.rtag; - outMessage = MessageWrapper.wrap(_context, replyMsg, sk, st); + outMessage = MessageWrapper.wrap(_context, replyMsg, req.readGarlicKeys()); if (outMessage == null) { if (_log.shouldWarn()) _log.warn("OTBRM encrypt fail"); @@ -1102,7 +1097,7 @@ class BuildHandler implements Runnable { accept = false; } } - if (accept) { + if (accept && _requestThrottler != null) { // early request throttle check, before queueing and decryption Hash fh = fromHash; if (fh == null && from != null) diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java index 9297993843..8680240777 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java @@ -146,19 +146,15 @@ abstract class BuildRequestor { Hash farEnd = cfg.getFarEnd(); TunnelManagerFacade mgr = ctx.tunnelManager(); boolean isInbound = settings.isInbound(); + // OB only, short record only + SessionKeyManager replySKM = null; if (settings.isExploratory() || !usePairedTunnels(ctx)) { if (isInbound) { pairedTunnel = mgr.selectOutboundExploratoryTunnel(farEnd); } else { pairedTunnel = mgr.selectInboundExploratoryTunnel(farEnd); if (pairedTunnel != null) { - OneTimeSession ots = cfg.getGarlicReplyKeys(); - if (ots != null) { - SessionKeyManager skm = ctx.sessionKeyManager(); - RatchetSKM rskm = (RatchetSKM) skm; - rskm.tagsReceived(ots.key, ots.rtag, 2 * BUILD_MSG_TIMEOUT); - cfg.setGarlicReplyKeys(null); - } + replySKM = ctx.sessionKeyManager(); } } } else { @@ -169,26 +165,10 @@ abstract class BuildRequestor { } else { pairedTunnel = mgr.selectInboundTunnel(from, farEnd); if (pairedTunnel != null) { - OneTimeSession ots = cfg.getGarlicReplyKeys(); - if (ots != null) { - SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(from); - if (skm != null) { - if (skm instanceof RatchetSKM) { - RatchetSKM rskm = (RatchetSKM) skm; - rskm.tagsReceived(ots.key, ots.rtag, 2 * BUILD_MSG_TIMEOUT); - cfg.setGarlicReplyKeys(null); - } else if (skm instanceof MuxedSKM) { - MuxedSKM mskm = (MuxedSKM) skm; - mskm.tagsReceived(ots.key, ots.rtag, 2 * BUILD_MSG_TIMEOUT); - cfg.setGarlicReplyKeys(null); - } else { - // ElG-only won't work, fall back to expl. - pairedTunnel = null; - } - } else { - // no client SKM, fall back to expl. - pairedTunnel = null; - } + replySKM = ctx.clientManager().getClientSessionKeyManager(from); + if (replySKM == null && cfg.getGarlicReplyKeys() != null) { + // no client SKM, fall back to expl. + pairedTunnel = null; } } } @@ -218,13 +198,7 @@ abstract class BuildRequestor { pairedTunnel = null; } if (pairedTunnel != null) { - OneTimeSession ots = cfg.getGarlicReplyKeys(); - if (ots != null) { - SessionKeyManager skm = ctx.sessionKeyManager(); - RatchetSKM rskm = (RatchetSKM) skm; - rskm.tagsReceived(ots.key, ots.rtag, 2 * BUILD_MSG_TIMEOUT); - cfg.setGarlicReplyKeys(null); - } + replySKM = ctx.sessionKeyManager(); } } if (pairedTunnel != null && log.shouldLog(Log.INFO)) @@ -305,6 +279,21 @@ abstract class BuildRequestor { } OutNetMessage outMsg = new OutNetMessage(ctx, msg, ctx.clock().now() + FIRST_HOP_TIMEOUT, PRIORITY, peer); outMsg.setOnFailedSendJob(new TunnelBuildFirstHopFailJob(ctx, cfg, exec)); + OneTimeSession ots = cfg.getGarlicReplyKeys(); + if (ots != null && replySKM != null) { + if (replySKM instanceof RatchetSKM) { + RatchetSKM rskm = (RatchetSKM) replySKM; + rskm.tagsReceived(ots.key, ots.rtag, 2 * BUILD_MSG_TIMEOUT); + } else if (replySKM instanceof MuxedSKM) { + MuxedSKM mskm = (MuxedSKM) replySKM; + mskm.tagsReceived(ots.key, ots.rtag, 2 * BUILD_MSG_TIMEOUT); + } else { + // non-EC client, shouldn't happen, checked at top of createTunnelBuildMessage() below + if (log.shouldWarn()) + log.warn("Unsupported SKM for garlic reply to: " + cfg); + } + cfg.setGarlicReplyKeys(null); + } try { ctx.outNetMessagePool().add(outMsg); } catch (RuntimeException re) { @@ -345,8 +334,8 @@ abstract class BuildRequestor { Hash replyRouter; boolean useVariable = SEND_VARIABLE && cfg.getLength() <= MEDIUM_RECORDS; boolean useShortTBM = SEND_SHORT && ctx.keyManager().getPublicKey().getType() == EncType.ECIES_X25519; - if (useShortTBM && !pool.getSettings().isExploratory()) { - // pool must be EC also + if (useShortTBM && !cfg.isInbound() && !pool.getSettings().isExploratory()) { + // client must be EC also to get garlic OTBRM reply LeaseSetKeys lsk = ctx.keyManager().getKeys(pool.getSettings().getDestination()); if (lsk != null) { if (!lsk.isSupported(EncType.ECIES_X25519)) -- GitLab