From 22efde37e3c7ebb10d2c48ab5368c8b78e0b86bc Mon Sep 17 00:00:00 2001
From: zzz <zzz@i2pmail.org>
Date: Sun, 12 Jun 2022 16:08:23 -0400
Subject: [PATCH] SSU2: Relay WIP part 15

Fix sending charlie's address in relay response
Fix sending session request after introduction
Send 0-length endpoint in relay response on failure
Log tweaks
---
 .../transport/udp/EstablishmentManager.java   | 16 +++++++++----
 .../transport/udp/IntroductionManager.java    | 23 ++++++++++++++-----
 .../udp/OutboundEstablishState2.java          |  5 ++++
 .../i2p/router/transport/udp/SSU2Util.java    | 17 ++++++++++----
 4 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 93e5711183..2c45d9d6f5 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -1283,8 +1283,10 @@ class EstablishmentManager {
                 break;
 
               case OB_STATE_INTRODUCED:
-                handlePendingIntro(state);
-                return;
+                if (_log.shouldDebug())
+                    _log.debug("Send Session Request after introduction to: " + state);
+                packet = _builder2.buildSessionRequestPacket(state2);
+                break;
 
               default:
                 if (_log.shouldWarn())
@@ -1458,11 +1460,17 @@ class EstablishmentManager {
         } else {
             ourra = _transport.getCurrentExternalAddress(false);
         }
-        if (ourra == null)
+        if (ourra == null) {
+            if (_log.shouldWarn())
+                _log.warn("No address to send in relay request");
             return;
+        }
         byte[] ourIP = ourra.getIP();
-        if (ourIP == null)
+        if (ourIP == null) {
+            if (_log.shouldWarn())
+                _log.warn("No IP to send in relay request");
             return;
+         }
         int ourPort = _transport.getRequestedPort();
         byte[] data = SSU2Util.createRelayRequestData(_context, bob.getRemotePeer(), charlie.getRemoteIdentity().getHash(),
                                                       charlie.getIntroNonce(), tag, ourIP, ourPort,
diff --git a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java
index f3d2f0047a..b152969fd8 100644
--- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java
@@ -855,12 +855,8 @@ class IntroductionManager {
         } else {
             // send rejection to Alice
             SigningPrivateKey spk = _context.keyManager().getSigningPrivateKey();
-            int iplen = data[13] & 0xff;
-            int testPort = (int) DataHelper.fromLong(data, 14, 2);
-            byte[] testIP = new byte[iplen - 2];
-            System.arraycopy(data, 16, testIP, 0, iplen - 2);
             data = SSU2Util.createRelayResponseData(_context, _context.routerHash(), rcode,
-                                                    nonce, testIP, testPort, spk, 0);
+                                                    nonce, null, 0, spk, 0);
             if (data == null) {
                 if (_log.shouldWarn())
                     _log.warn("sig fail");
@@ -954,6 +950,21 @@ class IntroductionManager {
                 rcode = SSU2Util.RELAY_REJECT_CHARLIE_UNKNOWN_ALICE;
             }
         }
+        byte[] ourIP = null;
+        RouterAddress ourra = _transport.getCurrentExternalAddress(isIPv6);
+        if (ourra != null) {
+            ourIP = ourra.getIP();
+            if (ourIP == null) {
+                if (_log.shouldWarn())
+                    _log.warn("No IP to send in relay response");
+                rcode = SSU2Util.RELAY_REJECT_CHARLIE_ADDRESS;
+            }
+        } else {
+            if (_log.shouldWarn())
+                _log.warn("No address to send in relay response");
+            rcode = SSU2Util.RELAY_REJECT_CHARLIE_ADDRESS;
+        }
+        int ourPort = _transport.getRequestedPort();
 
         // generate our signed data
         // we sign it even if rejecting, not required though
@@ -967,7 +978,7 @@ class IntroductionManager {
         }
         SigningPrivateKey spk = _context.keyManager().getSigningPrivateKey();
         data = SSU2Util.createRelayResponseData(_context, bob.getRemotePeer(), rcode,
-                                                nonce, testIP, testPort, spk, token);
+                                                nonce, ourIP, ourPort, spk, token);
         if (data == null) {
             if (_log.shouldWarn())
                 _log.warn("sig fail");
diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java
index 8ff91f9506..f3075a761e 100644
--- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java
+++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java
@@ -152,6 +152,11 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl
         if (_currentState != OutboundState.OB_STATE_PENDING_INTRO)
             return;
         introduced(ip, port);
+        try {
+            _bobSocketAddress = new InetSocketAddress(InetAddress.getByAddress(ip), port);
+        } catch (UnknownHostException uhe) {
+            throw new IllegalArgumentException("bad IP", uhe);
+        }
         _token = token;
         createNewState(_routerAddress);
     }
diff --git a/router/java/src/net/i2p/router/transport/udp/SSU2Util.java b/router/java/src/net/i2p/router/transport/udp/SSU2Util.java
index 4cc6089e55..6dbe579a34 100644
--- a/router/java/src/net/i2p/router/transport/udp/SSU2Util.java
+++ b/router/java/src/net/i2p/router/transport/udp/SSU2Util.java
@@ -252,7 +252,8 @@ final class SSU2Util {
      *  Make the data for the relay response block
      *
      *  @param h Bob hash to be included in sig, not included in data
-     *  @param ip non-null
+     *  @param ip may be null
+     *  @param port ignored if ip is null
      *  @param token if nonzero, append it
      *  @return null on failure
      *  @since 0.9.55
@@ -260,14 +261,20 @@ final class SSU2Util {
     public static byte[] createRelayResponseData(I2PAppContext ctx, Hash h, int code,
                                                  long nonce, byte[] ip, int port,
                                                  SigningPrivateKey spk, long token) {
-        int datalen = 12 + ip.length;
+        int datalen = 10;
+        if (ip != null)
+            datalen += 2 + ip.length;
         byte[] data = new byte[datalen];
         DataHelper.toLong(data, 0, 4, nonce);
         DataHelper.toLong(data, 4, 4, ctx.clock().now() / 1000);
         data[8] = 2;  // version
-        data[9] = (byte) (ip.length + 2);
-        DataHelper.toLong(data, 10, 2, port);
-        System.arraycopy(ip, 0, data, 12, ip.length);
+        if (ip != null) {
+            data[9] = (byte) (ip.length + 2);
+            DataHelper.toLong(data, 10, 2, port);
+            System.arraycopy(ip, 0, data, 12, ip.length);
+        } else {
+            // data[9] = 0;
+        }
         Signature sig = sign(ctx, RELAY_RESPONSE_PROLOGUE, h, null, data, datalen, spk);
         if (sig == null)
             return null;
-- 
GitLab