From 18e24edce5abef8bfd4cdffceaa77c5e62f8c56c Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Mon, 23 Jul 2018 20:50:42 +0000
Subject: [PATCH] NTCP2: Fix double-free of buffers after msg3 p2 fails Fix
 sending termination after msg3 p2 fails

---
 .../src/net/i2p/router/RouterVersion.java     |  2 +-
 .../transport/ntcp/InboundEstablishState.java | 40 ++++++++++++++-----
 2 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index e1f87e077d..8ab24107c9 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 16;
+    public final static long BUILD = 17;
 
     /** for example "-test" */
     public final static String EXTRA = "";
diff --git a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java
index 3531d3e0c2..cf88963ef3 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/InboundEstablishState.java
@@ -57,6 +57,8 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
     /** how long we expect _sz_aliceIdent_tsA_padding_aliceSig to be when its full */
     private int _sz_aliceIdent_tsA_padding_aliceSigSize;
 
+    private boolean _released;
+
     //// NTCP2 things
 
     private HandshakeState _handshakeState;
@@ -518,7 +520,10 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
             // rather than doing the whole handshake
             if(ip != null)
                _context.blocklist().add(ip);
-            fail("Peer is banlisted forever: " + aliceHash);
+            if (getVersion() < 2)
+                fail("Peer is banlisted forever: " + aliceHash);
+            else if (_log.shouldWarn())
+                _log.warn("Peer is banlisted forever: " + aliceHash);
             _msg3p2FailReason = NTCPConnection.REASON_BANNED;
             return false;
         }
@@ -544,7 +549,10 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
                                              aliceHash,
                                                _x("Excessive clock skew: {0}"));
             _transport.setLastBadSkew(_peerSkew);
-            fail("Clocks too skewed (" + diff + " ms)", null, true);
+            if (getVersion() < 2)
+                fail("Clocks too skewed (" + diff + " ms)", null, true);
+            else if (_log.shouldWarn())
+                _log.warn("Clocks too skewed (" + diff + " ms)");
             _msg3p2FailReason = NTCPConnection.REASON_SKEW;
             return false;
         } else if (_log.shouldLog(Log.DEBUG)) {
@@ -784,13 +792,15 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
                 // calls callbacks below
                 NTCP2Payload.processPayload(_context, this, payload, 0, _msg3p2len - MAC_SIZE, true);
             } catch (IOException ioe) {
-                fail("Bad msg 3 payload", ioe);
+                if (_log.shouldWarn())
+                    _log.warn("Bad msg 3 payload", ioe);
                 // probably payload frame/block problems
                 // setDataPhase() will send termination
                 if (_msg3p2FailReason < 0)
                     _msg3p2FailReason = NTCPConnection.REASON_FRAMING;
             } catch (DataFormatException dfe) {
-                fail("Bad msg 3 payload", dfe);
+                if (_log.shouldWarn())
+                    _log.warn("Bad msg 3 payload", dfe);
                 // probably RI problems
                 // setDataPhase() will send termination
                 if (_msg3p2FailReason < 0)
@@ -798,7 +808,8 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
                 _context.statManager().addRateData("ntcp.invalidInboundSignature", 1);
             } catch (I2NPMessageException ime) {
                 // shouldn't happen, no I2NP msgs in msg3p2
-                fail("Bad msg 3 payload", ime);
+                if (_log.shouldWarn())
+                    _log.warn("Bad msg 3 payload", ime);
                 // setDataPhase() will send termination
                 if (_msg3p2FailReason < 0)
                     _msg3p2FailReason = 0;
@@ -858,11 +869,18 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
     }
 
     /**
-     *  KDF for NTCP2 data phase,
-     *  then calls con.finishInboundEstablishment(),
-     *  passing over the final keys and states to the con.
+     *  KDF for NTCP2 data phase.
      *
-     *  This changes the state to VERIFIED.
+     *  If _msg3p2FailReason is less than zero,
+     *  this calls con.finishInboundEstablishment(),
+     *  passing over the final keys and states to the con,
+     *  and changes the state to VERIFIED.
+     *
+     *  Otherwise, it calls con.failInboundEstablishment(),
+     *  which will send a termination message,
+     *  and changes the state to CORRUPT.
+     *
+     *  If you don't call this, call fail().
      *
      *  @param buf possibly containing "extra" data for data phase
      *  @since 0.9.36
@@ -885,6 +903,7 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
             if (_log.shouldWarn())
                 _log.warn("Failed msg3p2, code " + _msg3p2FailReason + " for " + this);
             _con.failInboundEstablishment(sender, sip_ba, _msg3p2FailReason);
+            changeState(State.CORRUPT);
         } else {
             if (_log.shouldDebug()) {
                 _log.debug("Finished establishment for " + this +
@@ -1031,6 +1050,9 @@ class InboundEstablishState extends EstablishBase implements NTCP2Payload.Payloa
      */
     @Override
     protected void releaseBufs(boolean isVerified) {
+        if (_released)
+            return;
+        _released = true;
         super.releaseBufs(isVerified);
         // Do not release _curEncrypted if verified, it is passed to
         // NTCPConnection to use as the IV
-- 
GitLab