From f4c79c885a34e4c80de94aa9179879248eec1651 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Sat, 7 Feb 2015 14:03:42 +0000
Subject: [PATCH] Transport: Ban routers if they are too old and we are non-DSA

---
 router/java/src/net/i2p/router/Banlist.java   | 43 +++++++++++--------
 .../router/transport/TransportManager.java    | 29 ++++++++++++-
 .../router/transport/ntcp/NTCPTransport.java  |  2 +-
 3 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/router/java/src/net/i2p/router/Banlist.java b/router/java/src/net/i2p/router/Banlist.java
index 57f31b2da4..e5612a36a7 100644
--- a/router/java/src/net/i2p/router/Banlist.java
+++ b/router/java/src/net/i2p/router/Banlist.java
@@ -135,6 +135,30 @@ public class Banlist {
     }
 
     private boolean banlistRouter(Hash peer, String reason, String reasonCode, String transport, boolean forever) {
+        long expireOn;
+        if (forever) {
+            expireOn = _context.clock().now() + BANLIST_DURATION_FOREVER;
+        } else if (transport != null) {
+            expireOn = _context.clock().now() + BANLIST_DURATION_PARTIAL;
+        } else {
+            long period = BANLIST_DURATION_MS + _context.random().nextLong(BANLIST_DURATION_MS / 4);
+            if (period > BANLIST_DURATION_MAX)
+                period = BANLIST_DURATION_MAX;
+            expireOn = _context.clock().now() + period;
+        }
+        return banlistRouter(peer, reason, reasonCode, transport, expireOn);
+    }
+
+    /**
+     *  So that we may specify an expiration
+     *
+     *  @param reason may be null
+     *  @param reasonCode may be null
+     *  @param expireOn absolute time, not a duration
+     *  @param transport may be null
+     *  @since 0.9.18
+     */
+    public boolean banlistRouter(Hash peer, String reason, String reasonCode, String transport, long expireOn) {
         if (peer == null) {
             _log.error("wtf, why did we try to banlist null?", new Exception("banfaced"));
             return false;
@@ -149,22 +173,7 @@ public class Banlist {
                ((transport != null) ? " on transport " + transport : ""), new Exception("Banlist cause: " + reason));
         
         Entry e = new Entry();
-        if (forever) {
-            e.expireOn = _context.clock().now() + BANLIST_DURATION_FOREVER;
-        } else if (transport != null) {
-            e.expireOn = _context.clock().now() + BANLIST_DURATION_PARTIAL;
-        } else {
-            long period = BANLIST_DURATION_MS + _context.random().nextLong(BANLIST_DURATION_MS / 4);
-            //PeerProfile prof = _context.profileOrganizer().getProfile(peer);
-            //if (prof != null) {
-            //    period = BANLIST_DURATION_MS << prof.incrementBanlists();
-            //    period += _context.random().nextLong(period);
-            //}
-       
-            if (period > BANLIST_DURATION_MAX)
-                period = BANLIST_DURATION_MAX;
-            e.expireOn = _context.clock().now() + period;
-        }
+        e.expireOn = expireOn;
         e.cause = reason;
         e.causeCode = reasonCode;
         e.transports = null;
@@ -279,7 +288,7 @@ public class Banlist {
     
     public boolean isBanlistedForever(Hash peer) {
         Entry entry = _entries.get(peer);
-        return entry != null && entry.expireOn > _context.clock().now() + BANLIST_DURATION_MAX;
+        return entry != null && entry.expireOn > _context.clock().now() + 2*24*60*60*1000L;
     }
 
     /** @deprecated moved to router console */
diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java
index 96241652b5..188d5fb4d2 100644
--- a/router/java/src/net/i2p/router/transport/TransportManager.java
+++ b/router/java/src/net/i2p/router/transport/TransportManager.java
@@ -22,9 +22,11 @@ import java.util.TreeMap;
 import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
 
+import net.i2p.crypto.SigType;
 import net.i2p.data.Hash;
 import net.i2p.data.router.RouterAddress;
 import net.i2p.data.router.RouterIdentity;
+import net.i2p.data.router.RouterInfo;
 import net.i2p.data.i2np.I2NPMessage;
 import net.i2p.router.CommSystemFacade;
 import net.i2p.router.OutNetMessage;
@@ -37,6 +39,7 @@ import net.i2p.util.Addresses;
 import net.i2p.util.Log;
 import net.i2p.util.SystemVersion;
 import net.i2p.util.Translate;
+import net.i2p.util.VersionComparator;
 
 public class TransportManager implements TransportEventListener {
     private final Log _log;
@@ -58,6 +61,9 @@ public class TransportManager implements TransportEventListener {
     /** default true */
     public final static String PROP_ENABLE_UPNP = "i2np.upnp.enable";
     
+    /** not forever, since they may update */
+    private static final long SIGTYPE_BANLIST_DURATION = 36*60*60*1000L;
+
     public TransportManager(RouterContext context) {
         _context = context;
         _log = _context.logManager().getLog(TransportManager.class);
@@ -559,12 +565,31 @@ public class TransportManager implements TransportEventListener {
         }
         if (unreachableTransports >= _transports.size()) {
             if (msg.getTarget().getIdentity().getSigningPublicKey().getType() == null) {
+                // we don't support his crypto
                 _context.statManager().addRateData("transport.banlistOnUnsupportedSigType", 1);
                 _context.banlist().banlistRouterForever(peer, _x("Unsupported signature type"));
             } else if (unreachableTransports >= _transports.size() && countActivePeers() > 0) {
                 // Don't banlist if we aren't talking to anybody, as we may have a network connection issue
-                _context.statManager().addRateData("transport.banlistOnUnreachable", msg.getLifetime(), msg.getLifetime());
-                _context.banlist().banlistRouter(peer, _x("Unreachable on any transport"));
+                boolean incompat = false;
+                RouterInfo us = _context.router().getRouterInfo();
+                if (us != null) {
+                    RouterIdentity id = us.getIdentity();
+                    if (id.getSigType() != SigType.DSA_SHA1) {
+                        String v = msg.getTarget().getVersion();
+                        // NTCP is earlier than SSU, use that one
+                        if (VersionComparator.comp(v, NTCPTransport.MIN_SIGTYPE_VERSION) < 0)
+                            incompat = true;
+                    }
+                }
+                if (incompat) {
+                    // they don't support our crypto
+                    _context.statManager().addRateData("transport.banlistOnUnsupportedSigType", 1);
+                    _context.banlist().banlistRouter(peer, _x("No support for our signature type"), null, null,
+                                                     _context.clock().now() + SIGTYPE_BANLIST_DURATION);
+                } else {
+                    _context.statManager().addRateData("transport.banlistOnUnreachable", msg.getLifetime(), msg.getLifetime());
+                    _context.banlist().banlistRouter(peer, _x("Unreachable on any transport"));
+                }
             }
         } else if (rv == null) {
             _context.statManager().addRateData("transport.noBidsYetNotAllUnreachable", unreachableTransports, msg.getLifetime());
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
index 6f4acd8c8b..01ef417a06 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -106,7 +106,7 @@ public class NTCPTransport extends TransportImpl {
     /**
      *  RI sigtypes supported in 0.9.16
      */
-    private static final String MIN_SIGTYPE_VERSION = "0.9.16";
+    public static final String MIN_SIGTYPE_VERSION = "0.9.16";
 
 
     public NTCPTransport(RouterContext ctx, DHSessionKeyBuilder.Factory dh) {
-- 
GitLab