Whole document tree
3 Permissions and Security Policy3.1 The Permission ClassesThe permission classes represent access to system resources. The java.security.Permission class is an abstract class and is subclassed, as appropriate, to represent specific accesses. perm = new java.io.FilePermission("/tmp/abc", "read"); New permissions are subclassed either from the Permission class or one of its subclasses, such as java.security.BasicPermission. Subclassed permissions (other than BasicPermission) generally belong to their own packages. Thus, FilePermission is found in the java.io package. 3.1.1 java.security.PermissionThis abstract class is the ancestor of all permissions. It defines the essential functionalities required for all permissions. 3.1.2 java.security.PermissionCollectionThis class holds a homogeneous collection of permissions. In other words, each instance of the class holds only permissions of the same type. 3.1.3 java.security.PermissionsThis class is designed to hold a heterogeneous collection of permissions. Basically, it is a collection of java.security.PermissionCollection objects. 3.1.4 java.security.UnresolvedPermissionRecall that the internal state of a security policy is normally expressed by the permission objects that are associated with each code source. Given the dynamic nature of Java technology, however, it is possible that when the policy is initialized the actual code that implements a particular permission class has not yet been loaded and defined in the Java application environment. For example, a referenced permission class may be in a JAR file that will later be loaded. 3.1.5 java.io.FilePermissionThe targets for this class can be specified in the following ways, where directory and file names are strings that cannot contain white spaces. file directory (same as directory/) directory/file directory/* (all files in this directory) * (all files in the current directory) directory/- (all files in the file system under this directory) - (all files in the file system under the current directory) "<<ALL FILES>>" (all files in the file system) Note that "<<ALL FILES>>" is a special string denoting all files in the system. On a Unix system, this includes all files under the root directory. On an MS-DOS system, this includes all files on all drives. import java.io.FilePermission; FilePermission p = new FilePermission("myfile", "read,write"); FilePermission p = new FilePermission("/home/gong/", "read"); FilePermission p = new FilePermission("/tmp/mytmp", "read,delete"); FilePermission p = new FilePermission("/bin/*", "execute"); FilePermission p = new FilePermission("*", "read"); FilePermission p = new FilePermission("/-", "read,execute"); FilePermission p = new FilePermission("-", "read,execute"); FilePermission p = new FilePermission("<<ALL FILES>>", "read"); The FilePermission p = new FilePermission("c:\\temp\\foo", "read"); The double backslashes are necessary to represent a single backslash because the strings are processed by a tokenizer (java.io.StreamTokenizer), which allows "\" to be used as an escape string (e.g., "\n" to indicate a new line) and which thus requires two backslashes to indicate a single backslash. After the tokenizer has processed the above FilePermission target string, converting double backslashes to single backslashes, the end result is the actual path "c:\temp\foo" It is necessary that the strings be given in platform-dependent format until there is a universal file description language. Note also that the use of meta symbols such as "*" and "-" prevents the use of specific file names. We think this is a small limitation that can be tolerated for the moment. Finally, note that "/-" and "<<ALL FILES>>" are the same target on Unix systems in that they both refer to the entire file system. (They can refer to multiple file systems if they are all available). The two targets are potentially different on other operating systems, such as MS Windows and MacOS. FilePermission p = new FilePermission("/home/gong/", "read"); means you are only giving permission to list the files in that directory, not read any of them. To allow read access to files, you must specify either an explicit file name, or an "*" or "-", as in FilePermission p = new FilePermission("/home/gong/myfile", "read"); FilePermission p = new FilePermission("/home/gong/*", "read"); FilePermission p = new FilePermission("/home/gong/-", "read"); And finally, note that code always automatically has permission to read files from its same (URL) location, and subdirectories of that location; it does not need explicit permission to do so. 3.1.6 java.net.SocketPermissionThis class represents access to a network via sockets. The target for this class can be given as "hostname:port_range", where hostname can be given in the following ways: hostname (a single host) IP address (a single host) localhost (the local machine) "" (equivalent to "localhost") hostname.domain (a single host within the domain) hostname.subdomain.domain *.domain (all hosts in the domain) *.subdomain.domain * (all hosts) That is, the host is expressed as a DNS name, as a numerical IP address, as "localhost" (for the local machine) or as "" (which is equivalent to specifying "localhost"). N (a single port) N- (all ports numbered N and above) -N (all ports numbered N and below) N1-N2 (all ports between N1 and N2, inclusive) Here N, N1, and N2 are non-negative integers ranging from 0 to 65535 (2^16-1). import java.net.SocketPermission; SocketPermission p = new SocketPermission("java.sun.com","accept"); p = new SocketPermission("204.160.241.99","accept"); p = new SocketPermission("*.com","connect"); p = new SocketPermission("*.sun.com:80","accept"); p = new SocketPermission("*.sun.com:-1023","accept"); p = new SocketPermission("*.sun.com:1024-","connect"); p = new SocketPermission("java.sun.com:8000-9000", "connect,accept"); p = new SocketPermission("localhost:1024-", "accept,connect,listen"); Note that SocketPermission("java.sun.com:80,8080","accept") and SocketPermission("java.sun.com,javasun.sun.com","accept") are not valid socket permissions. 3.1.7 java.security.BasicPermissionThe BasicPermission class extends the Permission class. It can be used as the base class for permissions that want to follow the same naming convention as BasicPermission (see below). 3.1.8 java.util.PropertyPermissionThe targets for this class are basically the names of Java properties as set in various property files. Examples are the "java.home" and "os.name" properties. Targets can be specified as "*" (any property), "a.*" (any property whose name has a prefix "a."), "a.b.*", and so on. Note that the wildcard can occur only once and can only be at the rightmost position. 3.1.9 java.lang.RuntimePermissionThe target for a RuntimePermission can be represented by any string, and there is no action associated with the targets. For example, RuntimePermission("exitVM") denotes the permission to exit the Java Virtual Machine. createClassLoader getClassLoader setContextClassLoader setSecurityManager createSecurityManager exitVM setFactory setIO modifyThread stopThread modifyThreadGroup getProtectionDomain readFileDescriptor writeFileDescriptor loadLibrary.{library name} accessClassInPackage.{package name} defineClassInPackage.{package name} accessDeclaredMembers.{class name} queuePrintJob 3.1.10 java.awt.AWTPermissionThis is in the same spirit as the RuntimePermission; it's a permission without actions. The targets for this class are: accessClipboard accessEventQueue listenToAllAWTEvents showWindowWithoutWarningBanner 3.1.11 java.net.NetPermissionThis class contains the following targets and no actions: requestPasswordAuthentication setDefaultAuthenticator specifyStreamHandler 3.1.12 java.lang.reflect.ReflectPermissionThis is the Permission class for reflective operations. A ReflectPermission is a named permission (like RuntimePermission) and has no actions. The only name currently defined is suppressAccessChecks which allows suppressing the standard Java programming language access checks -- for public, default (package) access, protected, and private members -- performed by reflected objects at their point of use. 3.1.13 java.io.SerializablePermissionThis class contains the following targets and no actions: enableSubclassImplementation enableSubstitution 3.1.14 java.security.SecurityPermissionSecurityPermissions control access to security-related objects, such as Security, Policy, Provider, Signer, and Identity objects. This class contains the following targets and no actions: getPolicy setPolicy getProperty.{key} setProperty.{key} insertProvider.{provider name} removeProvider.{provider name} setSystemScope setIdentityPublicKey setIdentityInfo printIdentity addIdentityCertificate removeIdentityCertificate clearProviderProperties.{provider name} putProviderProperty.{provider name} removeProviderProperty.{provider name} getSignerPrivateKey setSignerKeyPair 3.1.15 java.security.AllPermissionThis permission implies all permissions. It is introduced to simplify the work of system administrators who might need to perform multiple tasks that require all (or numerous) permissions. It would be inconvenient to require the security policy to iterate through all permissions. Note that AllPermission also implies new permissions that are defined in the future. 3.1.16 Discussion of Permission ImplicationsRecall that permissions are often compared against each other, and to facilitate such comparisons, we require that each permission class defines an 3.1.17 How To Create New Types of PermissionsIt is essential that no one except Sun Microsystems should extend the permissions that are built into the Java 2 SDK, either by adding new functionality or by introducing additional target keywords into a class such as java.lang.RuntimePermission. This maintains consistency. public class com.abc.Permission extends java.security.Permission public class com.abc.TVPermission extends com.abc.Permission The following figure shows the subclass relationship. grant codeBase "http://java.sun.com/" { permission com.abc.TVPermission "channel-5", "watch"; } In the application's resource management code, when checking to see if a permission should be granted, call AccessController's com.abc.TVPermission tvperm = new com.abc.TVPermission("channel-5", "watch"); AccessController.checkPermission(tvperm); Note that, when adding a new permission, one should create a new (permission) class and not add a new method to the security manager. (In the past, in order to enable checking of a new type of access, you had to add a new method to the SecurityManager class.) 3.2 java.security.CodeSourceThis class extends the concept of a codebase within HTML to encapsulate not only the code location (URL) but also the certificate(s) containing public keys that should be used to verify signed code originating from that location. Note that this is not the equivalent of the CodeBase tag in HTML files. Each certificate is represented as a java.security.cert.Certificate, and each URL as a java.net.URL. 3.3 java.security.PolicyThe system security policy for a Java application environment, specifying which permissions are available for code from various sources, is represented by a Policy object. More specifically, it is represented by a Policy subclass providing an implementation of the abstract methods in the Policy class. 3.3.1 Policy File FormatIn the default Policy implementation, the policy can be specified within one or more policy configuration files. The configuration files indicate what permissions are allowed for code from specified code sources. keystore "some_keystore_url", "keystore_type"; Here, "some_keystore_url" specifies the URL location of the keystore, and "keystore_type" specifies the keystore type. The latter is optional. If not specified, the type is assumed to be that specified by the "keystore.type" property in the security properties file. policy.url.1=http://foo.bar.com/blah/some.policy and that policy file has an entry: keystore ".keystore"; then the keystore will be loaded from: http://foo.bar.com/blah/.keystore The URL can also be absolute. grant [SignedBy "signer_names"] [, CodeBase "URL"] { permission permission_class_name [ "target_name" ] [, "action"] [, SignedBy "signer_names"]; permission ... }; White spaces are allowed immediately before or after any comma. The name of the permission class must be a fully qualified class name, such as java.io.FilePermission, and cannot be abbreviated (for example, to FilePermission). PolicyFile -> PolicyEntry | PolicyEntry; PolicyFile PolicyEntry -> grant {PermissionEntry}; | grant SignerEntry {PermissionEntry} | grant CodebaseEntry {PermissionEntry} | grant SignerEntry, CodebaseEntry {PermissionEntry} | grant CodebaseEntry, SignerEntry {PermissionEntry} | keystore "url" SignerEntry -> signedby (a comma-separated list of strings) CodebaseEntry -> codebase (a string representation of a URL) PermissionEntry -> OnePermission | OnePermission PermissionEntry OnePermission -> permission permission_class_name [ "target_name" ] [, "action_list"] [, SignerEntry]; Now we give some examples. The following policy grants permission a.b.Foo to code signed by Roland: grant signedBy "Roland" { permission a.b.Foo; }; The following grants a FilePermission to all code (regardless of the signer and/or codeBase): grant { permission java.io.FilePermission ".tmp", "read"; }; The following grants two permissions to code that is signed by both Li and Roland: grant signedBy "Roland,Li" { permission java.io.FilePermission "/tmp/*", "read"; permission java.util.PropertyPermission "user.*"; }; The following grants two permissions to code that is signed by Li and that comes from http://java.sun.com: grant codeBase "http://java.sun.com/*", signedBy "Li" { permission java.io.FilePermission "/tmp/*", "read"; permission java.io.SocketPermission "*", "connect"; }; The following grants two permissions to code that is signed by both Li and Roland, and only if the bytecodes implementing com.abc.TVPermission are genuinely signed by Li. grant signedBy "Roland,Li" { permission java.io.FilePermission "/tmp/*", "read"; permission com.abc.TVPermission "channel-5", "watch", signedBy "Li"; }; The reason for including the second signer field is to prevent spoofing when a permission class does not reside with the Java runtime installation. For example, a copy of the com.abc.TVPermission class can be downloaded as part of a remote JAR archive, and the user policy might include an entry that refers to it. Because the archive is not long-lived, the second time the com.abc.TVPermission class is downloaded, posssibly from a different web site, it is crucial that the second copy is authentic, as the presence of the permission entry in the user policy might reflect the user's confidence or belief in the first copy of the class bytecode. grant signedBy "Roland" { permission java.io.FilePermission "C:\\users\\Cathy\\*", "read"; }; This is because the strings are processed by a tokenizer (java.io.StreamTokenizer), which allows "\" to be used as an escape string (e.g., "\n" to indicate a new line) and which thus requires two backslashes to indicate a single backslash. After the tokenizer has processed the above FilePermission target string, converting double backslashes to single backslashes, the end result is the actual path "C:\users\Cathy\*" 3.3.2 Property Expansion in Policy FilesProperty expansion is possible in policy files and in the security properties file. permission java.io.FilePermission "${user.home}", "read"; will expand "${user.home}" to use the value of the "user.home" system property. If that property's value is "/home/cathy", then the above is equivalent to permission java.io.FilePermission "/home/cathy", "read"; In order to assist in platform-independent policy files, you can also use the special notation of "${/}", which is a shortcut for "${file.separator}". This allows permission designations such as permission java.io.FilePermission "${user.home}${/}*", "read"; If user.home is /home/cathy, and you are on Solaris, the above gets converted to: permission java.io.FilePermission "/home/cathy/*", "read"; If on the other hand user.home is C:\users\cathy and you are on a Windows system, the above gets converted to: permission java.io.FilePermission "C:\users\cathy\*", "read"; Also, as a special case, if you expand a property in a codebase, such as grant codeBase "file:/${java.home}/lib/ext/" then any file.separator characters will be automatically converted to /'s, which is desirable since codebases are URLs. Thus on a Windows system, even if java.home is set to C:\j2sdk1.2, the above would get converted to grant codeBase "file:/C:/j2sdk1.2/lib/ext/" Thus you don't need to use ${/} in codebase strings (and you shouldn't). "${user.${foo}}" doesn't work, even if the "foo" property is set to "home". The reason is the property parser doesn't recognize nested properties; it simply looks for the first "${", and then keeps looking until it finds the first "}" and tries to interpret the result "${user.$foo}" as a property, but fails if there is no such property. grant codeBase "${foo}" { permission ...; permission ...; }; then all the permissions in this grant entry are ignored. If you have grant { permission Foo "${foo}"; permission Bar; }; then only the "permission Foo..." entry is ignored. And finally, if you have keystore "${foo}"; then the keystore entry is ignored. "C:\\users\\cathy\\foo.bat" This is because the strings are processed by a tokenizer (java.io.StreamTokenizer), which allows "\" to be used as an escape string (e.g., "\n" to indicate a new line) and which thus requires two backslashes to indicate a single backslash. After the tokenizer has processed the above string, converting double backslashes to single backslashes, the end result is "C:\users\cathy\foo.bat" Expansion of a property in a string takes place after the tokenizer has processed the string. Thus if you have the string "${user.home}\\foo.bat" then first the tokenizer processes the string, converting the double backslashes to a single backslash, and the result is "${user.home}\foo.bat" Then the ${user.home} property is expanded and the end result is "C:\users\cathy\foo.bat" assuming the user.home value is "C:\users\cathy". Of course, for platform independence, it would be better if the string was initially specified without any explicit slashes, i.e., using the ${/} property instead, as in "${user.home}${/}foo.bat" 3.3.3 Assigning PermissionsWhen loading a new class that originated from a particular CodeSource, the security mechanism consults the policy object to determine what permissions to grant. This is done by invoking the 1. match the public keys, if code is signed. 2. if a key is not recognized in the policy, ignore the key if every key is ignored, treat the code as unsigned. 3. if the keys are matched, or no signer was specified { try to match all URLs in the policy for the keys } 4. if either key or URL is not matched, use built-in default permission, which is the original sandbox permission. The exact meaning of a policy entry codeBase URL value depends on the characters at the end. A codeBase with a trailing "/" matches all class files (not JAR files) in the specified directory. A codeBase with a trailing "/*" matches all files (both class and JAR files) contained in that directory. A codeBase with a trailing "/-" matches all files (both class and JAR files) in the directory and recursively all files in subdirectories contained in that directory. "file:/home/cathy/temp/*" To specify files in the "temp" directory on the C drive in a Windows system, use "file:/c:/temp/*" Note: code base URLs always use slashes (no backlashes), regardless of the platform they apply to. "/home/gong/bin/MyWonderfulJava" 3.3.4 Default System and User Policy FilesIn the default Policy implementation, the policy can be specified within one or more policy configuration files. The configuration files specify what permissions are allowed for code from specified code sources. {java.home}/lib/security/java.policy (Solaris) {java.home}\lib\security\java.policy (Windows) Here, java.home is a system property specifying the directory into which the Java 2 SDK was installed. {user.home}/.java.policy (Solaris) {user.home}\.java.policy (Windows) Here, user.home is a system property specifying the user's home directory. {java.home}/lib/security/java.security (Solaris) {java.home}\lib/security\java.security (Windows) The policy file locations are specified as the values of properties whose names are of the form policy.url.n Here, n is a number. You specify each such property value in a line of the following form: policy.url.n=URL Here, URL is a URL specification. For example, the default system and user policy files are defined in the security properties file as policy.url.1=file:${java.home}/lib/security/java.policy policy.url.2=file:${user.home}/.java.policy You can actually specify a number of URLs, including ones of the form "http://", and all the designated policy files will get loaded. You can also comment out or change the second one to disable reading the default user policy file. java -Djava.security.manager -Djava.security.policy=pURL SomeApp Here, pURL is a URL specifying the location of a policy file, then the specified policy file will be loaded in addition to all the policy files that are specified in the security properties file. (The "-Djava.security.manager" argument ensures that the default security manager is installed, and thus the application is subject to policy checks, as described in "Security Management for Applets and Applications". It is not required if the application SomeApp installs a security manager.) java -Djava.security.manager -Djava.security.policy==pURL SomeApp If you want to pass a policy file to the appletviewer, again use a "-Djava.security.policy" argument as follows: appletviewer -J-Djava.security.policy=pURL myApplet Please note: The "-Djava.security.policy" policy file value will be ignored (for both java and appletviewer commands) if the "policy.allowSystemProperty" property in the security properties file is set to false. The default is true. 3.3.5 Customizing Policy EvaluationThe current design of the Policy class is not as comprehensive as it could be. We have given the issues much thought and are progressing cautiously, partly to ensure that we define method calls that are appropriate for the most common cases. For the meantime, an alternative policy class can be given to replace the default policy class, as long as the former is a subclass of the abstract Policy class and implements the {java.home}/lib/security/java.security (Solaris) {java.home}\lib\security\java.security (Windows) Here, {java.home} refers to the directory where the runtime environment is installed -- either the jre directory inside the Java 2 SDK, or the top-level directory of the Java 2 Runtime Environment. policy.provider=sun.security.provider.PolicyFile To customize, you can change the property value to specify another class, as in policy.provider=com.mycom.MyPolicy Note that the MyPolicy class must be a subclass of java.security.Policy. It is perhaps worth emphasizing that such an override of the policy class is a temporary solution and a more comprehensive policy API will probably make this unnecessary. 3.4 java.security.GeneralSecurityExceptionThis is a new exception class that is a subclass of java.lang.Exception. The intention is that there should be two types of exceptions associated with security and the security packages. Such an exception is thrown only when some sort of security violation is detected. For example, such an exception is thrown when some code attempts to access a file, but it does not have permission for the access. Application developers may catch these exceptions, if they want. Such an exception is security related but non-vital. For example, passing in an invalid key is probably not a security violation and should be caught and dealt with by a developer. CONTENTS | PREV | NEXT Copyright © 1997-1999 Sun Microsystems, Inc. All Rights Reserved. |