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. |