In Part 1, we created a webpage which could upload files with a drag and drop operation in the Mozilla and Firefox browsers. This page works wonderfully when it's on the local machine, but breaks as soon as it's put on a web server due to the Mozilla security mechanisms. In order to get this to work correctly when it's deployed out to a server, we need to create a signed jar which Mozilla recognizes. Although this seems like a straightforward task, I actually encountered a lot of difficulty figuring out how to do this right. The following steps must be followed in order to properly create a signed Mozilla jar:
- Download Mozilla NSS and NSPR, and set up the NSS directory
- Create a new certificate repository
- Create a new certificate with which to sign the jar
- Generate a signed jar from a folder with the web pages and scripts
- Discuss how jar links in Mozilla are handled
- Enable certificate permissions in the browser
Download and set up NSS and NSPR
In order to create a signed jar, you must download the Netscape/Mozilla jar signing tool. The Sun jar signing tool will NOT work correctly, as I discovered after several hours of trial and error – Mozilla will not recognize a Sun-signed jar as a valid signed jar. NSS and NSPR can be downloaded from the Mozilla site at the following URLs:
ftp://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/NSS_3_10_RTM/ftp://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v4.4.1/I preferred to just use an existing binary distribution, but you can compile your own from source if you choose. If you decide on binaries, select the platform you are running on and download as required. Once you have downloaded both NSS and NSPR, you will need to dump all of the libraries into one directory and put the executables you will be using in the same directory. For me, being on a Windows platform, this entailed copying all of the files from \NSPR\lib to \NSS\lib, and copying signtool.exe and certutil.exe into \NSS\lib.
Creating a new certificate repository
In order to create a new certificate repository, we need to use the certutil tool. If we wanted to create a new repository in c:\certdir, we would run the following command:
certutil -N -d c:\certdir
The program will ask you for a password which you will use to secure the certificate database. I will assume that the password used is
dragdrop. Once the program has completed, if you look in c:\certdir you will notice that three files have been added – cert8.db, key3.db, and secmod.db. These represent the certificate database.
Creating a new jar-signing certificate
Now that we have a new certificate database, we need to generate a certificate that can be used to sign the jar. This can be done using the following command:
signtool -G dragDropCert -d c:\certdir -p "dragdrop"
This will walk you through entering a bunch of information, like company name, person name, etc. This is the information which will be presented to the user, so put in data as appropriate. Once the questions have all been filled in, the program will generate a certificate, add it to the database, and create an x509.raw and x509.cacert file for you in whatever directory signtool.exe was run in. Hold onto x509.cacert, as we will need to add it to the website later so that the user can authorize the certificate to request special permissions.
An alternative to this certificate generating and permission requesting process which will be much more useful in a production environment is to get the certificate created and signed by a verified Certificate Authority, such as Verisign or Entrust. If you get a certificate signed by an authority which is already registered in Mozilla/Firefox, you can skip the whole certificate permissions part which is described in the
Enable certificate permissions section. For a complete list of default trusted certificate authorities, just install Firefox and open the Options dialog – under the Advanced Section and the Manage Certificates section, a list of all recognized certificate authorities is presented along with how much trust each has.
Generate a signed jar from a set of web pages
Now that we have a certificate to sign the jar with, we just need to generate the jar. If we have a folder called c:\jarfolder which contains all of the files we want to jar up (including subdirectories and such) then we would generate a signed jar with the following command:
signtool -d c:\certdir -k dragDropCert -p "dragdrop" -X -Z dragdrop.jar c:\jarfolder
This will create a signed jar called dragdrop.jar in the current directory based on the contents of c:\jarfolder. The jar will be signed with the certificate named dragDropCert from the certificate database in c:\certdir.
At this point, we have finished the technical part of creating a signed jar. Now however, we must consider two things which might prevent our application from working as expected. Each issue will be covered with its own section.
How jar links are handled in Mozilla
Mozilla has the ability to reference an HTML file inside of a jar directly. The URL for this would look like:
jar:http://www.remoteserver.com/website/dragdrop.jar!/mozilla-drag-example.html
As you can see, there are two parts to this URL. The first part is the URL to the jar itself:
http://www.remoteserver.com/website/dragdrop.jar
The second part is the jar URL and references the file inside the jar (which in this case is mozilla-drag-example.html):
jar:[jar-url]!/mozilla-drag-example.html
One of the biggest problems with jar URLs is that they must be absolute URLs. It is not possible to wrap a relative URL in a
jar: URL, therefore if you want to be able to handle a relative jar URL, you need to do some Javascript trickery. An example of what I did to enable a jar link on a page to work from multiple IP addresses is:
<SCRIPT>
function loader()
{
var elemList = document.getElementsByTagName("a");
for (var i = 0; i < elemList.length; i++)
{
if (elemList[i].getAttribute("class") == "jarlink")
{
elemList[i].href=
"jar:" +
elemList[i].href
;
}
}
}
</SCRIPT>
…
<BODY onload="loader();">
…
<a href="dragdrop.jar!/mozilla-drag-example.html" class="jarlink">
Basic Mozilla Drag and Drop Jar Link
</a>
As you can see, I have specified the A HREF attribute with a relative URL (i.e. dragdrop.jar is located in the same directory as the current page). I have also assigned it a class of
jarlink – that allows the loader() method to identify that this A HREF is a relative jar link, and it processes it appropriately. Please note that when I reconstruct the A HREF url, I am only appending the
jar: string to the beginning and then calling the existing href property on the A DOM object - this is because the href property will automatically convert
dragdrop.jar to it’s full path on the server (e.g.
http://www.remoteserver.com/website/dragdrop.jar) and thus I only need to append the
jar: to the beginning and the full link will be constructed.
Also note that, if you wish to use relative URLs inside the jar, you will have a similar issue - all of the URLs will be prefixed with
jar:http://www.remoteserver.com/..., which is not a valid server URL - you will need to manually reparse the URL with javascript to remove the
jar: at the beginning as well as do any other URL cleaning which has to occur.
Enabling certificate permissions in Mozilla
If you’ve used a self-signed certificate (as described in the steps above) to create your signed jar, you will need to ensure that the certificate has been granted enough permission to run correctly. The easiest way to do this is to add a link to your page somewhere which links to the certificate file (The one named x509.cacert which we created earlier – you will want to save it as x509.crt so that the browser and web server handle it correctly) and ask the user to click on it before they access the website. When they do this, a dialog will appear asking the user if they want to trust the new certificate which has just been presented – the user must check the
Trust this CA to identify software developers, or the XPConnect bridge will not be accessible to the drag and drop script. If they click on a jar link before clicking on the certificate link, the certificate will automatically be imported with no trust when the jar is first accessed, and clicking the certificate link will show a dialog that says
The Certificate already exists. If this happens, the user will have to open the Certificate Management console (Found under
Tools > Options > Advanced > Manage Certificates), find the certificate listed under
Authorities, and edit the certificate to enable the
Identify software makers permission.
I'll mention again that all of this can be eliminated if a certificate is purchased from a recognized certificate authority – these authorities have trust levels built into Mozilla and Firefox, and purchasing a certificate from them (e.g. a Class 2 public certificate from Verisign) will eliminate these trust-based issues entirely.
As a final note, this article is Copyright (C) 2005, Codesta LLC. All Rights Reserved. All of the research that I did for this article was on company time, and Codesta agreed to let me publish it. The information in it is free for you to use, but don't go claiming it's yours - it's not.