Installing a Policy Class

method of the AccessTest class, which has called the checkPermission method of the AccessController class. [1] The run method is always the bottom method on a stack since stacks apply on a per−thread basis. Figure 5−1. The stack and protection domains of a method The reason we need to know the stack trace of the current thread is to examine the protection domains that are on the stack. In Chapter 2, we referred to the classes on the stack as the active classes; the access controller looks at only those classes and domains that are on the stack. In this example, only the AccessTest class has been loaded by a class loader: the AppletPanel class and the Thread class were loaded from the core API with the primordial class loader. Hence, only the AccessTest class has a nonsystem protection domain associated with the URL from which we loaded it, http:piccolo in this case. The permissions in effect for any particular operation are the intersection of all permissions of each protection domain on the stack when the checkPermission method is called. When the checkPermission method is called, it checks the permissions associated with the protection domain for each method on the stack. It does this starting at the top of the stack and proceeding through each class. If this entry appeared in the policy file: grant codeBase http:piccolo { permission java.net.SocketPermission :1024−, connect; }; the protection domain that applies to the AccessTest class will have permission to open the socket. Remember that the system domain implicitly has permission to perform any operation; as there are no other nonsystem protection domains associated with any class on the stack, the checkPermission method will permit this operation −− which is to say that it will silently return. For most implementations of Java browsers, and many Java applications, there will only be a single nonsystem protection domain on the stack: all the classes for the applet will have come from a single CODEBASE and hence a single protection domain. But the checkPermission method is more general than that, and if you use a class loader that performs delegation, there will be multiple protection domains on the stack. This is a common occurrence if youre using a Java extension or your own custom class loader. Lets say that youve written a payroll application that uses a class loader that loads classes from two sources: the server in the XYZ HR department and the server in the XYZ network services department. [2] This might lead to a call to the checkPermission method with the stack shown in Figure 5−2. Note that this stack trace is a little more complicated than the one weve just shown −− in this case, were relying on the fact that the constructor of the Socket class indirectly calls the access controller because, as we mentioned in Chapter 4, it eventually calls the security manager, which calls the access controller. [2] Well show this example and class loaders to implement it in Chapter 6. Figure 5−2. A stack with multiple nonsystem protection domains In this example, the access controller first checks the protection domain for the Network class to see if a class loaded from http:network.xyz.com is allowed to connect to the socket. If that succeeds, it then checks the protection domain of the PayrollApp class to see if a class loaded from http:hr.xyz.com is allowed to connect to the socket. Only if both code sources are granted permission in the policy file either individually or via an entry that does not specify a code base at all does the checkPermission method succeed. Whether or not this is the appropriate behavior depends upon your intent. Lets say that the policy file for the payroll application specifies that classes with a code base of http:network.xyz.com are allowed to create sockets but that no other protection domains other than the system protection domain, of course are granted that permission. That leads to the situation where a class from the network services department might not be able to open a socket even though it has that permission in the file: if there is any class in the HR protection domain on the stack, the operation will fail. All classes on the stack must have permission for an operation to succeed. Often, however, you want a class to be temporarily given the ability to perform an action on behalf of a class that might not normally have that ability. In this case, we might want to establish a policy where the classes from the HR department cannot create a socket directly but where they can call classes from the network services department that can create a socket. [3] In this case, you want to tell the access controller to grant temporarily the permissions of the network services department to any methods that it might call within the current thread. [3] Consider this in terms of writing a file: an applet might not be able to write a file, but it can call a method of the SDK to play audio data −− which means the SDK class must write to the audio device file. That facility is possible with these methods of the access controller class: public static Object doPrivilegedPrivilegedAction pa public static Object doPrivilegedPrivilegedExceptionAction pae public static Object doPrivilegedPrivilegedExceptionAction action, AccessControlContext context Execute the run method on any given object, temporarily granting its permission to any protection domains below it on the stack. In the second case, if the embedded run method throws an exception, the doPrivileged method will throw a PrivilegedActionException .