Default Policy Implementation and Policy File Syntax

Last Modified: 8 June, 1998

The policy for a Java runtime (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 (which is in the java.security package).

The source location for the policy information utilized by the Policy object is up to the Policy implementation. There is a default Policy implementation that obtains its information from static policy configuration files. The rest of this document pertains to the default Policy implementation and the syntax that must be used in policy files it reads.

Here is an outline:

Default Policy Implementation
Default Policy File Locations
Changing the Policy Implementation
Policy File Syntax
Policy File Examples
Property Expansion in Policy Files
Related Documentation

Default Policy Implementation

In the default Policy implementation, the policy can be specified within one or more policy configuration files. The configuration file(s) specify what permissions are allowed for code from specified code sources.

A policy file can be composed via a simple text editor, or via a graphical policytool utility. (See policytool for Solaris or policytool for Windows.)

There is by default a single system-wide policy file, and a single user policy file.

The default Policy object is initialized the first time its getPermissions method is called, or whenever its refresh method is called. Initialization involves parsing the policy configuration file(s) (see Policy File Syntax), and then populating the Policy object.

Default Policy File Locations

As mentioned previously, there is by default a single system-wide policy file, and a single user policy file.

The system policy file is by default located at

    <java.home>/lib/security/java.policy

where <java.home> is a system property specifying the directory into which the JDK was installed.

The user policy file is by default located at

    <user.home>/.java.policy

where <user.home> is a system property specifying the user's home directory.

When the Policy is initialized, the system policy is loaded in first, and then the user policy is added to it. If neither policy is present, a built-in policy is used. This built-in policy is the same as the original sandbox policy.

Policy file locations are specified in the security properties file, which is located at

    <java.home>/lib/security/java.security
The policy file locations are specified as the values of properties whose names are of the form
    policy.url.n
where n is a number. For example, the default system and user policy files are defined in the security properties file as
    policy.url.1=${java.home}/lib/security/java.policy
    policy.url.2=${user.home}/.java.policy

(See Property Expansion for information about specifying property values via a special syntax, such as specifying the java.home property value via ${java.home}.)

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.

The algorithm starts at policy.url.1, and keeps incrementing until it does not find a URL. Thus if you have policy.url.1 and policy.url.3, policy.url.3 will never be read.

It is also possible to specify an additional or a different policy file when invoking execution of an application. This can be done via the "-Djava.security.policy" command line argument, which sets the value of the java.security.policy property. For example, if you use

    java -Djava.security.manager -Djava.security.policy=someURL SomeApp
where someURL 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. It is not required if the application SomeApp installs a security manager.) If you use
    java -Djava.security.manager -Djava.security.policy==someURL SomeApp
(note the double equals) then just the specified policy file will be used; all others will be ignored.

If you want to pass a policy file to the appletviewer, then use a "-J-Djava.security.policy" argument as follows:

    appletviewer -J-Djava.security.policy=someURL 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.

Changing the Policy Implementation

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 getPermissions method (and other methods as necessary).

The default Policy implementation can be changed by editing the security properties file, which is the java.security file in the lib/security directory of the JDK.

One of the types of properties you can set in java.security is of the following form:

    policy.provider=PolicyClassName

PolicyClassName must specify the fully qualified name of the desired Policy implementation class. The default security properties file entry for this property is the following:

    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

Policy File Syntax

The policy configuration file(s) for a JDK installation specify what permissions (which types of system resource accesses) are allowed by code from specified code sources.

In order for an applet (or an application running under a Security Manager) to be allowed to perform secured actions (such as reading or writing a file), the applet (or application) must be granted permission for that particular action. In the default Policy implementation, that permission must be granted by a grant entry in a policy configuration file. See below and the "Java Security Architecture Specification" for more information. (The only exception is that code always automatically has permission to read files from its same CodeSource and subdirectories of that CodeSource; it does not need explicit permission to do so.)

A policy configuration file essentially contains a list of entries. It may contain a "keystore" entry, and contains zero or more "grant" entries.

A keystore is a database of private keys and their associated digital certificates such as X.509 certificate chains authenticating the corresponding public keys. The keytool utility (for Solaris) (for Windows) is used to create and administer keystores. The keystore specified in a policy configuration file is used to look up the public keys of the signers specified in the grant entries of the file. A keystore entry must appear in a policy configuration file if any grant entries specify signer aliases (see below).

