The Artima Developer Community
Sponsored Link

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

<<  Page 16 of 17  >>

Advertisement

A Futile Use of doPrivileged()

It is important to understand that a method can never grant itself more privileges than it already has with a doPrivileged() invocation. By calling doPrivileged(), a method is merely enabling privileges it already has. It is telling the AccessController that it is taking responsibility for exercising its own permissions, and that the AccessController should ignore the permissions of its callers. Thus, the doPrivileged() call in the previous example, Example2c enabled answer.txt to be read because Friend, the class that executed the doPrivileged(), already had permission to read the file, and so did all the frames above it on the stack.

For an example of a futile attempt to use doPrivileged(), consider the Example2d application from the security/ex2 directory of the CD-ROM:

// On CD-ROM in file security/ex2/Example2d.java
import com.artima.security.friend.Friend;
import com.artima.security.stranger.Stranger;

// This fails because even though Stranger does
// a doPrivileged() call, Stranger doesn't have
// permission to read question.txt. (Passing
// false as second arg to Stranger constructor
// causes it to do a doPrivileged().)

class Example2d {

    public static void main(String[] args) {

        TextFileDisplayer tfd = new TextFileDisplayer("answer.txt");

        Stranger stranger = new Stranger(tfd, false);

        Friend friend = new Friend(stranger, true);

        friend.doYourThing();
    }
}

The difference between Example2d and the previous example, Example2c, is that the Stranger and Friend objects have swapped positions and roles. The Stranger object is now farther up the stack, with the Friend below it on the stack. And this time, it is Stranger that will make the call to doPrivileged(), not Friend.

When the Example2d program invokes doYourThing() on the Friend object referenced from the friend variable, the Friend object invokes doYourThing() on the Stranger object, which (because direct is false) invokes doPrivileged(), passing in the anonymous inner class instance that implements PrivilegedAction. The doPrivileged() method invokes run() on the passed PrivilegedAction object, which invokes doYourThing() on the TextFileDisplayer object.

As in the previous two examples, TextFileDisplayer's doYourThing() method attempts to open and read a file named "answer.txt" in the current directory and print its contents to the standard output. When TextFileDisplayer's doYourThing() method creates a new FileReader object, the FileReader constructor creates a new FileInputStream, whose constructor checks to see whether or not a security manager has been installed. As in all the examples, the concrete SecurityManager has been installed, so the FileInputStream's constructor invokes checkRead() on the concrete SecurityManager. The checkRead() method instantiates a new FilePermission object representing permission to read file answer.txt and passes that object to the concrete SecurityManager's checkPermission() method, which passes the object on to the checkPermission() method of the AccessController. The AccessController's checkPermission() method performs the stack inspection to determine whether this thread should be allowed to open file answer.txt for reading. The stack presented to the AccessController by Example2d is shown in Figure 3-9.



Figure 3-9. Stack inspection for Example2d: frame five doesn't have permission.

The call stack to be inspected in Example2d looks similar to the call stack inspected in Example2c. The only difference is that Friend and Stranger have swapped positions. As always, stack inspection starts at the top of the stack and proceeds on down the stack towards frame one. But alas, once again the inspection process will not actually reach frame one. When the AccessController reaches frame five, it discovers a stack frame associated with the STRANGER protection domain, which doesn't have permission to read answer.txt. As a result of this discovery, the AccessController throws an AccessControlException, indicating the requested read of answer.txt should not be performed.

Had the Stranger class been able to enlist the assistance of an instance of some class that implemented PrivilegedAction, performed the desired invocation of the TextFileDisplayer's doYourThing() method, and belonged to a protection domain that has permission to read >answer.txt, Stranger's attempt to open answer.txt with the help of doPrivileged() would have still been futile. Imagine, for example, that the code of the run() method represented by frame five of Example2d's call stack had been associated with to the CD-ROM protection domain. In that case, the AccessController would have determined that frame five had permission to open answer.txt and continued on to frame four. At frame four, the AccessController would have discovered the doPrivileged() invocation. As a result of this discovery, the AccessController would make one more check: it would make certain the method that invoked doPrivileged(), which in this case was Stranger's doYourThing() method represented by stack frame three, has permission to read file answer.txt. Because frame three is associated with the STRANGER protection domain that doesn't have permission to read answer.txt, the AccessController would still throw an AccessControlException.

To get the Example2d application to work as intended, you must start the application with yet another appropriate command. When using the java program from the Java 2 SDK version 1.2, the appropriate command takes the form:

java -Djava.security.manager -Djava.security.policy=policyfile.txt -
Dcom.artima.ijvm.cdrom.home=d:\books\InsideJVM\manuscript\cdrom -cp
.;jars/friend.jar;jars/stranger.jar Example2d

This command, which is contained in the ex2d.bat file in the security/ex2 directory of the CD-ROM, is an example of the kind of command you'll need to use to get the example to work. As before, to execute Example2d on your own system, you must set the com.artima.ijvm.cdrom.home property to the security/ex2 directory of your CD-ROM, or to whatever directory you may have copied the security/ex2 directory from the CD-ROM. When you run this program, you should see the kind of output that crackers everywhere hate to see:

Exception in thread "main" java.security.AccessControlException: access
denied (java.io.FilePermission answer.txt read)
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:195)
	at java.security.AccessController.checkPermission(AccessController.java:403)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.lang.SecurityManager.checkRead(SecurityManager.java:873)
	at java.io.FileInputStream.(FileInputStream.java:65)
	at java.io.FileReader.(FileReader.java:35)
	at TextFileDisplayer.doYourThing(TextFileDisplayer.java, Compiled Code)
	at com.artima.security.stranger.Stranger$1.run(Stranger.java:27)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.artima.security.stranger.Stranger.doYourThing(Stranger.java:24)
	at com.artima.security.friend.Friend.doYourThing(Friend.java:21)
	at Example2d.main(Example2d.java:21)

<<  Page 16 of 17  >>


Sponsored Links



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