The Artima Developer Community
Sponsored Link

Chapter 3 of Inside the Java Virtual Machine
Security
by Bill Venners

<<  Page 11 of 17  >>

Advertisement

The Access Controller

Class java.security.AccessController provides a default security policy enforcement mechanism that uses stack inspection to determine whether potentially unsafe actions should be permitted. The access controller can't be instantiated. It isn't an object. Rather, it is a bundle of static methods collected in a single class. The central method of the AccessController is its static checkPermission() method, which decides whether or not a particular action is allowed. This method returns void and takes a reference to a Permission object as its only parameter. Similar to the check methods of the security manager, if the AccessController decides the operation should be allowed, its checkPermission() method simply returns silently. But if the AccessController decides that an operation should be forbidden, its checkPermission() method completes abruptly by throwing an AccessControlException, or one of its subclasses.

As mentioned previously, the concrete SecurityManager's implementation of the legacy check methods (such as checkRead() and checkWrite()) simply instantiate an appropriate Permission object and invoke the concrete SecurityManager's checkPermission() method. The concrete SecurityManager's checkPermission() method simply invokes checkPermission() on the AccessController. Thus, if you install the concrete SecurityManager, the AccessController is the ultimate entity that decides whether or not potentially unsafe actions will be allowed.

The basic algorithm implemented by the AccessController's checkPermission() method makes certain that every frame on the call stack has permission to perform the potentially unsafe action. Each stack frame represents some method that has been invoked by the current thread. Each method is defined in some class. Each class belongs to some protection domain. And each protection domain contains a set of permissions. Thus, each stack frame is indirectly associated with a set of permissions. For an action represented by the Permission object passed to the AccessController's checkPermission() method to be allowed, the basic algorithm of the AccessController requires that the permissions associated with each frame on the call stack must include or imply the Permission passed to checkPermission().

The AccessController's checkPermission() method inspects the stack from the top down. As soon as it encounters a frame that doesn't have permission, it throws an AccessControlException. By throwing the exception, the AccessController, indicates that the action should not be allowed. On the other hand, if the checkPermission() method reaches the bottom of the stack without encountering any frames that don't have permission to perform the potentially unsafe action, checkPermission() returns silently. By returning rather than throwing an exception, the AccessController indicates the action should be allowed

The actual algorithm implemented by the AccessController's checkPermission() method is a bit more complex than the basic algorithm described here. By invoking any of several doPrivileged() methods of class AccessController, programs can in effect cause the AccessController to stop its frame by frame search before it reaches the bottom of the stack. The doPrivileged() method will be described later in this chapter.

The implies() Method

To determine whether or not the action represented by the Permission object passed to the AccessController's checkPermission() method is included among (or implied by) the permissions associated with the code on the call stack, the AccessController makes use of an important method named implies(). The implies() method is declared in class Permission, as well as in classes PermissionCollection and ProtectionDomain. implies() takes a Permission object as its only parameter and returns a boolean true or false. The implies() method of class Permission determines whether the permission represented by one Permission object is naturally implied by the permission represented by a different Permission object. The implies() methods of PermissionCollection and ProtectionDomain determine whether the passed Permission is included among or implied by the collection of Permission objects encapsulated in the PermissionCollection or ProtectionDomain.

For example, a permission to read all files in the /tmp directory would naturally imply a permission to read /tmp/f, a specific file in the /tmp directory, but not vice versa. If you asked a FilePermission object that represents the permission to read any file in the /tmp directory if it implies the permission to read file /tmp/f, the implies() method should return true. But if you ask a FilePermission object representing the permission to read /tmp/f if it implies the permission to read any file in the /tmp directory, the implies() method should return false.

The Example1 application from the security/ex1 directory of the CD-ROM demonstrates this meaning of implies():

import java.security.Permission;
import java.io.FilePermission;
import java.io.File;

// On CD-ROM in file security/ex1/Example1.java
class Example1 {

    public static void main(String[] args) {

        char sep = File.separatorChar;

        // Read permission for "/tmp/f"
        Permission file = new FilePermission(
            sep + "tmp" + sep + "f", "read");

        // Read permission for "/tmp/*", which
        // means all files in the /tmp directory
        // (but not any files in subdirectories
        // of /tmp)
        Permission star = new FilePermission(
            sep + "tmp" + sep + "*", "read");

        boolean starImpliesFile = star.implies(file);
        boolean fileImpliesStar = file.implies(star);

        // Prints "Star implies file = true"
        System.out.println("Star implies file = "
            + starImpliesFile);

        // Prints "File implies star = false"
        System.out.println("File implies star = "
            + fileImpliesStar);
    }
}

The Example1 application creates two FilePermission objects, one that represents read permission for a particular directory and another that represents read permission for a particular file in that same directory. The FilePermission object referenced from local variable star represents permission to read any file in /tmp. The FilePermission object referenced from local variable file represents permission to read file /tmp/f. When executed, this application prints:

Star implies file = true
File implies star = false

The implies() method is used by the AccessController to determine whether a thread has permission to take actions. If the checkPermission() method of the AccessController is invoked to determine whether that thread has permission to read file /tmp/f, for example, the AccessController can invoke the implies() method on the ProtectionDomain objects associated with each frame of that thread's call stack. To each implies() method, the AccessController can pass the FilePermission object representing permission to read file /tmp/f that was passed to its checkPermission() method. The implies() method of each ProtectionDomain object can invoke implies() on the PermissionCollection it encapsulates, passing along the same FilePermission. Each PermissionCollection can in turn invoke implies() on the Permission objects it contains, once again passing along a reference to the same FilePermission object. As soon as a PermissionCollection's implies() method encounters one Permission object whose implies() method returns true, the PermissionCollection's implies() method returns true. Only if none of the implies() methods of the Permission objects contained in a PermissionCollection return true does the PermissionCollection return false. The ProtectionDomain's implies() method simply returns what the PermissionCollection's implies() method returns. If the AccessController gets back a true from the implies() method of a ProtectionDomain associated with a particular stack frame, the code represented by that stack frame has permission to perform the potentially unsafe action.

<<  Page 11 of 17  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use