At this time, there can be only one keystore entry in the policy file (others after the first one are ignored), and it can appear anywhere outside the file's grant entries. It has the following syntax:

    keystore "some_keystore_url", "keystore_type";
where "some_keystore_url" specifies the URL location of the keystore, and "keystore_type" specifies the keystore type.

The URL is relative to the policy file location. Thus if the policy file is specified in the security properties file as:

    policy.url.1=http://foo.bar.com/fum/some.policy
and that policy file has an entry:
    keystore ".keystore";
then the keystore will be loaded from:
    http://foo.bar.com/fum/.keystore
The URL can also be absolute.

A keystore type defines the storage and data format of the keystore information, and the algorithms used to protect private keys in the keystore and the integrity of the keystore itself. The default type supported by Sun Microsystems is a proprietary keystore type named "JKS".

Code being executed is always considered to come from a particular "code source" (represented by an object of type CodeSource). The code source includes not only the location (URL) where the applet originated from, but also a reference to the certificate(s) containing the public key(s) corresponding to the private key(s) used to sign the code. Certificates in a code source are referenced by (symbolic) alias names from the user's keystore.

Each grant entry in a policy file essentially consists of a CodeSource and its permissions. (Actually, a CodeSource consists of a URL and a set of certificates, while a policy file grant entry includes a URL and a list of signer names. The system creates the corresponding CodeSource after consulting the keystore to determine the certificate(s) of the specified signers.)

Each grant entry includes a number of "permission entries". Each grant entry grants a specified code source a set of permissions, specifying which actions are allowed. The basic format of a grant entry is the following:

  grant signedBy "signer_names", codeBase "URL" {
    permission permission_class_name "target_name", "action", 
        signedBy "signer_names";
    ....
    permission permission_class_name "target_name", "action", 
        signedBy "signer_names";
  };
 	
