Summary The Security Manager

Chapter 5. The Access Controller

In the last chapter, we looked at the security manager, which provides the security policy interface used by the core Java API. The implementation of most security managers, however, is based entirely upon the access controller. In this chapter, were going to look at the access controller and its related classes. Along the way, well cover a number of important topics: How to implement and use your own permission classes to extend the mechanism of the Java sandbox to your own applications. • How to implement a different security policy so that permissions can be set in new ways e.g., by reading them from a central server rather than from a collection of files. • How the core Java API is able to perform certain operations that other classes cannot. • How to create objects that can only be accessed if you have the appropriate permission. • The access controller is built upon the four concepts we examined in Chapter 2 : Code sources An encapsulation of the location from which certain Java classes were obtained. Permissions An encapsulation of a request to perform a particular operation. Policies An encapsulation of all the specific permissions that should be granted to specific code sources. Protection domains An encapsulation of a particular code source and the permissions granted to that code source. Well start by examining how these concepts map to the Java API.

5.1 The CodeSource Class

A code source is a simple object that reflects the URL from which a class was loaded and the keys if any that were used to sign that class. Class loaders are responsible for creating and manipulating code source objects, as well see in the next chapter. The CodeSource class java.security.CodeSource has a few interesting methods: public CodeSourceURL url, Certificate cers[] Create a code source object for code that has been loaded from the specified URL. The optional array of certificates is the array of public keys that have signed the code that was loaded from this URL. These certificates are typically obtained from reading a signed jar file; if the code was not signed, this argument should be null . Similarly, the URL may be null . public boolean equalsObject o Two code source objects are considered equal if they were loaded from the same URL that is, the equals method for the URL of the objects returns true and the array of certificates is equal that is, a comparison of each certificate in the array of certificates will return true . public final URL getLocation Return the URL that was passed to the constructor of this object. public final Certificate[] getCertificates Return a copy of the array of certificates that was used to construct this code source object. The original certificates are not returned so that they cannot be modified accidentally or maliciously. public boolean impliesCodeSource cs Determine if the code source implies the parameter according to the rules of the Permission class see later in this chapter. One code source implies another if it contains all the certificates of the parameter and if the URL of the parameter is implied by the URL of the target. Thats the extent of the CodeSource class. In Chapter 6, well show how to construct and use class loaders; later in this chapter, well see how they fit into the design of the access controller.

5.2 Permissions

The basic entity that the access controller operates on is a permission object −− an instance of the Permission class java.security.Permission . This class, of course, is the basis of the types that are listed in a policy file for the default security policy. The Permission class itself is an abstract class that represents a particular operation. The nomenclature here is a little misleading because a permission object can reflect two things. When it is associated with a class through a code source and a protection domain, a permission object represents an actual permission that has been granted to that class. Otherwise, a permission object allows us to ask if we have a specific permission. For example, if we construct a permission object that represents access to a file, possession of that object does not mean we have permission to access the file. Rather, possession of the object allows us to ask if we have permission to access the file. An instance of the Permission class represents one specific permission. A set of permissions −− e.g., all the permissions that are given to classes signed by a particular individual −− is represented by an instance of the Permissions class java.security.Permissions . Weve seen how administrators use the class in order to modify security policies; now well look into the programming behind this class, including defining your own permission classes.

5.2.1 The Permission Class

