A security architecture for PerDiS in Java

George Coulouris, Jean Dollimore, Tim Kindberg and Marcus Roberts

{george|jean| timk|marcusr}@dcs.qmw.ac.uk

Department of Computer Science
Queen Mary and Westfield College
London E1 4NS


23 September 1997

The PerDiS DSM platform [1] is intended to support collaborative working in virtual enterprises. The organisations that make up a virtual enterprise are partners in a collaborative project, but they may be competitors in other areas. A PerDiS security design encompassing the protection of clusters of objects with role-specific access rights and a secure communication subsystem has been defined [2]. The security design is based upon a trust model that enables necessary sharing of information to occur even when there is only minimal trust between participating organisations. A proposal exists for the implementation of the PerDiS security model in a UNIX/C++ environment [2].

In this paper we propose an architecture for the implementation of PerDiS object sharing and protection in Java. Our architecture is designed as a set of system classes to be written in Java and run over a minimally-modified Java virtual machine. The proposed architecture is intended to support the controlled sharing of persistent objects through a DSM that stores its objects at one of a set of storage services. We describe our architecture with reference to PJava [4,5], which supports a version of Java that includes persistent objects, but does not currently include distribution or protection.

The sharing of objects is controlled by an access control guard that restricts access according to the identity of the principal and a predefined set of access control rules for (clusters of) objects. We retain the PerDiS notion that strong protection can be applied to clusters of objects - a cluster is not delivered to the machine of any principal unless they have the right to read it and updates are not accepted from the machine of any principal unless they have the right to write it. This is protection by separation. The protection mechanisms are strong because they rely upon strong cryptography to ensure the integrity, authenticity and secrecy of communication amongst cooperating machines.

Architecture

Our proposed architecture requires:

  1. A cache manager component on each site maintaining a cache of clusters (or pages thereof) obtained from a local storage service or from other sites. These clusters are shared with other sites.
  2. A protection manager that applies access control checks before:
  3. Secure authenticated communication between sites for the transmission of requests and the contents of clusters.
  4. A storage service for managing clusters of inactive persistent objects.

The first three components have a job similar to the PerDiS Daemon in the current UNIX/C++ implementation, but they will be written in Java and will run on a minimally modified JVM. The fourth component is analogous to the Texas persistent store [3] in the current PerDiS implementation and to the Object Store in PJava.

Figure 1

Figure 1. The role of the PerDiS Shell

PerDiS shell

To enable components 1-3 to manage a cache of clusters for multiple applications running on behalf of the same principal, we propose that they should play the role of a shell by loading the code of applications into the JVM and running them. For this reason we call them the PerDiS Shell.. The PerDiS shell is written entirely in Java. Clearly, the PerDiS shell should be trustworthy code, which can be achieved using the trusted code features of Java 1.1.

Figure 1 shows the role of the PerDiS Shell in relation to the JVM and other components. We require a modified JVM (like the one provided by PJava) that allows objects to be loaded from the cluster cache into the PJava object cache whenever they are referenced in Java programs. [footnote: Persistent Java divides the memory of the Java Virtual Machine into two parts: an Object Cache that holds active copies of persistent objects and the standard heap that holds transient objects. PerDiS objects are always persistent and will therefore be loaded into the Object Cache.] Objects in the object cache are written back to the cluster cache on transaction commit for sharing with other applications and for saving at a storage service. Our PJVM includes the functionality in PJava for object-faulting, loading objects in the PJava object cache, marking and flushing dirty objects. The PJVM also includes a persistent storage service - this is similar to our storage service but we treat it as a separate component, allowing different storage strategies to be adopted as required.

Each PerDiS user runs a Java application called the PerDiS shell, which has the following functionality:

The PerDiS shell contains a custom class loader, which optionally checks that application classes have been signed by a recognised PerDiS agency, before execution. The signature attests to the trustworthiness of the loaded class. Some sites may prefer to forgo these checks, in the name of efficiency. The checks may in any case be foregone for classes belonging to recognised PerDiS packages (which are part of the PerDiS distribution, and therefore trusted).

The PerDiS shell registers itself as the persistent store for its PJVM. This causes the PJVM to communicate with it whenever it needs to load or flush an object. The shell handles the request by:

The PerDiS shell installs its own security manager, which protects threads belonging to different applications from one another. It does this by securely associating a different thread group with each application, and ensuring that only threads belonging to the same group may perform operations on one another.

Protection manager

The Protection Manager in the PerDiS shell applies access control to all requests from the PJVM to load or flush objects. We propose that the access control rules are implemented by a class called ProtectionManager and that an instance of this class is available. We refer to this instance as the Protection Manager.

The rights to access a cluster available to the principal running the Java application in the PJVM can be discovered by invoking the get_access_rights method in the Protection Manager. The get_access_rights method takes as arguments a set of certificates representing the user's credentials and the security attributes of the cluster. The security attributes are obtained from the reserved part of the cluster. The method returns the principal's access rights to the cluster.

Issues arising

Exception reporting

