Client-Side Changes Disabling Dynamic Classloading Entirely

This means that the JVM containing the registry needs to load the following classes: Account AccountImpl_Stub Money NegativeAmountException OverdraftException The problem is this: if the registry had any of these classes on its local classpath, then it would load them from the filesystem instead of using the URLs contained in their annotation. However, if the naming service loads the class from the local filesystem, then, when the client requests the instance, the original annotation will be lost the classes will either not have an annotation or will be annotated with the value of java.rmi.server.codebase thats set for the naming services JVM. The only way we can guarantee to preserve codebase annotations is by paying attention to the third rule from earlier: If a class wasnt loaded from the filesystem but was instead loaded via dynamic classloading, the original annotation, which was used to load the class in the first place, is retained and sent as the class annotation. This means that no application-specific classes should be on the naming services classpath. Failing to clear the naming services classpath is probably the single most common reason why dynamic classloading breaks down. It can be really annoying because the calls to bind or rebind will succeed. The failure will only become apparent when the client tries to retrieve the stub.

19.5.3 Client-Side Changes

On the client side, there are two things that need to be done. The first is that a SecurityManager must be installed. Without a SecurityManager, RMI will not dynamically load classes. Installing a SecurityManager usually amounts to adding a single line of code to the client, which will be executed very early in the applications lifecycle. For example, adding the following line to main will do the trick: public void mainString args[] { System.setSecurityManagernew RMISecurityManager ; ... } The second thing that must be done is that the classes that will be dynamically downloaded need to be removed from or just not installed on the clients classpath. Thats it. With these changes, an RMI application can dynamically load classes from a server at runtime. Once you install a security manager, you will also need to install a security policy. Well discuss this in detail in Chapt er 20 . In the meantime, you can use the wide-open security policy that we defined for the server-side eariler and specify the -Djava.security.policy=file option on the command line for the client.

19.5.4 Disabling Dynamic Classloading Entirely

There are a number of situations when you may not want any form of dynamic classloading to be enabled. For example, while it makes perfect sense to download classes to client applications, its much dicier when clients upload classes to servers. Generally, thats a security risk a typical enterprise application might want to avoid. There are two ways to do this. The first is to not install a security manager. Well talk more about security managers in Chapt er 20 , but the basic point is that RMI wont dynamically load classes unless a security manager is installed. On the other hand, security managers are useful objects, and you probably want to use one. The second way to disable dynamic classloading is to set a specific system property. If the java.rmi.server.useCodebaseOnly system property is set to true , then RMI will only load classes from the local filesystem, regardless of whether the class has a codebase annotation.

Chapter 20. Security Policies

Making a distributed system secure is a mindnumbingly difficult task. As a system acquires more users, it will naturally acquire more security holes. In this chapter, well discuss a general-purpose Java mechanism for safeguarding against a new type of security problem. By the end of this chapter, you will understand the security policy mechanism in Java 2, and know how to use it to safeguard some aspects of your RMI application. RMI has been part of the Java platform for a long time. The first versions of RMI were interim releases that worked with JDK 1.2. With JDK 1.1, RMI became part of the Java specification. However, when Java 2 was released, something surprising happened. Working RMI applications suddenly failed. They compiled perfectly, they linked correctly, and they appeared to launch correctly. Yet whenever an application attempted to connect to an external process e.g., the launch code tried to connect to the registry, a socket exception was thrown. The reason for this: Java 2 contains a whole new security model. The net effect of the new security model is that a piece of code, unless explicitly granted permission, is not allowed to access anything that is not entirely contained within the JVM. This means that, for example, a legacy RMI application that doesnt have the appropriate permissions will no longer be able to open socket connections. Because all of RMIs messages travel across socket connections, the new security model quite effectively breaks legacy applications. Technically speaking, this isnt quite true. Permissions are enforced by the security manager. Applications that dont have a security manager installed still behave as they used to behave. However, any program that installs a security manager as RMI programs usually do now requires a security policy. Well discuss how SecurityManagers work in more detail later in this chapter.

20.1 A Different Kind of Security Problem

In Chapt er 2 , we discussed the three classical security problems that can arise in a distributed application. Data confidentiality How do we prevent third parties from seeing confidential information?