Policy Files

Java 2 provides a simple mechanism for protecting your computer from evil programs like viruses. If you download a program from somewhere on the Internet, how can you prevent it from stealing information on your computer and sending it back out into the Internet? How can you prevent a malicious program from disabling your computer or erasing data on your disk? Most computing platforms have no answer for these questions.

Java 2 offers powerful ways to limit the actions of running code. Before Java 2, much of the buzz about security had to do with the security of applets. The applet ran with security restrictions that prevented the applet from doing questionable things like reading from or writing to the disk or contacting arbitrary computers on the network. In Java 2, it’s just as easy to apply applet-style security to applications. Furthermore, it’s easy to fine-tune the access you allow applications. For example, you can allow an application to access the disk, but only in a specific directory, or you can allow network access to certain addresses.

Why is this important? Let’s suppose that you need a certain application, like a calendar or an address manager. You go to your favorite Internet search engine and find a promising-looking Java application that does just what you want. You download and run it. But it’s entirely possible that what you’ve downloaded is not what you wanted. It could be a computer virus that infects your computer. Or it could simply be a malicious program that erases files from your disk. In this case, it would have been a really good idea to restrict the application’s actions.

The Default Security Manager

You can use an option of the java interpreter to install a default security manager. This security manager enforces many of the same rules as for applets. To see how this works, let’s write a little program that does something questionable, making a network connection to some computer on the Internet. (We’ll cover the specifics of network programming later, in Chapter 11 and Chapter 12.)

//file: EvilEmpire.java
import java.net.*;

public class EvilEmpire {
  public static void main(String[] args) throws Exception{
    try {
      Socket s = new Socket("207.46.131.13", 80);
      System.out.println("Connected!");
    }
    catch (SecurityException e) {
      System.out.println("SecurityException: could not connect.");
    }
  }
}

If you just run this program with the Java interpreter, it will make the network connection:

C:\> java EvilEmpire
Connected!

C:\>

This is kind of scary. Let’s install the default security manager, like this:

C:\> java -Djava.security.manager EvilEmpire
SecurityException: could not connect.

C:\>

That’s better, but suppose that the application actually has a legitimate reason to make its network connection. We’d like to leave the default security manager in place, just to be safe, but we’d like to grant this application permission to make a network connection.

The policytool Utility

To permit our EvilEmpire example to make a network connection, we need to create a policy file that contains the appropriate permission. A handy utility called policytool , included in SDK 1.2 and later, helps you make policy files. Fire it up from a command line like this:

C:\> policytool

You may get an error message when policytool starts up about not finding a default policy file. Don’t worry about this; just click OK to make the message go away.

We want to add a network permission for the EvilEmpire application. The application is identified by its origin, also called a codebase . A codebase is described by a URL. In this case, it will be a file: URL that points to the location of the EvilEmpire application on your disk.

If you started up policytool, you should be looking at its main window, shown in Figure 3.2. Click on Add Policy Entry. Another window pops up, like the one shown in Figure 3.3 (but with the fields empty).

The policytool window

Figure 3-2. The policytool window

Adding a policy entry

Figure 3-3. Adding a policy entry

First, fill in the codebase with the URL of the directory containing EvilEmpire as shown in the figure. Then click on Add Permission. Yet another window pops up, shown in Figure 3.4.

Creating a new permission

Figure 3-4. Creating a new permission

Choose SocketPermission from the first combo box. Then fill out the second text field on the right side with the network address that EvilEmpire will connect to. Finally, choose connect from the third combo box. Click on OK; you should see the new permission in the policy entry window, as shown in Figure 3.3.

Click on Done to finish creating the policy. Then choose Save As from the File menu and save the policy file as something memorable, like EvilEmpire.policy. You can quit policytool now; we’re all done with it.

There’s nothing magical about the policy file you just created. Take a look at it with a text editor. It has a simple syntax; here’s the important part, showing the policy we just created:

grant codeBase "file:/c:/Projects/Exploring/" {
  permission java.net.SocketPermission "207.46.131.13", "connect";
};

You can eschew policytool entirely and just create policy files with a text editor, if you’re more comfortable that way.

Using a Policy File with the Default Security Manager

Now that we’ve gone to the trouble of creating a policy file, let’s use it. You can tell the default security manager to use the policy file with another command-line option to the java interpreter:

C:\> java -Djava.security.manager -Djava.security.policy=EvilEmpire.policy 
               EvilEmpire
Connected!

EvilEmpire can now make its socket connection because we have explicitly granted it permission with a policy file. The default security manager still protects us in other ways, however; EvilEmpire cannot write or read files on the disk except in the directory it came from; it cannot make connections to any other network addresses except the one we specified. Take a moment and bask in this warm fuzzy feeling.

Later, in Chapter 20, you’ll see policytool again when we explain signed applets. In this chapter, codebases are identified by URLs, which isn’t the most secure option. Through tricky network shenanigans, a clever forger may be able to give you code that appears to be from somewhere it’s not. Crytpographically signed code is even more trustworthy; see Chapter 20 for the full details.

Get Learning Java now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.