Protection violations should raise exceptions as soon as an unauthorised access is attempted. For read accesses, this will occur naturally n our architecture, since the protection manager will detect any attempt to follow a reference to an object for which the user does not have read rights and will immediately raise the appropriate exception. However to enable write-protection violations to be reported synchronously (as opposed to reporting them only when the relevant transaction completes) we require an additional mechanism.

This additional mechanism comprises a "Read only" flag attached to each object when it is in the PJava object cache. The read only flag must be checked by the PJava interpreter whenever an assignment to any of the variables of an object is attempted. If the Read only flag is set, the interpreter must refuse to perform the assignment and raise an exception.

Unfortunately, this mechanism entails a low-level modification to the Java execution mechanism. This seems to be a drawback of the Java implementation versus the C++ implementation, where memory protection hardware can be used to trigger a program interrupt when an unauthorised write is attempted on a read-only cluster.

We understand that PJava has already required a similar modification (to maintain a "dirty" flag on each object in the object cache) and it may be possible to extend that mechanism to include our Read only check.

Possible security violations

The user who wishes to gain rights to enable them to read a cluster without having the access rights may use one of the following lines of attack :

  1. substitute their own version of the ProtectionManager class.
  2. replace the Protection Manager by an instance of a subclass with an override of the get_access_rights method.
  3. provide false information by altering the value of a class or instance variable (perhaps via setter methods) either in the ProtectionManager class or in another related class.

Regarding the first line of attack: the ProtectionManager class must be loaded before its instance, the Protection Manager can be created. After this, the class of the Protection Manager cannot be changed. This is achieved by creating the Protection Manager in the PerDiS Shell before any application code is run.

Java 1.1 provides 'blank finals'. These are variables that can be assigned once only - that is, they are effectively constants that are initialised at run time. The variable that holds the value of the Protection Manager can be made a blank final to prevent the second line of attack.

Another defense against the second line of attack is to make the ProtectionManager class final, which prevents it from having subclasses; or less restrictively, the sensitive methods such as get_access_rights may be made final.

The third line of attack can be prevented either by making the variables and their setter functions private or where appropriate making them final (constants).

Note that the reflection facilities of Java 1.1 allow programs to find out the names of the private variables, but does not allow access to them.

Secure Communication

PerDiS shells will communicate with one another in order to acquire or store a cluster in response to load and flush requests from their local PJVM that refer to remote clusters. The communication requirements and the rules for access control on acquiring remote clusters are described in [1] sections 4.1-4.3. Here we propose a design based on a set of Java classes that support secure communication based on signed messages.

An instance of a class Request will be available to the PerDiS Shell for sending and receiving the messages needed to acquire a remote cluster. It will provide an acquire method to be used to acquire a remote cluster by giving as argument the cluster name, the required mode and the credentials of the user on whose behalf it is made. The result of a successful invocation of acquire is that the cluster and a read or write token is returned, but an access control exception will be raised if the user does not have read access rights to the cluster.

The PerDiS Shell will provide an instance of a Server class that is responsible for servicing authenticated messages containing acquire requests. On receipt of a message containing an acquire request the PerDiS shell will perform the following actions:

The reply message will be signed by the private key of the principal running the PerDiS Shell.

Conclusions

This preliminary investigation indicates that it is feasible to implement the strong protection mechanisms of PerDiS in Java. The only modifications required to the Java Virtual Machine are very similar to those required by Persistent Java.

The facilities for establishing trust in Java byte codes (through the use of custom class loaders and signed digests of code) and the strong typing of Java programs enable strong protection to be implemented within a single JVM (whereas PerDiS protection architecture for UNIX/C++ requires separate address spaces for system and application code).

We have not discussed the implementation of finer-grained protection (at the level of individual objects and their instance variables) in this paper, but we hold the view that the reflection mechanisms of Java may provide the necessary machinery to enable fine-grained object filters to be constructed.

References

1. Shapiro et al. 1996. The PerDiS Project general description.
[ http://www.perdis.esprit.ec.org/papers/detailed.html]
2. Coulouris and Dollimore, Security Services Design, PerDiS deliverable TD 1.1a. June 3, 1997.
[ http://www.dcs.qmw.ac.uk/research/distrib/perdis/deliverables/TD1.1a.html]
3. Vivek Singhal, Sheetal Kakkad, and Paul Wilson. Texas: An Efficient, Portable Persistent Store. In Persistent Object Systems: Proceedings of the Fifth International Workshop on Persistent Object Systems, pages 11-33, San Miniato, Italy, September 1992.
[ http://www.cs.utexas.edu/users/oops/papers.html#texas]
4. Atkinson et al, Design Issues for Persistent Java: a type-safe, object-oriented, orthogonally persistent system, Seventh International Workshop on Persistent Object Systems (POS7) May 1996.
[http://www.dcs.gla.ac.uk/pjava/]
5. Tony Printezis, Malcolm Atkinson, Laurent Daynes, Susan Spence and Pete Bailey, The Design of a new Persistent Object Store for PJama, Second International Workshop on Persistence and Java, August 1997.
[ http://www.sunlabs.com/research/forest/pjw2/]