|
From: <ka...@us...> - 2011-10-06 23:05:12
|
Revision: 3652
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3652&view=rev
Author: kappa1
Date: 2011-10-06 23:05:06 +0000 (Thu, 06 Oct 2011)
Log Message:
-----------
AppletLoader: apply fix/workaround for the double security dialogs issue on OS X
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-10-06 21:11:46 UTC (rev 3651)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-10-06 23:05:06 UTC (rev 3652)
@@ -65,8 +65,10 @@
import java.net.URLConnection;
import java.security.AccessControlException;
import java.security.AccessController;
+import java.security.AllPermission;
import java.security.CodeSource;
import java.security.PermissionCollection;
+import java.security.Permissions;
import java.security.PrivilegedExceptionAction;
import java.security.SecureClassLoader;
import java.security.cert.Certificate;
@@ -1155,13 +1157,31 @@
file = file.replace("!", "%21");
urls[i] = new URL(file);
}
-
+
+ // get AppletLoader certificates
+ final Certificate[] certs = getCurrentCertificates();
+
+ // detect if we are running on a mac and save result as boolean
+ String osName = System.getProperty("os.name");
+ final boolean isMacOS = (osName.startsWith("Mac") || osName.startsWith("Darwin"));
+
// add downloaded jars to the classpath with required permissions
classLoader = new URLClassLoader(urls) {
protected PermissionCollection getPermissions (CodeSource codesource) {
PermissionCollection perms = null;
try {
+
+ // if mac, apply workaround for the multiple security dialog issue
+ if (isMacOS) {
+ // if certificates match the AppletLoader certificates then don't use SecureClassLoader to get further permissions
+ if (certificatesMatch(certs, codesource.getCertificates())) {
+ perms = new Permissions();
+ perms.add(new AllPermission());
+ return perms;
+ }
+ }
+
// getPermissions from original classloader is important as it checks for signed jars and shows any security dialogs needed
Method method = SecureClassLoader.class.getDeclaredMethod("getPermissions", new Class[] { CodeSource.class });
method.setAccessible(true);
@@ -1666,18 +1686,8 @@
nativeFolder.mkdir();
}
- // get the current certificate to compare against native files
- Certificate[] certificate = AppletLoader.class.getProtectionDomain().getCodeSource().getCertificates();
-
- // workaround for bug where cached applet loader does not have certificates!?
- if (certificate == null) {
- URL location = AppletLoader.class.getProtectionDomain().getCodeSource().getLocation();
-
- // manually load the certificate
- JarURLConnection jurl = (JarURLConnection) (new URL("jar:" + location.toString() + "!/org/lwjgl/util/applet/AppletLoader.class").openConnection());
- jurl.setDefaultUseCaches(true);
- certificate = jurl.getCertificates();
- }
+ // get the current AppletLoader certificates to compare against certificates of the native files
+ Certificate[] certificate = getCurrentCertificates();
for (int i = urlList.length - nativeJarCount; i < urlList.length; i++) {
@@ -1755,8 +1765,10 @@
in.close();
out.close();
- // validate if the certificate for native file
- validateCertificateChain(certificate, entry.getCertificates());
+ // validate the certificate for the native file being extracted
+ if (!certificatesMatch(certificate, entry.getCertificates())) {
+ throw new Exception("The certificate(s) in " + nativeJar + " do not match the AppletLoader!");
+ }
}
subtaskMessage = "";
@@ -1770,26 +1782,54 @@
}
/**
- * Validates the certificate chain for a single file
+ * Compare two certificate chains to see if they match
*
- * @param ownCerts Chain of certificates to check against
- * @param native_certs Chain of certificates to check
+ * @param cert1 first chain of certificates
+ * @param cert2 second chain of certificates
+ *
+ * @return true if the certificate chains are the same
*/
- protected static void validateCertificateChain(Certificate[] ownCerts, Certificate[] native_certs) throws Exception {
- if (native_certs == null)
- throw new Exception("Unable to validate certificate chain. Native entry did not have a certificate chain at all");
-
- if (ownCerts.length != native_certs.length)
- throw new Exception("Unable to validate certificate chain. Chain differs in length [" + ownCerts.length + " vs " + native_certs.length + "]");
-
- for (int i = 0; i < ownCerts.length; i++) {
- if (!ownCerts[i].equals(native_certs[i])) {
- throw new Exception("Certificate mismatch: " + ownCerts[i] + " != " + native_certs[i]);
+ protected static boolean certificatesMatch(Certificate[] certs1, Certificate[] certs2) throws Exception {
+ if (certs1 == null || certs2 == null) {
+ return false;
+ }
+
+ if (certs1.length != certs2.length) {
+ return false;
+ }
+
+ for (int i = 0; i < certs1.length; i++) {
+ if (!certs1[i].equals(certs2[i])) {
+ return false;
}
}
+
+ return true;
}
/**
+ * Returns the current certificate chain of the AppletLoader
+ *
+ * @return - certificate chain of AppletLoader
+ */
+ protected static Certificate[] getCurrentCertificates() throws Exception {
+ // get the current certificate to compare against native files
+ Certificate[] certificate = AppletLoader.class.getProtectionDomain().getCodeSource().getCertificates();
+
+ // workaround for bug where cached applet loader does not have certificates!?
+ if (certificate == null) {
+ URL location = AppletLoader.class.getProtectionDomain().getCodeSource().getLocation();
+
+ // manually load the certificate
+ JarURLConnection jurl = (JarURLConnection) (new URL("jar:" + location.toString() + "!/org/lwjgl/util/applet/AppletLoader.class").openConnection());
+ jurl.setDefaultUseCaches(true);
+ certificate = jurl.getCertificates();
+ }
+
+ return certificate;
+ }
+
+ /**
* Check and validate jars which will be loaded into the classloader to make
* sure that they are not corrupt. This ensures corrupt files are never marked
* as successful downloadeds by the cache system.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|