Recall that permissions have three properties: a type, a name, and some actions. The name and actions are optional. The type corresponds to an actual Java type e.g., java.io.FilePermission ; the types that are built into the core API are listed in Chapter 2. The name of a permission is fairly arbitrary. In the case of file permissions, the name is obviously the file. But the name of the showWindowWithoutWarningBanner permission among many others is chosen by convention, and it is up to all Java programs to adhere to that convention. This is only a concern to programmers when dealing with your own permission classes; as a developer you rarely need to create 78 permission objects for the types of permissions defined in the Java API. On the other hand, this naming convention is of concern to end users and administrators, who must know the name of the permission they want to grant to the programs they are going to run. The presence of actions is dependent upon the semantics of the specific type of permission. A file permission object has a list of actions that could include read, write, and delete; an XYZ payroll permission object could have a list of actions that includes view and update. On the other hand, a window permission does not have an action: you either have permission to create the window or you dont. Actions can also be specified by wildcards. The terms used to specify a list of actions are also arbitrary and handled by convention. Permissions can serve two roles. They allow the Java API to negotiate access to several resources files, sockets, and so on. Those permissions are defined by convention within the Java API, and their naming conventions are wholly within the domain of the Java API itself. Hence, you can create an object that represents permission to read a particular file, but you cannot create an object that represents permission to copy a particular file since the copy action is not known within the file permission class. On the other hand, you can create arbitrary permissions for use within your own programs and completely define both the names of those permissions as well as the actions if any that should apply. If you are writing a payroll program, for example, you could create your own permission class that uses the convention that the name of the permission is the employee upon whose payroll information you want to act; you could use the convention that the permissible actions on the payroll permission are view and update. Then you can use that permission in conjunction with the access controller to allow employees to view their own payroll data and to allow managers to change the payroll data for their employees. From a developer perspective, this latter role is the more interesting, and well use it when we examine the permission class itself.

5.2.2 Using the Permission Class

Well now look into the classes upon which all these permissions are based: the Permission class. This class abstracts the notion of a permission and a name. From a programmatic standpoint, the Permission class is really used only to create your own types of permissions. It has some interesting methods, but the operations that are implemented on a permission object are not generally used in code that we write −− they are used instead by the access controller. Hence, well examine this class primarily with an eye towards understanding how it can be used to implement our own permissions. Permission is an abstract class that contains these public methods: public PermissionString name Construct a permission object that represents the desired permission. public abstract boolean equalsObject o Subclasses of the Permission class are required to implement their own test for equality. Often this is simply done by comparing the name and actions, if applicable of the permission. public abstract int hashCode Subclasses of the Permission class are required to implement their own hash code. In order for the access controller to function correctly, the hash code for a given permission object must never change during execution of the virtual machine. In addition, permissions that compare as equal must return Chapter 5. The Access Controller the same hash code. public final String getName Return the name that was used to construct this permission. public abstract String getActions Return the canonical form of the actions if any that were used to construct this permission. public String toString The convention for printing a permission is to print in parentheses the class name, the name of the permission, and the actions. For example, a file permission might return: java.io.FilePermission,myclassesxyzHRApplet.class,read public abstract boolean impliesPermission p This method is one of the keys of the Permission class: it is responsible for determining whether a class that is granted one permission is granted another. This method is normally responsible for performing wildcard matching so that, for example, the file permission myclasses− implies the file permission myclassesxyzHRApplet.class. But this method need not rely on wildcards; permission to write a particular object in a database would probably imply permission to read that object as well. public PermissionCollection newPermissionCollection Return a permission collection suitable for holding instances of this type of permission. Well discuss the topic of permission collections in the next section. This method returns null by default. public void checkGuardObject o Call the security manager to see if the permission i.e., the this variable has been granted, generating a SecurityException if the permission has not been granted. The object parameter of this method is unused. Well give more details about this method later in this chapter. Implementing your own permission means providing a class with concrete implementations of these abstract methods. Note that the notions of wildcard matching and actions are not generally present in this class −− if you want your class to support either of these features, youre responsible for implementing all of the necessary logic to do so although the BasicPermission class that well look at next can help us with that. Say that you are implementing a program to administer payroll information. Youll want to create permissions to allow users to view their payroll history. Youll also want to allow the HR department to update the pay rate for employees. Well need to implement a permission class to encapsulate all of that: package javasec.samples.ch05; import java.security.; import java.util.; public class XYZPayrollPermission extends Permission { protected int mask;