OCF and Browser Applets - Answers
Frequently Asked Questions
Background and legal details
Teaching how to develop Web Browsers Java Applets is beyond the scope
of this document. A good URL to start with is the Sun Web site
tutorial:
http://java.sun.com/docs/books/tutorial/applet/
For accessing smartcards inside a Java applet, as well as
inside a Java application, the best way is to use OCF.
There are a number of pitfalls when using OCF to access a
smartcard inside a browser applet, because it will almost
always certainly involve calling features out of the sandbox,
and so it requires precise security settings.
A good document to read in order to start is the:
OCF 1.2 Programmer's Guide
(use this FAQ only in addition).
Return to questions
Tough question!
You can use IE's own Java Virtual Machine at the condition
of downloading a special version of the JVM, see the question
on that issue. This is true for both CommAPI-based CardTerminals
(i.e., those labelled as pure-java) and the PC/SC
wrapper CardTerminal.
Concerning Netscape's own Java Virtual Machine, it is possible
to use it out-of-the-box (with the necessary security settings,
see below) but only with the PC/SC wrapper CardTerminal,
not with a pure-java CardTerminal, because of a mismatch
between the CommAPI implementation and Netscape security scheme,
see the question on this issue.
At last, it is possible to use the Java Plugin,
distributed by Sun, for all browser where it is available (e.g.,
Mozilla, Netscape, Internet Explorer, etc.), but at the
condition of using an up-to-date version of the CommAPI
(for pure-java CardTerminals) or to use a workaround
for a Comm API bug when used into a Java2 (1.2 or 1.3) JDK.
Note that it used to work without any problem for JDKs
version 1.1.x (which are not covered by this FAQ).
Note also that for those three VMs, the three security schemes
are all different (for MS, Sun's Plugin, and Netscape) :-(.
Dealing with the security involves basically learning:
1) how to use OCF in applets (see first question),
2) how to sign an applet in the considered security scheme, and
3) how to grant the necessary rights.
Return to questions
In order to finely specify the permissions, you need to step
by step grant them when a layer of software is requesting
an access to such a file or such a port. That's how I did
and so I think my policy file is quite minimum for my
platform (it is listed in appendix).
BUT note that it will not work "out-of-the-box"
for any platform because not only the security schemes are different
but also the security permissions you need to grant are different
from one platform to another (e.g., name of the ports to access,
location of the different properties files: Java, Comm, and even some
CardTerminal, locations of the dynamic libraries: depending on the JDK
-there are three JDKs under Linux!-, and of course name of these
libraries: '.so' under Linux or Solaris, '.DLL' under Windows etc.).
Sorry about this.. In fact, it's quite a nightmare if you are
thinking about deployment.. except if you have targeting uniform
platforms (i.e., OS, browser, JRE, etc.).
In this case, it's important to understand what is needed, usually
accesses from Comm or sometimes from OCF ('opencard.properties') and
then to specify them.
This way you will limit security holes. Note that there are
sometimes bugs in some software layers, for example it should be
enough to grant "read" access for
'javax.comm.properties', but for the Comm API you need
to specify "read,write", which seems strange and...
dangerous to me. But we would need the sources of 'comm.jar'
to understand the reason, and maybe patch it.
Return to questions
First of all, you should use the "appletviewer" tool instead of
"java", by calling it in your HTML page, because it will give you
proper Java error messages. E.g., in Unix, '$' being the
shell prompt, type:
$ appletviewer example1.html
|
Return to questions
-
A good document to read in order to start is of course the:
OCF 1.2 Programmer's Guide, especially the Using OCF in Applets section!
-
Xavier Lorphelin has written a nice article
about the subject ("SmartCards & Internet") where he explains the
three different security models, how to sign and how to
grant permissions in IE, Netscape, and Java. There are examples
for both JDK 1.1 and JDK 1.2 security models. The article is a good
overview:
SmartCards & Internet (direct link to the [PDF Version])
-
This FAQ will cover specific question and will be enhanced ... with
your help! :-)
Return to questions
for Java (for JDK 1.2: Signed Applet Example): http://java.sun.com/security/signExample12/
for Netscape (Signing Software with Netscape Signing Tool 1.1): http://developer.netscape.com/docs/manuals/signedobj/signtool/index.htm
and
(Object Signing Tool download links): http://developer.netscape.com/software/signedobj/jarpack.html
and (more doc): http://developer.java.sun.com/developer/onlineTraining/Security/Fundamentals/
magercises/Signtool/help.html
for IE (Trust-Based Security for Java): http://www.microsoft.com/java/security/default.htm
and
(Java SDK with Signing Software): http://www.microsoft.com/java/download/dl_sdk40.htm
Miscellaneous:
for Mac OS (the javax.comm.MRJ project, a Comm API implementation for Macintosh): http://www.vmeng.com/beard/javax.comm.MRJ/
an article of Peter Bendel posted in the OCF mailing-list
explains why the Comm API cannot work in a Netscape applet. See:
http://www.opencard.org/archive/old/opencard/msg00528.html
Excerpt from his article:
"Javax.comm uses System.loadLibrary in static initializers. Static
initializers run in another thread than the one you call the browser's
capability API. That is the reason why current javax.comm cannot be
used under browser's security policy.
We have filed a bug report to SUN on this with the request to remove the
loadLibrary call from static initializers."
Return to questions
Here is a list of commands to launch in order to sign an applet
and use it in the Plugin (first command is on one line):
$ keytool -genkey -alias cm -keystore /root/.keystore -keypass cmkeypass -dname
"cn=Christophe Muller" -storepass cmstorepass
$ keytool -export -alias cm -file cmCert4J12.cer
Enter keystore password: cmstorepass
Certificate stored in file <cmCert4J12.cer>
$ javac -d . -O ./Chart.java
$ jar cvf Chart.jar Chart.class
added manifest
adding: Chart.class (in=9788) (out=5248) (deflated 46%)
$ jarsigner -storepass cmstorepass -keystore /root/.keystore -keypass cmkeypass
Chart.jar cm
$ appletviewer example1.html
|
Note: one step was requested by the doc:
$ keytool -import -alias cm -file cmCert4J12.cer -storepass cmstorepass
Enter key password for <cm>: cmkeypass
keytool error: Certificate reply and certificate in keystore are identical
|
that does not seem to be necessary.. (?)
Also, in order to get the right HTML file (from a Netscape one), you can
follow the indications below:
7.3: How can I use Java Activator within Netscape browsers?
In order to use Java Activator with Netscape browsers, web page
authors must convert the <applet> tags in the HTML file to <embed>
tags. The actual mapping between the <applet> tag and the <embed> tag
is specified in the Java Activator HTML Specification from
JavaSoft. Here is an example: Original <applet> tag:
<applet archive="ExampleJarFile.jar" code="ExampleApplet.class" codebase="."
align="baseline" width="200" height="200"
<param name="FirstParameter" value="FirstValue"
No JDK 1.1 support for Applet!
</applet>
|
New <embed> tag:
<embed type="application/x-java-vm/java-applet" width="200" height="200"
align="baseline" code="ExampleApplet.class"
codebase="." archive="ExampleJarFile.jar" FirstParameter="FirstValue"
plug-inspage="http://www.site.com/activator/plug-in-install.html"
<noembed>
No JDK 1.1 support for Applet!
</noembed>
</embed>
|
If the client machine has not installed Java Activator, the browser
will load the HTML page which is set in plug-inspage parameter.
Then you can download and install it in your machine.
Return to questions
Here is a list of commands to launch in order to sign an applet
and use it in a Netscape Communicator 4.x VM?
1) create a password (security icon / passwords)
2) add to "init" in your applet the following code (before "SmartCard.start();"):
opencard.core.util.SystemAccess sys =
new opencard.opt.netscape.NetscapeSystemAccess();
opencard.core.util.SystemAccess.setSystemAccess(sys);
3) sign the applet
$ signtool -G cm
... Test Applet Signing Certificate
... Gemplus
... Research Lab
... France
... FR
... cmuller
... Christophe.Muller@research.gemplus.com
... zzzzzz
$ signtool -l
using certificate directory: /root/.netscape
Object signing certificates
---------------------------------------
cm
Issued by: cm (Test Applet Signing Certificate)
Expires: Sat Aug 12, 2000
---------------------------------------
For a list including CA's, use "signtool -L"
$ mkdir signing
$ cp -i Dir.class signing
$ cp -i NetscapeSystemAccess.class signing
$ signtool -k cm -Z NetDir.jar signing
using certificate directory: /root/.netscape
Generating signing/META-INF/manifest.mf file..
--> Dir.class
adding signing/Dir.class to NetDir.jar...(deflated 48%)
--> NetscapeSystemAccess.class
adding signing/NetscapeSystemAccess.class to NetDir.jar...(deflated 52%)
Generating zigbert.sf file..
Enter Password or Pin for "Communicator Certificate DB":
adding signing/META-INF/manifest.mf to NetDir.jar...(deflated 29%)
adding signing/META-INF/zigbert.sf to NetDir.jar...(deflated 36%)
adding signing/META-INF/zigbert.rsa to NetDir.jar...(deflated 14%)
tree "signing" signed successfully
$ signtool -v NetDir.jar
using certificate directory: /root/.netscape
archive "NetDir.jar" has passed crypto verification.
status path
------------ -------------------
verified Dir.class
verified NetscapeSystemAccess.class
4) use it in an HTML file with <APPLET> tag:
<applet codebase="." code="Dir" archive=NetDir.jar width=251 height=125>
</applet>
|
Return to questions
From Dan Holmdahl:
For the Java Plugin, the solution to specify the multiple
jar files needed by OCF applets (adapt the list to your needs)
is to write in your HTML file:
<PARAM NAME="archive" VALUE="MyOCFApplet.jar,base-core.jar,base-opt.jar,
gemplus-rad-terminals.jar,gemplus-terminals-4.1.jar,gemplus-util.jar,
pcsc_wrapper.jar,..." >
|
Return to questions
If you have an error of the following type:
using NetscapeSystemAccess.getProperty()
java.security.AccessControlException: access denied
(java.util.PropertyPermission OpenCard.loaderClassName read)
|
You have probably let in your applet code some settings that
are intended for Netscape or IE. When using the regular Java VM,
(aka the Java Plugin), you don't need them. Please remove these
settings and try again.
Return to questions
If you have an error of the following type:
$ appletviewer example1.html
java.security.AccessControlException: access denied
(java.util.PropertyPermission OpenCard.loaderClassName read)
{...}
at opencard.core.util.SystemAccess.getProperty(Compiled Code)
|
There are lots of possible reasons: no security has been defined, or
the applet has not been signed, or you do not have a
'[user.home].java.policy' file, etc. etc.
Please follow carrefully the secutity procedure as described in the
OCF Programmer's Guide.
Also be aware that for the Java Plugin 1.2.1 from blackdown
(for Linux), the 'java.security' file is searched in
'~/.netscape/java/lib/' instead of the default
location (which should be '~/.java.policy')!
I'm not sure whether there are other Plug-ins on other platforms which
also behave like this and if only appletviewer is searching in
'$HOME' but be sure to try this tip in case of problems.
Return to questions
If you have an error of the following type:
java.lang.NoClassDefFoundError: javax/comm/CommPortIdentifier
{...}
java.lang.ExceptionInInitializerError: java.security.AccessControlException:
access denied (java.io.FilePermission
/usr/local/share/cardtable/java/jre/lib/javax.comm.properties read)
|
Then you probably missed some security settings in your
'[user.home].java.policy' file. Typically for the error
shown above (which is just an example), you should add in your
policy file a line such as the following one:
// read the 'javax.comm.properties' file in the standard location
permission java.io.FilePermission "${java.home}/lib/javax.comm.properties", "read";
|
Note that many security rights such as this one have to be granted.
I have included my policy file in appendix, but the contents of
the file depends on the platform, the Java VM, the javax.comm
implementation etc. etc. so you will have to understand the
philosophy and adapt the contents to your needs.
Return to questions
This is a known bug of the Comm API. On all platforms, you will have
the same type of error (on Linux with gnu.io.RXTXCommDriver,
on Windows with com.sun.comm.Win32Driver, etc.) always
mentioning a "name can't be null" error message, e.g.,:
Caught java.lang.NullPointerException: name can't be null while loading
driver com.sun.comm.Win32Driver
|
or
Caught java.lang.ExceptionInInitializerError while loading driver
gnu.io.RXTXCommDriver
|
or
Caught java.lang.IllegalArgumentException: name can't be null while
loading driver gnu.io.RXTXCommDriver
|
or (with IBM's Linux JDK1.3)
Caught java.lang.ExceptionInInitializerError while loading driver
com.ibm.comm.NSCommDriver
|
This error is due to a "Comm API" / "JDK1.2 Security Model" mismatch... :-(
A work-around that fixes it was given by Haripriya Kanduri
in the OCF mailing-list, it consist in adding the following lines
to your applet code:
String drivername = "gnu.io.RXTXCommDriver";
try {
CommDriver driver =
(CommDriver)Class.forName(drivername).newInstance();
driver.initialize();
} catch (Exception e) {
System.out.println (e.getMessage ());
}
|
The code above has to be placed before the OCF
"SmartCard.start();" line in your
applet. You do not need to modify the framework sources.
There is unfortunately still an error message from the Comm API
on the console, but it can be ignored.
This quick-hacked fix has been found by Haripriya on the JDC forums
posted by Luc Kumps. The exact URL for this thread on the
mismatch between javax.comm and JDK1.2.x can be found on Sun's
Java Forums by searching the word "javax_commapi" in the forums:
search for ``javax_commapi''
It "should" give the location below (no warranty.. :-)
http://forum.java.sun.com/read/29645/qAxEfZPiDIHkAA
(This problem with Comm API and Java2 has been declared by IBM; it's
referenced name is: "BUG ID 4251547").
Update: the latest version of the Comm API (Version 2.O.2)
fixes this problem. It is currently only available for the Solaris
and Linux platforms.
Return to questions
This is an other security rule to be added... If you haved the
following type of error, (e.g., here on Linux):
java.lang.ExceptionInInitializerError: java.security.AccessControlException:
access denied (java.io.FilePermission
/usr/local/share/cardtable/java/jre/lib/ext/i386/libSerial.so read)
|
A fix for this one is to add access rights for the driver shared
library ('.so' or '.DLL', the name depending on the platform and
on the driver's implementation)
// read the Comm API driver implementation in the standard location
permission java.io.FilePermission "${java.home}/lib/ext/i386/libSerial.so", "read";
|
Note that there are lots of others (on Linux printer devices
'/dev/lp' because it is listed as a parallel port
in the Comm API driver RXTX, etc.) See the policy file in appendix
for more details and adapt it to your platform, Comm API
implementation, etc.
Return to questions
If you have an error of the following type (e.g., here in Linux):
java.lang.NoClassDefFoundError: gnu/io/RXTXCommDriver
{...}
at sun.applet.AppletPanel.run(Compiled Code)
at java.lang.Thread.run(Compiled Code)
java.lang.ExceptionInInitializerError: java.security.AccessControlException:
access denied (java.lang.RuntimePermission loadLibrary.Serial )
{...}
at java.lang.Runtime.loadLibrary0(Compiled Code)
at java.lang.System.loadLibrary(Compiled Code)
at gnu.io.RXTXCommDriver.<clinit>(RXTXCommDriver.java:38)
|
This error occurs for accounts different from 'root' under Unix,
and I know of no fix yet :-(. It seems that the loading of dynamic
libraries is broken under JDK1.2 for user's accounts (Blackdown VM
pre-release-v2).
Return to questions
If you have an error of the following type:
java.lang.NoClassDefFoundError: opencard/core/terminal/CardTerminalException
at java.lang.Class.newInstance0(Native Method)
|
It means that you have not installed the necessay OCF jar files under
'<NetscapeDir>/java/lib/ext/' (similarly for the Comm API,
CardTerminals, or CardServices that are used).
Where '<NetscapeDir>' is:
- C:\Progr~1\Netscape\Users\default on windows, and
- $HOME/.netscape/ on Unix
Return to questions
If you have an error of the following type:
# Verifier error Dir.init()V: Cannot find class javax/comm/CommDriver
# Applet exception: class Dir got a security violation: method verification error
java.lang.VerifyError: Dir
at java.lang.ClassLoader.resolveClass(ClassLoader.java:269)
|
Then you should copy the 'comm.jar' file under
'<NetscapeDir>/java/bin'
Where '<NetscapeDir>' is:
- C:\Progr~1\Netscape\Users\default on windows, and
- $HOME/.netscape/ on Unix
Return to questions
If you have an error of the following type:
using NescapeSystemAccess.loadLibrary()
java.lang.UnsatisfiedLinkError: no Serial in shared library path
at java.lang.Runtime.loadLibrary(Runtime.java:429)
|
Then, you must copy the shared libraries (e.g., in Unix
'*.so' files and in Windows '*.DLL' files)
needed by the Comm API implementation in the 'netscape/java/bin'
('netscape' being where the product has been
installed) directory and in addition
declare this zone in your "LD_LIBRARY_PATH" or
"PATH" variable (respecitvely for Unix or Windows),
and then launch Netscape again when this variable has been set.
E.g., in Unix:
$ export LD_LIBRARY_PATH=.:/usr/lib/netscape/java/bin
$ netscape
|
Return to questions
If you have an error of the following type:
java.lang.ExceptionInInitializerError: netscape.security.AppletSecurityException:
security.checklink: Serial
at Dir.init(Dir.java:52)
|
Then, you have probably forgot to set-up the Netscape security
settings.
OCF provides special tools for that: please include the following
lines before starting the framework:
opencard.core.util.SystemAccess sys
= new opencard.opt.netscape.NetscapeSystemAccess();
opencard.core.util.SystemAccess.setSystemAccess(sys);
|
Note: similar tools exist for IE security settings.
Return to questions
If you have an error of the following type:
Problem during driver pre-creation:security.checkread:
Read of '/dev' not permitted
netscape.security.AppletSecurityException: security.checkpropsaccess.key
at netscape.security.AppletSecurity.checkPropertyAccess(AppletSecurity.java:484)
|
It appears that the OCF security settings are not enough to work
under Linux, because of the Comm API implementation (RXTX).
Especially all that was granted for Java plug-in (see previous
section) should be allowed as well for Netscape, e.g.,
the access to '/dev' devices (for serial ports).
Return to questions
If you have an error of the following type:
using NetscapeSystemAccess.loadProperties()
OpenCardPropertyLoadingException:
property file not found
|
You should put your 'opencard.properties' file in
your Netscape HOME dir, i.e.,
- C:\Progr~1\Netscape\Users\default on windows, and
- $HOME/.netscape/ on Unix
or also in the "current" directory, i.e., the directory
in which you were when Netscape was launched (e.g., in Unix, it
could be '$HOME', or '/tmp', or wherever).
Return to questions
If you have an error of the following type:
# Security Exception: checkpropsaccess.key
netscape.security.AppletSecurityException: security.checkpropsaccess.key
at netscape.security.AppletSecurity.checkPropertyAccess(AppletSecurity.java:484)
at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:958)
at java.lang.System.getProperty(System.java:425)
at javax.comm.CommPortIdentifier.<clinit>(CommPortIdentifier.java:250)
at com.gemplus.opencard.terminal.SerialComm.open(SerialComm.java:151)
at com.gemplus.opencard.terminal.GemCoreFamily.open(GemCoreFamily.java:247)
at com.gemplus.opencard.terminal.GemplusCardTerminal.open(GemplusCardTerminal.java:241)
at com.gemplus.opencard.terminal.GemplusCardTerminal.open(GemplusCardTerminal.java:220)
at opencard.core.terminal.CardTerminalRegistry.add(CardTerminalRegistry.java:130)
at com.gemplus.opencard.terminal.GemplusCardTerminalFactory.createCardTerminals
at opencard.core.service.SmartCard.handleTerminalFactoryEntries(SmartCard.java:432)
at opencard.core.service.SmartCard.configureTerminalRegistry(SmartCard.java:261)
at opencard.core.service.SmartCard.start(SmartCard.java:534)
|
Unfortunately, there is no solution to this problem!
It is currently not possible to use the Netscape JVM
with applets using javax.comm. This is due to the Comm API
Java classes from Sun which start a new thread before trying
to access to protected resources. Because of this, there is
no way to set the privileges for Netscape VM as they are only valid
for the current thread (we would need to modify the Comm API sources
and recompile but the sources are not available).
IBM has filed a bug report to SUN which was accepted as:
"(Review ID: 54232) javax.comm under Netscape 4.07 JVM on Windows NT"
Note also that "BUG ID 4016171" is very close to this
problem (although the problem exist with RMI properties too). See:
http://developer.java.sun.com/developer/bugParade/bugs/4016171.html
Return to questions
Yes, it is possible to use IE without the Sun Plugin (i.e.,
using the original IE Java Virtual Machine), but only with
a JNI-enabled VM that can be downloaded from
the Microsoft web site. So you always have to download
something anyway, it doesn't work "out-of-the-box".
A goof version of VM that allows JNI calls (i.e.,
calls from Java to C routines) can be obtained at:
http://www.microsoft.com/java/download/dl_sdk40.htm
and you also have to learn how to use MS security scheme, see:
http://www.microsoft.com/java/security/default.htm
To my knowledge, an IE JVM that is JNI-enabled
should work with both the CardTerminals using Comm API and the
PC/SC wrapper CardTerminal, as far as the applet is signed and
the necessary authorizations have been granted. I have not
tested the PC/SC solution much, though.. (being working on Linux).
Please forward me
any information you have on the subject (positive or negative)
and I will update the FAQ.
Return to questions
(from the Java forums) : The 'comm.jar' file and the
'javax.comm.properties' files must be present in the:
'C:\winnt\java\lib' directory.
This is the '[java_home]' directory for the Microsoft VM,
which is where the VM expects the JAR files to be.
Return to questions
Note: I would like to add two other examples of policy file: one
typical settings for accessing the PC/SC wrapper on Windows, and
one for accessing a pure Java driver on Windows. If somebody has
had success, please send me your settings.
// this keystore is to store our certificates
keystore ".keystore";
// a grant entry suitable for the OCF applets
// allows ALL applets that were signed by "cm" to carry out the following actions
grant signedBy "cm" {
/* TEST with AllPermission */
/*permission java.security.AllPermission;*/
// read and write arbitrary (including sensitive) system properties
permission java.util.PropertyPermission "*", "read,write";
// read the 'opencard.properties' file in the standard locations
permission java.io.FilePermission "${java.home}/lib/opencard.properties", "read";
permission java.io.FilePermission "${user.home}/.opencard.properties", "read";
permission java.io.FilePermission "${user.dir}/opencard.properties", "read";
permission java.io.FilePermission "${user.dir}/.opencard.properties", "read";
// read the 'javax.comm.properties' file in the standard location
permission java.io.FilePermission "${java.home}/lib/javax.comm.properties",
"read,write,delete";
permission java.io.FilePermission "${java.home}/lib/Gempluscardterminal.properties",
"read,write,delete";
// read the Comm API driver implementation in the standard locations (Blackdown & IBM)
permission java.io.FilePermission "${java.home}/lib/ext/libSerial.so", "read";
permission java.io.FilePermission "${java.home}/lib/ext/i386/libSerial.so", "read";
permission java.io.FilePermission "${java.home}/bin/libibmcomm.so", "read";
permission java.io.FilePermission "${java.home}/lib/ext/libibmcomm.so", "read";
permission java.io.FilePermission "${java.home}/lib/ext/x86/libibmcomm.so", "read";
// access the serial port devices
permission java.io.FilePermission "/dev", "read,write";
permission java.io.FilePermission "/dev/lp0", "read,write";
permission java.io.FilePermission "/dev/lp1", "read,write";
permission java.io.FilePermission "/dev/lp2", "read,write";
permission java.io.FilePermission "/dev/ttyS0", "read,write";
permission java.io.FilePermission "/dev/ttyS1", "read,write";
permission java.io.FilePermission "/dev/ttyS2", "read,write";
permission java.io.FilePermission "/dev/ttyS3", "read,write";
// dynamically load native libraries
permission java.lang.RuntimePermission "loadLibrary.*";
// get access to declared constructors/methods/fields via reflection API
permission java.lang.RuntimePermission "reflect.declared.*";
};
|
Return to questions
Last updated: June 07, 2001
HTML generated by FAQmaker, v0.3: 2000-07-27
|