CONTENTS | PREV | NEXT | Java Security Architecture |
The JAR and Manifest specifications on code signing allow a very flexible format. Classes within the same archive can be signed with different keys, and a class can be unsigned, signed with one key, or signed with multiple keys. Other resources within the archive, such as audio clips and graphic images, can also be signed or unsigned, just like classes can.This flexibility brings about the issue of interpretation. The following questions need to be answered, especially when keys are treated differently:
1. Should images and audios be required to be signed with the same key if any class in the archive is signed? 2. If images and audios are signed with different keys, can they be placed in the same appletviewer (or browser page), or should they be sent to different viewers for processing?These questions are not easy to answer, and require consistency across platforms and products to be the most effective. Our intermediate approach is to provide a simple answer -- all images and audio clips are forwarded to be processed within the same applet classloader, whether they are signed or not. This temporary solution will be improved once a consensus is reached.Moreover, if a digital signature cannot be verified because the bytecode content of a class file does not match the signed hash value in the JAR, a security exception is thrown, as the original intention of the JAR author is clearly altered. Previously, there was a suggestion to run such code as untrusted. This idea is undesirable because the applet classloader allows the loading of code signed by multiple parties. This means that accepting a partially modified JAR file would allow an untrusted piece of code to run together with and access other code through the same classloader.
The class java.security.SecureClassLoader subclasses from the abstract system java.lang.ClassLoader. The AppletClassLoader now subclasses from the SecureClassLoader. It is our hope that all existing and future classloaders subclass from SecureClassLoader and not directly from the system classloader.Classloaders are very delicate, and the current class loading architecture is still not perfect (or perfectly secure). Applets and applications can create classloaders only if the system security policy is configured to allow this to happen. (We are working towards a solution so that the creation of classloaders or SecureClassLoader need not be so strictly controlled).
Suppose versioning support may require that classes from the same package be loaded by the same classloader; this is already the default behavior of the SecureClassLoader. However, if the classloader should load only classes from that single package, then the classloader needs to be customized.
The new access control mechanism is fully backward compatible. For example, all check methods in SecurityManager are still supported, although most of their implementations are changed to call AccessController. Note that certain internal security checks may stay in the SecurityManager class, unless it can be parameterized.We have not at this time revised all JDK system code to call AccessController instead of calling SecurityManager (and checking for the existence of a classloader), because of the potential of existing third-party applications that subclass the SecurityManager and customize the check methods. In fact, we added a new method SecurityManager.checkPermission() that by default simply invokes AccessController.checkPermission().
To understand the relationship between SecurityManager and AccessController, it is sufficient to note that SecurityManager represents the concept of a central point of access control, while AccessController implements a particular access control algorithm, with special features such as the doPrivileged() method. By keeping SecurityManager up to date, we maintain backward compatibility (e.g., for those applications that have written their own security manager classes based on earlier versions of the JDK) and flexibility (e.g., for someone wanting to customize the security model to implement mandatory access control or multilevel security). By providing AccessController, we build in the algorithm that we believe is the most restrictive and that relieves the typical programmer from the burden of having to write extensive security code in most scenarios.
We strongly encourage the use of AccessController in application code, while customization of a security manager (via subclassing) should be the last resort and should be done with extreme care. Moreover, a customized security manager, such as one that always checks the time of the day before invoking standard security checks, could and should utilize the algorithm provided by AccessController whenever appropriate.
On another often-discussed topic, resource consumption management is relatively easy to implement in some cases (e.g., to limit the number of windows any application can pop up at any one time) but hard in other cases (e.g., to limit memory or file system usage). We plan to coherently address such issues in the future.
A potentially useful concept not currently implemented is that of "subdomains." A subdomain is one that is enclosed in another. A subdomain would not have more permissions or privileges than the domain of which it is a subpart. A domain could be created, for example, to selectively further limit what a program can do.Often a domain is thought of as supporting inheritance: a subdomain would automatically inherit the parent domain's security attributes, except in certain cases where the parent further restricts the subdomain explicitly. Relaxing a subdomain by right amplification is a possibility with the notion of trusted code.
For convenience, we can think of the system domain as a single, big collection of all system code. For better protection, though, system code should be run in multiple system domains, where each domain protects a particular type of resource and is given a special set of rights. For example, if file system code and network system code run in separate domains, where the former has no rights to the networking resources and the latter has no rights to the file system resources, the risks and consequence of an error or security flaw in one system domain is more likely to be confined within its boundary.
Sometimes it is convenient to group a number of permissions together and use a short-hand name to refer to them. For example, if we would like to have a permission called "SuperPermission" to include (and imply) both FilePermission("-", "read,write") and SocketPermission("*", "connect,accept"), technically we can use the class Permissions or a similar class to implement this super permission by using the "add()" methods to add the required permissions. And such grouping can be arbitrarily complicated.The more difficult issues are the following. First, to understand what actual permissions one is granting when giving out such a super permission, either a fixed and named permission class is created to denote a statically specified group of permissions, or the member permissions need to be spelled out in the policy file. Second, processing the policy (file) can become more complicated because the grouped permissions may need to be expanded. Moreover, nesting of grouped permission increases complexity even more.
Today the notion of a principal (e.g., user) is implicit because each JVM is owned by one user. In the future, there will be a need to extend the existing concept of ProtectionDomain to include the notion of "running-on-behalf of" a principal.Therefore, we are actively looking to provide the following features in the near future:
Given the object-oriented nature of the Java programming language, it is conceivable that developers will benefit from a set of appropriate object-level protection mechanisms that (1) goes beyond the natural protection provided by Java the language and that (2) supplements the thread-based access control mechanism.One such mechanism is SignedObject. Parallel to this primitive, we will provide SealedObject that uses encryption to hide the content of an object. (Due to current U.S. export control regulations on the use of encryption, the SealedObject class will likely be provided separate from JDK.)
GuardedObject is a general way to enforce access control at a per class/object per method level. This method, however, should be used only selectively, partly because this type of control can be difficult to administer at a high level.