JGridstart/Bouncycastle and Java Web start
BouncyCastle is a cryptographic library for Java that complements and completes the default Java Cryptography Extension. To use it as a provider (e.g. to to access a KeyStore that is supported by BouncyCastle), one has to use the JAR file provided by them because that is signed by Sun (because of law-stuff). When creating a Java Web Start application, the way to do this is by referencing to a bouncycastle JNLP file using the extension tag. For example the file app.jnlp:
<?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0+" href="app.jnlp" codebase="http://somewhere/"> <information> <title>App</title> <vendor>Nikhef</vendor> <homepage href="http://somewhere/"/> </information> <security> <all-permissions/> </security> <resources> <j2se href="http://java.sun.com/products/autodl/j2se" version="1.3+"/> <jar href="app.jar"/> <extension name="BouncyCastle cryptography library" href="bcprov.jnlp"/> </resources> <application-desc main-class="app.Main"/> </jnlp>
References the file bcprov.jnlp which describes the BouncyCastle extension. This can not be put in the application's JNLP because all JARs in a single JNLP file need to be signed by the same key. The file bcprov.jnlp can contain:
<?xml version="1.0" encoding="UTF-8"?> <jnlp spec="1.0+" codebase="http://somewhere/" href="bcprov.jnlp"> <information> <title>bcprov-jdk14</title> <vendor>Sun Microsystems, Inc.</vendor> <offline-allowed/> </information> <security> <all-permissions/> </security> <resources> <jar href="bcprov-jdk14-142.jar"/> </resources> <component-desc/> </jnlp>
You see that this file also has the all-permissions tag in the security section. This is to allow the file to register itself as a cryptography provider.
Now when the Java Web Start application is run, the user has to accept a warning dialog twice: one for the application itself, and one for the BouncyCastle extension. This is a little troublesome, since the user doesn't care about the extension; if he has just consented to grant the application access why does it ask for it again?
Workaround: one warning dialog only (Sun JRE)
Note that this workaround appears to work only for Sun Java, not for OpenJDK. The following section describes how to get the best of both worlds.
The security warning for the BouncyCastle extension (the second warning) can be avoided if one uses a policy file in the application. This policy file explicitely grants access to certain operations, and these operations can be BouncyCastle's as well. So we get the following files
app.jnlp (note the new property tag):
<?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0+" href="app.jnlp" codebase="http://somewhere/"> <information> <title>App</title> <vendor>Nikhef</vendor> <homepage href="http://somewhere/"/> </information> <security> <all-permissions/> </security> <resources> <j2se href="http://java.sun.com/products/autodl/j2se" version="1.3+"/> <jar href="app.jar"/> <extension name="BouncyCastle cryptography library" href="bcprov.jnlp"/> <property name="java.security.policy" value="http://somewhere/bcprov.policy"/> </resources> <application-desc main-class="app.Main"/> </jnlp>
bcprov.jnlp, now without any permissions (note the removed security section):
<?xml version="1.0" encoding="UTF-8"?> <jnlp spec="1.0+" codebase="http://somewhere/" href="bcprov.jnlp"> <information> <title>bcprov-jdk14</title> <vendor>Sun Microsystems, Inc.</vendor> <offline-allowed/> </information> <resources> <jar href="bcprov-jdk14-142.jar"/> </resources> <component-desc/> </jnlp>
and a new bcprov.policy, which grants BouncyCastle its access:
grant { // allow BouncyCastle to register itself permission java.security.SecurityPermission "Security.insertProvider.BC"; permission java.security.SecurityPermission "putProviderProperty.BC"; // allow access to BouncyCastle properties permission java.util.PropertyPermission "org.bouncycastle.*","read"; };
Note that bcprov.policy is referenced using the full url, it is not located in the application's jar.
This method avoids a second permission dialog for the BouncyCastle JAR using the Sun Java runtime environment. OpenJDK's runtime environment still requires all-permissions in bcprov.jnlp's security section, which triggers the second permission dialog. This is tackled in the next section.
Full workaround: Sun & OpenJDK
While it is thus possible to avoid the BouncyCastle permission dialog for the Sun JRE, the OpenJDK JRE still requires all-permissions. So the Sun Java Web Start application needs to be served a different bcprov.jnlp than the OpenJDK Java Web Start application. Luckily, it is possible to distinguish between the two (altough more an accident that the developers' purpose) by looking at the HTTP request headers: when UA-Java-Version exists as a header, it is the Sun JRE; if not, it is the OpenJDK JRE.
With the widely used Apache web server it is possible to use its mod_rewrite to do this easily. One needs the app.jnlp as in the previous section (with the security policy), and the two species of bcprov.jnlp. Let's call the first version (with all-permissions in the security section) bcprov.policy, and the second version (without a security section) bcprov-sun.jnlp (don't forget to update its href accordingly). Now add the following to your .htaccess file:
RewriteEngine On # you may need a RewriteBase directive here RewriteCond %{HTTP:UA-Java-Version} !^$ RewriteRule bcprov.jnlp bcprov-sun.jnlp
Now the OpenJDK JRE is served the file bcprov.jnlp just like without a .htaccess, and the Sun JRE is served bcprov-sun.jnlp when it requests bcprov.jnlp. So all are happy now!
I have tested this only with <all-permissions/> in the security section. If you have experiences with <j2ee-permissions/> please notify me and I'll add it here.