From 32822cb5bd4aa259290260ac1746cfc7ea321de4 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 23 Apr 2016 00:11:36 +0200 Subject: [PATCH] Add check for BC provider, use reflection to avoid security restriction --- .../io/bitsquare/common/util/Utilities.java | 42 +++++++++++++++++++ .../java/io/bitsquare/app/BitsquareApp.java | 2 + .../io/bitsquare/gui/main/MainViewModel.java | 12 +++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/io/bitsquare/common/util/Utilities.java b/common/src/main/java/io/bitsquare/common/util/Utilities.java index edd5bfb980..5a8f5e3ab9 100644 --- a/common/src/main/java/io/bitsquare/common/util/Utilities.java +++ b/common/src/main/java/io/bitsquare/common/util/Utilities.java @@ -30,11 +30,15 @@ import org.slf4j.LoggerFactory; import java.awt.*; import java.io.*; +import java.lang.reflect.Field; import java.net.URI; import java.net.URISyntaxException; import java.net.URLConnection; import java.net.URLEncoder; +import java.security.Permission; +import java.security.PermissionCollection; import java.util.Locale; +import java.util.Map; import java.util.Random; import java.util.concurrent.*; @@ -407,4 +411,42 @@ public class Utilities { return false; } } + + // See: https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an + public static void removeCryptographyRestrictions() { + if (!isRestrictedCryptography()) { + log.debug("Cryptography restrictions removal not needed"); + return; + } + try { + final Class jceSecurity = Class.forName("javax.crypto.JceSecurity"); + final Class cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions"); + final Class cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission"); + + final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted"); + isRestrictedField.setAccessible(true); + isRestrictedField.set(null, false); + + final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy"); + defaultPolicyField.setAccessible(true); + final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null); + + final Field perms = cryptoPermissions.getDeclaredField("perms"); + perms.setAccessible(true); + ((Map) perms.get(defaultPolicy)).clear(); + + final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE"); + instance.setAccessible(true); + defaultPolicy.add((Permission) instance.get(null)); + + log.debug("Successfully removed cryptography restrictions"); + } catch (Exception e) { + log.warn("Failed to remove cryptography restrictions", e); + } + } + + public static boolean isRestrictedCryptography() { + // This simply matches the Oracle JRE, but not OpenJDK. + return "Java(TM) SE Runtime Environment".equals(System.getProperty("java.runtime.name")); + } } diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index de6a7cb564..77d8ff529e 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -123,6 +123,8 @@ public class BitsquareApp extends Application { Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); + if (Utilities.isRestrictedCryptography()) + Utilities.removeCryptographyRestrictions(); Security.addProvider(new BouncyCastleProvider()); BitsquareApp.primaryStage = primaryStage; diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index 5878641116..9ebf26d9de 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -81,6 +81,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; +import java.security.Security; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -541,7 +542,7 @@ public class MainViewModel implements ViewModel { log.error(msg); UserThread.execute(() -> new Popup<>().warning(msg) .actionButtonText("Shut down") - .onAction(() -> BitsquareApp.shutDownHandler.run()) + .onAction(BitsquareApp.shutDownHandler::run) .closeButtonText("Report bug at Github issues") .onClose(() -> Utilities.openWebPage("https://github.com/bitsquare/bitsquare/issues")) .show()); @@ -549,6 +550,15 @@ public class MainViewModel implements ViewModel { } }; checkCryptoThread.start(); + + if (Security.getProvider("BC") == null) { + new Popup<>().warning("There is a problem with the crypto libraries. BountyCastle is not available.") + .actionButtonText("Shut down") + .onAction(BitsquareApp.shutDownHandler::run) + .closeButtonText("Report bug at Github issues") + .onClose(() -> Utilities.openWebPage("https://github.com/bitsquare/bitsquare/issues")) + .show(); + } }