From fa1c077fddb4c759e73f897f6a6144b50a792bb7 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Sat, 30 Aug 2014 19:00:57 +0000
Subject: [PATCH]  * Console: Show unavailable crypto on /logs  * Router: Log
 warnings for unavailable crypto at startup

---
 .../src/net/i2p/router/web/LogsHelper.java    | 12 +++
 apps/routerconsole/jsp/error500.jsp           |  3 +-
 apps/routerconsole/jsp/logs.jsp               |  6 +-
 core/java/src/net/i2p/util/SystemVersion.java | 14 +++-
 router/java/src/net/i2p/router/Router.java    |  1 +
 .../net/i2p/router/tasks/CryptoChecker.java   | 77 +++++++++++++++++++
 6 files changed, 109 insertions(+), 4 deletions(-)
 create mode 100644 router/java/src/net/i2p/router/tasks/CryptoChecker.java

diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
index 062ab73d5e..e3845df9da 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
@@ -9,6 +9,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import net.i2p.I2PAppContext;
+import net.i2p.crypto.SigType;
 import net.i2p.util.FileUtil;
 import net.i2p.util.VersionComparator;
 
@@ -29,6 +30,17 @@ public class LogsHelper extends HelperBase {
         return Server.getVersion();
     }
 
+    /** @since 0.9.15 */
+    public String getUnavailableCrypto() {
+        StringBuilder buf = new StringBuilder(128);
+        for (SigType t : SigType.values()) {
+            if (!t.isAvailable()) {
+                buf.append("<b>Crypto:</b> ").append(t.toString()).append(" unavailable<br>");
+            }
+        }
+        return buf.toString();
+    }
+
     /**
      *  Does not call logManager.flush(); call getCriticalLogs() first to flush
      */
diff --git a/apps/routerconsole/jsp/error500.jsp b/apps/routerconsole/jsp/error500.jsp
index 2a965fc617..70e82e9d2d 100644
--- a/apps/routerconsole/jsp/error500.jsp
+++ b/apps/routerconsole/jsp/error500.jsp
@@ -60,9 +60,10 @@
 <p>
 <b>I2P version:</b> <%=net.i2p.router.RouterVersion.FULL_VERSION%><br>
 <b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
-<b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
  <jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
  <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+<jsp:getProperty name="logsHelper" property="unavailableCrypto" />
+<b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
 <b>Server version:</b> <jsp:getProperty name="logsHelper" property="jettyVersion" /><br>
 <b>Servlet version:</b> <%=getServletInfo()%><br>
 <b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
diff --git a/apps/routerconsole/jsp/logs.jsp b/apps/routerconsole/jsp/logs.jsp
index a028d9334c..99d518cbbd 100644
--- a/apps/routerconsole/jsp/logs.jsp
+++ b/apps/routerconsole/jsp/logs.jsp
@@ -24,16 +24,18 @@
  <p>
 <b>I2P version:</b> <%=net.i2p.router.RouterVersion.FULL_VERSION%><br>
 <b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
-<b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
  <jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
  <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+<jsp:getProperty name="logsHelper" property="unavailableCrypto" />
+<b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
 <b>Server version:</b> <jsp:getProperty name="logsHelper" property="jettyVersion" /><br>
 <b>Servlet version:</b> <%=getServletInfo()%><br>
 <b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
 <b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>
 <b>Jbigi:</b> <%=net.i2p.util.NativeBigInteger.loadStatus()%><br>
 <b>Encoding:</b> <%=System.getProperty("file.encoding")%><br>
-<b>Charset:</b> <%=java.nio.charset.Charset.defaultCharset().name()%></p>
+<b>Charset:</b> <%=java.nio.charset.Charset.defaultCharset().name()%><br>
+</p>
 <p><%=intl._("Note that system information, log timestamps, and log messages may provide clues to your location; please review everything you include in a bug report.")%></p>
 <h3><%=intl._("Critical Logs")%></h3><a name="criticallogs"> </a>
  <jsp:getProperty name="logsHelper" property="criticalLogs" />
