[ Team LiB ] Previous Section Next Section

7.1 Running Untrusted Code

Recall the Server example of Chapter 5. That generic server class dynamically loaded and ran Service implementations. Suppose that you are a system administrator in charge of the Server program, and that you don't trust the programmers who are developing the Service implementations; you're afraid that they'll accidentally (or maliciously) include damaging code in their Service classes. Java makes it easy to run these untrusted classes with access-control mechanisms in place, to prevent them from doing anything they shouldn't.

Access control in Java is performed by the SecurityManager and AccessController classes. When a security manager has been registered, Java checks with it every time it is asked to perform any operation that might be restricted, such as reading or writing a file or establishing a network connection. In Java 1.2 and later, the SecurityManager class uses the AccessController class to perform these access-control checks, and the AccessController in turn refers to a Policy file that describes exactly which Permission objects are granted to what code.

As of Java 1.2, it is quite simple to run code under the watchful eye of a security manager. Simply run the Java interpreter using the -D option to set the java.security.manager property. For example, to run the Server class under a security manager, start it like this:

% java -Djava.security.manager je3.net.Server \
-control password 4000

When you do this, both the Server class and the control service class it loads are subject to the access-control checks of a security manager that uses the system's default security policy.

If you try running Server using the default security policy shipped by Sun, the server will fail when the first client attempts to connect to it, and you'll see the following message:

     access denied (java.net.SocketPermission accept,resolve)

This message tells you that the security manager has not allowed your Server class to accept a network connection from the client. The reason is that the default security policy is too restrictive for our server. Fortunately, there is an easy way to allow the server to accept connections. Create a file with the following contents (except replace the directory name with the name of the directory where you have your classes installed) and name it Server.policy :

// These lines grant permissions to any code loaded from the directory shown.
// Edit the directory to match the installation on your system.
// On Windows systems, change the forward slashes to double backslashes: "\\".
grant codeBase "file:/home/david/Books/JavaExamples2/Examples" {
     // Allow the server to listen for and accept network connections 
     // from any host on any port > 1024
     permission java.net.SocketPermission "*:1024-", "listen,accept";

Once you've created the Server.policy file, run the server class again but add another -D option to specify that the interpreter should use this policy file:

% java -Djava.security.manager -Djava.security.policy=Server.policy \
je3.net.Server -control password 4000

When you use this command line, the Java interpreter takes the default security policy and augments it with the policy specified on the command line. Note that if you use = = instead of = in the command line, the interpreter ignores the default policy and uses only the policy you've specified. Our Server.policy file should work either way.

The moral of the story is that if you write a Java application and want people who don't trust you to run it, you should figure out exactly what kind of restricted actions it takes and develop a policy file for it. Then your users can study the policy file to see what permissions the application requires. If they're willing to grant those permissions to your code, they can run your program using the -D options shown earlier, secure in the knowledge that your code can't take any dangerous actions other than those explicitly allowed by your policy file.

To fully understand Java's access control mechanisms, you'll want to read about the java.security.Permission class and its many subclasses. You should also read about the java.security.Policy class. To be able to create policy files of your own, you'll want to read about the policytool program that ships with the Java SDK from Sun. See Java in a Nutshell. If you want to edit policy files by hand (which is often easiest), see the security documentation that comes with the SDK for details on the file format.

    [ Team LiB ] Previous Section Next Section