CONTENTS | PREV | NEXT Java Security Architecture


5 Secure Classloader, GuardedObject, and SignedObject


5.1 java.security.SecureClassLoader

The class SecureClassLoader is a concrete implementation of java.lang.Classloader that also handles loading remote classes (e.g., from URL and InputStream). This class can be extended to include new methods, but most existing methods are final, as this class is significant for security.

All applets and applications (except for system classes) are loaded by a SecureClassLoader either directly or indirectly (in which case, it is probably loaded by another classloader that itself is loaded by a SecureClassLoader).

SecureClassLoader's defineClass methods enforce the following search algorithm. If the desired class (by the given name) is not found, the next step is taken. If the class is still not found after the last step, a ClassNotFound exception is thrown.

1. see if the class is already loaded and resolved
2. see if the class requested is a system class.
   if so, load the class with the null system classloader.
3. attempt to find the class in a customized way, using a non-final
   method called findAppClass. By default, this method tries
   to find the class in a search path java.class.path.
JDK 1.2 includes a property named java.class.path. The CLASSPATH environment variable sets this property, as does the optional -classpath command-line argument. Classes that are stored on the local file system but should not be treated as system classes should be on this path. (CLASSPATH no longer includes the path to system classes, which are assumed to be in the installation's lib/classes.zip file unless the command-line -Xsysclasspath flag specifies a different path.) Classes on this path are loaded with a special class loader in order to take advantage of both installed extensions (to be discussed in a future draft) and the new security model so that their execution can be controlled by the global security policy.

Note that java.class.path is required in a platform-dependent format. An example path is set in Solaris as

java.class.path=/home/gong/classes:/usr/local/classes
Note: The path java.class.path can also be set by specifying the path directories via a command-line option, as follows:

     java -Djava.class.path=. application 
There might be a future need to develop a generic Path class that not only provides platform-independent path names but also makes dynamic path manipulation easier. Moreover, currently, this java.class.path class path is treated as a sequence of directories on the local file system. It is conceivable that, in the future, remote directories or URLs can be included as well.

A subclass may choose to override the findAppClass method in order to customize class searching and loading. For example, the AppletClassLoader caches all raw class materials found inside a JAR file. Thus, it is reasonable for the AppletClassLoader, which is a subclass of the SecureClassLoader, to use findAppClass to look into its own cache. A class introduced in such a fashion is guaranteed not to be a system class, and is subjected to the same security policy as its loading class.

Sometimes a class may cause another class belonging to another domain to be loaded. In the case of AppletClassLoader, the second class is loaded by the same classloader that loaded the first class, except when either class is a system class, in which case the system class is loaded with a null classloader. This ensures that classes in the same applet can access each other easily (as compared to the case when they are loaded by different classloaders). It is possible, and sometimes desirable, to restrict a classloader to not load classes from more than one protection domain.


5.2 Security Management for Applets and Applications

Currently, all JDK system code invokes SecurityManager methods to check the policy currently in effect and perform access control checks. There is typically a security manager (SecurityManager implementation) installed whenever an applet is running; the appletviewer and most browsers, including those from Netscape and Microsoft, install a security manager.

A security manager is not automatically installed when an application is running. To apply the same security policy to an application found on the local file system as to downloaded applets, either the user running the application must invoke the Java virtual machine with the new "-Djava.security.manager" command-line argument (which sets the value of the java.security.manager property), as in

    java -Djava.security.manager  SomeApp
or the application itself must call the setSecurityManager method in the java.lang.System class to install a security manager.

It is possible to specify on the command line a particular security manager to be utilized, by following "-Djava.security.manager" with an equals and the name of the class to be used as the security manager, as in

    java -Djava.security.manager=COM.abc.MySecMgr  SomeApp
If no security manager is specified, the built-in default security manager is utilized (unless the application installs a different security manager). All of the following are equivalent and result in usage of the default security manager:

    java -Djava.security.manager  SomeApp
    java -Djava.security.manager=""  SomeApp
    java -Djava.security.manager=default  SomeApp
As noted in the previous section, JDK 1.2 includes a property named java.class.path. Classes that are stored on the local file system but should not be treated as system classes should be on this path. Classes on this path are loaded with a secure class loader and are thus subjected to the security policy being enforced.

There is also a "-Djava.security.policy" command-line argument whose usage determines what policy files are utilized. This command-line argument is described in detail in the "Default System and User Policy Files" section. Basically, if you don't include "-Djava.security.policy" on the command line, then the policy files specified in the security properties file will be used.

You can use a "-Djava.security.policy" command-line argument to specify an additional or a different policy file when invoking execution of an application. For example, if you use

    java -Djava.security.manager -Djava.security.policy=pURL SomeApp
where pURL is a URL specifying the location of a policy file, then the specified policy file will be loaded in addition to all the policy files specified in the security properties file. If you use

java -Djava.security.manager -Djava.security.policy==pURL SomeApp
then just the specified policy file will be used; all others will be ignored.


5.3 java.security.GeneralSecurityException

This is a new exception class that is a subclass of java.lang.Exception. The intention is that there should be two types of exceptions associated with security and the security packages.

Such an exception is thrown only when some sort of security violation is detected. For example, such an exception is thrown when some code attempts to access a file, but it does not have permission for the access. Application developers may catch these exceptions, if they want.

Such an exception is security related but non-vital. For example, passing in an invalid key is probably not a security violation and should be caught and dealt with by a developer.

There are currently still two exceptions within the java.security package that are subclasses from RuntimeException. We at this moment cannot change these due to backward compatibility requirements. We will revisit this issue in the future.


5.4 java.security.GuardedObject and java.security.Guard

Recall that the class AccessControlContext is useful when an access control decision has to be made in a different context. There is another such scenario, where the supplier of a resource is not in the same thread as the comsumer of that resource, and the consumer thread cannot provide the supplier thread the access control context information (because the context is security-sensitive, or the context is too large to pass, or for other reasons). For this case, we provide a class called GuardedObject to protect access to the resource, illustrated in the figure below.

The basic idea is that the supplier of the resource can create an object representing the resource, create a GuardedObject that embeds the resource object inside, and then provide the GuardedObject to the consumer. In creating the GuardedObject, the supplier also specifies a Guard object such that anyone (including the consumer) can only obtain the resource object if certain (security) checks inside the Guard are satisfied.

Guard is an interface so any object can choose to become a Guard. The only method in this interface is called checkGuard(object) that performs certain (security) checks. The Permission class in java.security implements the Guard interface.

For example, suppose a system thread is asked to open a file /a/b/c.txt for read access, but the system thread does not know who the requestor is or under what circumstances the request is made. Therefore, the correct access control decision cannot be made at the server side. The system thread can use GuardedObject to delay the access control checking, as follows.

FileInputStream f = new FileInputStream("/a/b/c.txt");
FilePermission p = new FilePermission("/a/b/c.txt", "read");
GuardedObject g = new GuardedObject(f, p);
Now the system thread can pass g to the consumer thread. For that thread to obtain the file input stream, it has to call

FileInputStream fis = (FileInputStream) g.getObject();
This method in turn invokes the checkGuard() method on the Guard object p, and because p is a Permission, its checkGuard() method is in fact:

AccessController.checkPermission(this);
This ensures that a proper access control check takes place within the consumer context. In fact, one can replace often-used hash tables and access control lists in many cases and simply store a hash table of GuardedObjects.

This basic pattern of GuardedObject and Guard is very general, and we expect that by extending the basic Guard and GuardedObject classes, developers can easily obtain quite powerful access control tools. For example, per-method invocation can be achieved with an appropriate Guard for each method, and a Guard can check the time of the day, the signer or other identification of the caller, or any other relevant information.

Note that certain typing information is lost because GuardedObject returns an Object. GuardedObject is intended to be used between cooperating parties so that the receiving party should know what type of object to expect (and to cast for). In fact, we envision that most usage of GuardedObject involves subclassing it (say to form a GuardedFileInputStream class), thus encapsulating typing information, and casting can happen suitably in the subclass.


5.5 java.security.SignedObject

This class is an essential building block for other security primitives. SignedObject contains another Serializable object, the (to-be-)signed object and its signature. If the signature is not null, it contains a valid digital signature of the signed object. This is illustrated in the figure below.

The underlying signing algorithm is set through a Signature object as a parameter to the sign() method call, and the algorithm can be, among others, the NIST standard DSA, using DSA and SHA-1. The algorithm is specified using the same convention for signatures, such as "SHA/DSA".

The signed object is a "deep copy" (in serialized form) of an original object. Once the copy is made, further manipulation of the original object has no side effect on the copy. A signed object is immutable.

A typical example of creating a signed object is the following:

Signature signingEngine =
    Signature.getInstance(algorithm,provider);
SignedObject so =
    new SignedObject(myobject, signingKey, signingEngine);
A typical example of verification is the following (having received SignedObject so), where the first line is not needed if the name of the algorithm is known:

String algorithm = so.getAlgorithm();
Signature verificationEngine =
    Signature.getInstance(algorithm, provider);
so.verify(verificationEngine);
Potential applications of SignedObject include:

It is intended that this class can be subclassed in the future to allow multiple signatures on the same signed object. In that case, existing method calls in this base class will be fully compatible in semantics. In particular, any get method will return the unique value if there is only one signature, and will return an arbitrary one from the set of signatures if there is more than one signature.



CONTENTS | PREV | NEXT
Copyright © 1997-1998 Sun Microsystems, Inc. All Rights Reserved.