diff --git a/core/java/src/net/i2p/util/SystemVersion.java b/core/java/src/net/i2p/util/SystemVersion.java
index 6411058db9..6650cf4797 100644
--- a/core/java/src/net/i2p/util/SystemVersion.java
+++ b/core/java/src/net/i2p/util/SystemVersion.java
@@ -26,6 +26,7 @@ public abstract class SystemVersion {
 
     private static final boolean _oneDotSix;
     private static final boolean _oneDotSeven;
+    private static final boolean _oneDotEight;
     private static final int _androidSDK;
 
     static {
@@ -60,9 +61,11 @@ public abstract class SystemVersion {
         if (_isAndroid) {
             _oneDotSix = _androidSDK >= 9;
             _oneDotSeven = _androidSDK >= 19;
+            _oneDotEight = false;
         } else {
             _oneDotSix = VersionComparator.comp(System.getProperty("java.version"), "1.6") >= 0;
-            _oneDotSeven = VersionComparator.comp(System.getProperty("java.version"), "1.7") >= 0;
+            _oneDotSeven = _oneDotSix && VersionComparator.comp(System.getProperty("java.version"), "1.7") >= 0;
+            _oneDotEight = _oneDotSeven && VersionComparator.comp(System.getProperty("java.version"), "1.8") >= 0;
         }
     }
 
@@ -127,6 +130,15 @@ public abstract class SystemVersion {
         return _oneDotSeven;
     }
 
+    /**
+     *
+     *  @return true if Java 1.8 or higher, false for Android.
+     *  @since 0.9.15
+     */
+    public static boolean isJava8() {
+        return _oneDotEight;
+    }
+
     /**
      * This isn't always correct.
      * http://stackoverflow.com/questions/807263/how-do-i-detect-which-kind-of-jre-is-installed-32bit-vs-64bit
diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index f6eb8a907e..106efe00dd 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -317,6 +317,7 @@ public class Router implements RouterClock.ClockShiftListener {
             if (f.exists())
                 SecureFileOutputStream.setPerms(f);
         }
+        CryptoChecker.warnUnavailableCrypto(_context);
 
         _routerInfo = null;
         _higherVersionSeen = false;
diff --git a/router/java/src/net/i2p/router/tasks/CryptoChecker.java b/router/java/src/net/i2p/router/tasks/CryptoChecker.java
new file mode 100644
index 0000000000..a870e887a7
--- /dev/null
+++ b/router/java/src/net/i2p/router/tasks/CryptoChecker.java
@@ -0,0 +1,77 @@
+package net.i2p.router.tasks;
+
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.Cipher;
+
+import net.i2p.crypto.SigType;
+import net.i2p.router.RouterContext;
+import net.i2p.util.Log;
+import net.i2p.util.SystemVersion;
+
+/**
+ *  Warn about unavailable crypto to router and wrapper logs
+ *
+ *  @since 0.9.15
+ */
+public class CryptoChecker {
+
+    private static String JRE6 = "http://www.oracle.com/technetwork/java/javase/downloads/index.html";
+    private static String JRE7 = "http://www.oracle.com/technetwork/java/javase/documentation/java-se-7-doc-download-435117.html";
+    private static String JRE8 = "http://www.oracle.com/technetwork/java/javase/documentation/jdk8-doc-downloads-2133158.html";
+
+    public static void warnUnavailableCrypto(RouterContext ctx) {
+        if (SystemVersion.isAndroid())
+            return;
+        boolean unavail = false;
+        Log log = null;
+        for (SigType t : SigType.values()) {
+            if (!t.isAvailable()) {
+                if (!unavail) {
+                    unavail = true;
+                    log = ctx.logManager().getLog(CryptoChecker.class);
+                }
+                String s = "Crypto " + t + " is not available";
+                log.logAlways(log.WARN, s);
+                System.out.println("Warning: " + s);
+            }
+        }
+        if (unavail) {
+            if (!SystemVersion.isJava7()) {
+                String s = "Java version: " + System.getProperty("java.version") + " Please consider upgrading to Java 7";
+                log.logAlways(log.WARN, s);
+                System.out.println(s);
+            }
+            if (!isUnlimited()) {
+                String s = "Please consider installing the Java Cryptography Unlimited Strength Jurisdiction Policy Files from ";
+                if (SystemVersion.isJava8())
+                    s  += JRE8;
+                else if (SystemVersion.isJava7())
+                    s  += JRE7;
+                else
+                    s  += JRE6;
+                log.logAlways(log.WARN, s);
+                System.out.println(s);
+            }
+            String s = "This crypto will be required in a future release";
+            log.logAlways(log.WARN, s);
+            System.out.println("Warning: " + s);
+        }
+    }
+
+    /**
+     *  Following code adapted from Orchid
+     *  According to http://www.subgraph.com/orchid.html ,
+     *  "Orchid is licensed under a three-clause BSD license."
+     */
+    private static boolean isUnlimited() {
+        try {
+            if (Cipher.getMaxAllowedKeyLength("AES") < 256)
+                return false;
+        } catch (NoSuchAlgorithmException e) {
+            return false;
+        } catch (NoSuchMethodError e) {
+        }
+        return true;
+    }
+}
+
-- 
GitLab