Previous | Next | Trail Map | The Extension Mechanism | Setting Extension Security Privileges

Setting Privileges for Extensions

If a security manager is in force, these conditions must be met to enable extension software to perform security-sensitive operations:

Let's look at each of these conditions in a little more detail, with some examples.

Using the PrivilegedAction Class

Suppose you want to modify the RectangleArea class in the example extension of the previous lesson so that it writes rectangle areas to a file rather than to stdout. Writing to a file, however, is a security-sensitive operation, so if your software is going to be running under a security manager, you'll need to mark your code as being privileged. There are two steps you need to take to do so:
  1. You need to place code that performs security-sensitive operations within the run method of an object of type java.security.PrivilegedAction.
  2. You must use that PrivilegedAction object as the argument in a call to the doPrivileged method of java.security.AccessController.

Applying these guidelines to the RectangleArea class would lead to a class definition looking something like this:

import java.io.*;
import java.security.*;

public final class RectangleArea {
    public static void writeArea(final java.awt.Rectangle r) {
        AccessController.doPrivileged(new PrivilegedAction() {
	    public Object run() {
	        try { 
		    int area = r.width * r.height;
		    FileWriter fw = new FileWriter("AreaOutput");
		    fw.write("The rectangle's area is " + area);
		    fw.flush();
		    fw.close();
	        } catch(IOException ioe) {
		    System.err.println(ioe);
	        }
	        return null;
	    }
        });
    }
}

The single method in this class, writeArea, computes the area of a rectangle, and writes the area to a file called AreaOutput.

The security-sensitive statements dealing with the output file are placed within the run method of a new instance of PrivilegedAction. (Note that run requires that an Object instance be returned. The returned object can be null.) The new PrivilegedAction instance is then passed as an argument in a call to AccessController.doPrivileged.

For more information about using doPrivileged, see New API for Privileged Blocks in the JDKTM documentation.

Wrapping security-sensitive code in a PrivilegedACtion object in this manner is the first requirement for enabling an extension to perform security-sensitive operations. Let's turn now to the second requirement: getting the security manager to grant the privileged code the appropriate permissions.

Specifying Permissions with the Security Policy

The security policy in force at runtime is specified by a policy file. The default security policy is set by the file lib/security/java.policy in the JRE software.

The policy file assigns security privileges to software by using grant entries. The policy file can contain any number of grant entries. The default policy file has this grant entry for installed extensions:

grant codeBase "file:${java.home}/lib/ext/" {
    permission java.security.AllPermission;
};
This entry specifies that files at the location file:${java.home}/lib/ext/ are to be granted the permission called java.security.AllPermission. (Note that in version 1.2 of the Java platform, java.home refers to the jre directory.) It's not too hard to guess that java.security.AllPermission grants installed extensions all the security privileges that it's possible to grant.

By default, then, installed extensions have no security restrictions. Extension software can perform security-sensitive operations as if there were no security manager installed, provided that security-sensitive code is contained in an instance of PrivilegedAction passed as an argument in a doPrivileged call.

To limit the privileges granted to extensions, you need to modify the policy file. To deny all privileges to all extensions, you could simply remove the above grant entry. There are also several permissions you can grant that are less comprehensive than the java.security.AllPermission granted by default. Other possible permissions are:

The Policy Permissions file in the JDK documentation provides details about each of these permissions. Let's look at just one, java.io.FilePermission, as an example.

The only permission that the RectangleArea.writeArea method really needs is the permission to write to a file. Assuming the RectangleArea class is bundled in the file area.jar, you could grant write privileges by adding this entry to the policy file:

grant codeBase "file:${java.home}/lib/ext/area.jar" {
    permission java.io.FilePermission "/tmp/*", "write";  
};
The codeBase "file:${java.home}/lib/ext/area.jar" part of this entry guarantees that any permissions specified by this entry will apply only to your JAR file. The java.io.FilePermission permits access to a file. The first string argument, "/tmp/*", indicates that all files in the /tmp directory are to be granted FilePermission. The second argument indicates that the file access being granted is only for writing. (Other choices for the second argument are "read", "delete", and "execute".)

Signing Extensions

You can use the policy file to place additional restrictions on the permissions granted to extensions by requiring them to be signed by a trusted entity. (For a review of signing and verifying JAR files, see the JAR File Format trail in this tutorial.)

To allow signature verification of extensions or other software in conjuction with granting permissions, the policy file must contain a keystore entry. The keystore entry specifies which keystore is to be used in the verification. Keystore entries have the form:

kestore "keystore_url";
keystore_url is an absolute or relative URL to the keystore. If it's relative, the URL is relative to the location of the policy file.

To indicate that an extension must be signed in order to be granted security privileges, you use the signedBy field. For example, the following entry indicates that the extension area.jar is to be granted write privileges only if it is signed by the users identified in the keystore by the aliases Robert and Rita:

grant signedBy "Robert,Rita", codeBase "file:${java.home}/lib/ext/area.jar" {
    permission java.io.FilePermission "*", "write";  
};
If the codeBase field is omitted, as in the following "grant", the permissions are granted to any software, including installed or download extensions, that are signed by "Robert" or "Rita":
grant signedBy "Robert,Rita" {
    permission java.io.FilePermission "*", "write";  
};

For further details about the policy file format, see section 3.3.1 of the Security Architecture Specification in the JDK documentation.


Previous | Next | Trail Map | The Extension Mechanism | Setting Extension Security Privileges