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;