When Java security is discussed, the discussion typically centers around Java's applet-based security model -- the security model that is embodied by Java-enabled browsers. It's considered "applet-based" because in early versions of Java, it applied only to applets that run within a Java-enabled browser. In the Java 2 platform, however, this security model can apply to any Java application as well as to the Java Plug-in, which allows newer browsers to run Java 2 applets. The Java 2 security model is also configurable by an end user or system administrator so that it can be made less restrictive than earlier implementations of that model.
This security model centers around the idea of a sandbox. The idea is when you allow a program to be hosted on your computer, you want to provide an environment where the program can play (i.e., run), but you want to confine the program's play area in certain bounds. You may decide to give the program certain toys to play with (i.e., you may decide to let it have access to certain system resources), but in general, make sure that the program is confined to its sandbox.
This analogy works better when you consider it from the view of a close relative rather than from the view of a parent. If you're a parent, you probably consider the purpose of a sandbox to be to provide a safe environment for your child to play in. When my niece Rachel visits me, however, I consider the purpose of a sandbox not (only) to be to protect her, but also to protect my grandmother's china
from her. I love my niece, but I can't give her leave to run through my house; I enjoy running the latest cool applet on the Internet, but I can't give it leave to run through my filesystem.
The Java sandbox is responsible for protecting a number of resources, and it does so at a number of levels. Consider the resources of a typical machine as shown in Figure 1. The user's machine has access to many things:
Encryption and Weaponry
The whole question of importing and exporting encryption technology occurs because it is often classified as a munition. While this position is sometimes questioned, it comes from a long tradition in computer science.
During WWII, the Allies waged a successful and pivotal campaign in the Atlantic against the Axis navy. The success of this campaign was greatly due to the work of Alan Turing, who with his colleagues broke the German encryption algorithm known as Enigma. Turing was also one of the founding fathers of modern computer science, much of which was based on the work he developed in service to his country during the war.
Ironically, the reward that Turing reaped for his efforts was that some years after the war, he was arrested and forced to undergo harmful chemical treatments because he was gay. There's an odd parallel here: many of the harsh restrictions that are sometimes placed on encryption technology make no more sense in a world with a global Internet than did England's persecution of Alan Turing in the 1950s. Perhaps the relaxation of export restrictions is a good sign in general.
- Internally, it has access to its local memory (the computer's RAM).
- Externally, it has access to its filesystem and to other machines on the local network.
- For running applets, it also has access to a web server, which may be on its local (private) net or may be on the Internet.
- Data flows through this entire model, from the user's machine through the network and (possibly) to disk.
Each of these resources needs to be protected, and those protections form the basis of Java's security model. We can imagine a number of different-sized sandboxes in which a Java program might run:
- A sandbox in which the program has access to the CPU, the screen, keyboard, and mouse, and to its own memory. This is the minimal sandbox -- it contains just enough resources for a program to run.
- A sandbox in which the program has access to the CPU and its own memory as well as access to the web server from which it was loaded. This is often thought of as the default state for the sandbox.
- A sandbox in which the program has access to the CPU, its memory, its web server, and to a set of program-specific resources (local files, local machines, etc.). A word-processing program, for example, might have access to the
docsdirectory on the local filesystem, but not to any other files.
- An open sandbox, in which the program has access to whatever resources the host machine normally has access to.
The sandbox, then, is not a one-size-fits-all model. Expanding the boundaries of the sandbox is always based on the notion of trust: when my one-year-old niece comes to visit, there's very little in the sandbox for her to play with, but when my six-year-old godchild comes to visit, I trust that I might give her more things to play with. In the hands of some visitors, a toy with small removable parts would be dangerous, but when I trust the recipient, it's perfectly reasonable to include that item in the sandbox. And so it is with Java programs: in some cases, I might trust them to access my filesystem; in other cases, I might trust them to access only part of my filesystem; and in still other cases, I might not trust them to access my filesystem at all.
Applets, Applications, and Programs
In early versions of Java, only applets were run within a sandbox. In the Java 2 platform, all programs have the potential to run in a sandbox. Applets that run through the Java Plug-in or the appletviewer will always run in a sandbox, and applications that are run via the command line (or by clicking an icon on the desktop) may optionally be set up to use a sandbox. Applications also have the option of programatically installing new versions of the sandbox.
Hence, in the Java 2 platform there is little distinction between the security level of an applet and an application. There are programmatic differences, of course, but both are subject to the same security model, and the security model for both is administered and programmed in the same way. There is one significant difference, however: applets always run with Java's security model (even if that model has been administered such that the applet is allowed to do anything it wants to), and an application will only run under the security model if it is told to do so. This is typically done by the end user by specifying a command-line parameter; it may be done by the program developer who specifies that parameter in a script that starts the application, and it may be done by the developer who inserts code into his program.
Any program, including an applet, can change the behavior of the sandbox under certain circumstances. However, most of them will use Java's default sandbox. The default sandbox, as we'll see in Chapter 2, The Default Sandbox, is very flexible; it allows the user who runs the program to determine exactly how the sandbox will operate. This moves the definition of the security policy to the end user or system administrator of the machine running the program.
Anatomy of a Java Program
The anatomy of a typical Java program is shown in Figure 2. Each of the features of the Java platform that appears in a rectangle plays a role in the development of the Java security model. In particular, the elements of the Java security policy are defined by:
- The bytecode verifier
- The bytecode verifier ensures that Java class files follow the rules of the Java language. In terms of resources, the bytecode verifier helps enforce memory protections for all Java programs. As the figure implies, not all classes are subject to bytecode verification.
- The class loader
- One or more class loaders load all Java classes. Programatically, the class loader can set permissions for each class it loads.
- The access controller
- The access controller allows (or prevents) most access from the core API to the operating system, based upon policies set by the end user or system administrator.
- The security manager
- The security manager is the primary interface between the core API and the operating system; it has the ultimate responsibility for allowing or preventing access to all system resources. However, it exists mostly for historical reasons; it defers its actions to the access controller.
- The security package
- The security package (that is, classes in the
java.securitypackage as well as those in the security extensions) allows you to add security features to your own application as well as providing the basis by which Java classes may be signed. Although it is only a small box in this diagram, the security package is a complex API and discussion of it is broken into several chapters of this book. This includes discussions of:
- The security provider interface -- the means by which different security implementations may be plugged into the security package
- Message digests
- Keys and certificates
- Digital signatures
- Encryption (through JCE and JSSE)
- Authentication (through JAAS)
- The key database
- The key database is a set of keys used by the security infrastructure to create or verify digital signatures. In the Java architecture, it is part of the security package, though it may be manifested as an external file or database.
The last two items in this list have broad applicability beyond expanding the Java sandbox. With respect to the sandbox, digital signatures play an important role because they provide authentication of who actually provided the Java class. As we'll see, this provides the ability for end users and system administrators to grant very specific privileges to individual classes or signers. But a digital signature might be used for other applications. Let's say that you're deploying a payroll application throughout a large corporation. When an employee sends a request to view his payroll information, you really want to make sure that the request came from that employee rather than from someone else in the corporation. Often, this type of application is secured by a simple password, but a more secure system could require a digitally signed request before it sent out the payroll information.
This list is also a rough outline of the path we'll take through this book. We'll start by looking at the default sandbox and how it can be administered. Following that, we'll look at the details of everything that makes up that sandbox, from the bytecode verifier through the access controller. Then we'll move into the security APIs that allow you to add digital signatures and encryption to your own applications.