All non-italicized items above must appear as is (although case doesn't matter and some are optional, as noted below). Italicized items represent variable values.

A grant entry must begin with the word grant.

The signedBy and codeBase name/value pairs are optional, and the order between these fields does not matter.

The signedBy value is a string alias that is mapped (using the keystore) to a set of public keys that are associated with the signers. These keys are used to verify that classes from the specified code source are really signed by these signers.

The signedBy value can be a comma-separated string containing names of multiple signers, an example of which is "Adam,Eve,Charles", which means "signed by Adam and Eve and Charles" (i.e., the relationship is AND, not OR).

The signedBy field is optional in that, if it is omitted, it signifies "any signer", or in other words, it doesn't matter whether the code is signed or not or by whom.

Similarly, if there is no codeBase entry, it signifies "any code"; it doesn't matter where the code originates from.

Note: a codeBase value is a URL and thus should always utilize slashes (never backslashes) as the directory separator, even when the code source is actually on a Windows system. Thus, if the source location for code on a Windows system is actually C:\somepath\app\, then the policy codeBase entry should look like:

    grant codeBase "file:/C:/somepath/api/" {
      ...
    }

A permission entry must begin with the word permission. The word permission_class_name in the template above would actually be a specific permission type, such as java.io.FilePermission or java.lang.RuntimePermission.

The "action" is required for many permission types, such as java.io.FilePermission (where it specifies what type of file access is permitted). It is not required for categories such as java.lang.RuntimePermission where it is not necessary - you either have the permission specified by the "target_name" value following the permission_class_name or you don't.

The signedBy name/value pair for a permission entry is optional. If present, it indicates a signed permission. That is, the permission class itself must be signed by the given alias(es) in order for the permission to be granted. For example, suppose you have the following grant entry:

  grant {
    permission Foo "foobar", signedBy "FooSoft";
  }

Then this permission of type Foo is granted if the Foo.class permission has been signed by the "FooSoft" alias, or if Foo.class is a system class, since system classes are not subject to policy restrictions.

Items that appear in a permission entry must appear in the specified order (permission, permission_class_name, "target_name", "action", and signedBy "signer_names"). An entry is terminated with a semicolon.

Case is unimportant for the identifiers (permission, signedBy, codeBase, etc.) but is significant for the permission_class_name or for any string that is passed in as a value.

Please note: When you are specifying a java.io.FilePermission, the "target_name" is a file path. On Windows systems, whenever you directly specify a file path in a string (but not in a codeBase URL), you need to include two backslashes for each actual single backslash in the path, as in

    grant {
        permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "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 file path string, converting double backslashes to single backslashes, the end result is
    "C:\users\cathy\foo.bat"

Policy File Examples

An example of two entries in a policy configuration file is

  // If the code is signed by "Duke", grant it read/write access to all 
  // files in /tmp:

  grant signedBy "Duke" {
    permission java.io.FilePermission "/tmp/*", "read,write";
  };

// Grant everyone the following permission: grant { permission java.util.PropertyPermission "java.vendor"; };

The contents of another sample policy configuration file appear below.

  grant signedBy "sysadmin", codeBase "file:/home/sysadmin/" {
    permission java.security.SecurityPermission "Security.insertProvider.*";
    permission java.security.SecurityPermission "Security.removeProvider.*";
    permission java.security.SecurityPermission "Security.setProperty.*";
  };
This specifies that only applet code that was loaded from a signed JAR file (whose signature can be verified using the public key referenced by the alias name "sysadmin" in the keystore) from beneath the "/home/sysadmin/" directory on the local file system can call methods in the Security class to add or remove providers or to set Security properties.

Either component of the code source (or both) may be missing. An example where codeBase is missing is:

  grant signedBy "sysadmin" {
    permission java.security.SecurityPermission "Security.insertProvider.*";
    permission java.security.SecurityPermission "Security.removeProvider.*";
};
If this policy is in effect, code that comes in a JAR File signed by "sysadmin" can add/remove providers - regardless of where the JAR File originated from.

An example without a signer is:

  grant codeBase "file:/home/sysadmin/" {
    permission java.security.SecurityPermission "Security.insertProvider.*";
    permission java.security.SecurityPermission "Security.removeProvider.*";
};
In this case, code that comes from anywhere beneath the "/home/sysadmin/" directory on the local filesystem can add/remove providers. The code does not need to be signed.

An example where neither codeBase nor signedBy is included is:

  grant {
    permission java.security.SecurityPermission "Security.insertProvider.*";
    permission java.security.SecurityPermission "Security.removeProvider.*";
};
Here, with both code source components missing, any code (regardless of where it originated from, or whether or not it is signed, or who signed it) can add/remove providers.

Property Expansion in Policy Files

Property expansion is possible in policy files and in the security properties file.

Property expansion is similar to expanding variables in a shell. That is, when a string like

    ${some.property}
appears in a policy file, or in the security properties file, it will be expanded to the value of the system property. For example,
    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 things like
    permission java.io.FilePermission "${user.home}${/}*", "read";
If the value of the user.home property is /home/cathy, and we are on Solaris, the above gets converted to:
    permission java.io.FilePermission "/home/cathy/*", "read";
If on the other hand the user.home value is C:\users\cathy and we 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. Thus on a Windows system, the above would get converted to
    grant codeBase "file:C:/jdk1.2/lib/ext/"
even if java.home is set to C:\jdk1.2. Thus you don't need to use ${/} in codebase strings (and you shouldn't).

Property expansion takes place anywhere a double quoted string is allowed in the policy file. This includes the "signer_names", "URL", "target_name", and "action" fields.

Whether or not property expansion is allowed is controlled by the value of the "policy.expandProperties" property in the security properties file. If the value of this property is true (the default), expansion is allowed.

Please note: You can't use nested properties; they will not work. For example,

    "${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 (in this case, "${user.$foo}") as a property, but fails if there is no such property.

Also note: If a property can't be expanded in a grant entry, permission entry, or keystore entry, that entry is ignored. For example, if the system property "foo" is not defined and you have:

    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.

One final note: On Windows systems, when you directly specify a file path in a string (but not in a codeBase URL), you need to include two backslashes for each actual single backslash in the path, as in

    grant {
        permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "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 file path 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"

Related Documentation


Copyright © 1997-98 Sun Microsystems, Inc. All Rights Reserved.

Please send comments to: java-security@java.sun.com. This is not a subscription list.
Sun
Java Software Division