Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Security, Policy Files in JDK 1.2

Java Programming, Lecture Notes # 715, Revised 5/16/99.


Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the spring semester of 1999.

This lesson was originally written on April 10, 1999 and has been updated several times since.

The purpose of this lesson is to provide an introduction to the use of security policy files under JDK 1.2.

Disclaimer

I claim absolutely no expertise in the area of security. I am simply a college professor attempting to gather information about Java on one hand and present it to my students on the other. I disclaim any responsibility for any security problems that may occur as a result of anyone using any of the material in any of my tutorial lessons.

You are responsible for your own actions. With regard to security, you should study not only the material that I will present, but also material provided by others who possess expertise in the security area. Hopefully my material will be useful in getting you started in that direction.

Two good books on security published by O'Reilly & Associates are:

I highly recommend both of these books.

Discussion

The pain of progress

When migrating from JDK 1.1 to JDK 1.2, you must contend with the fact that JDK 1.2 incorporates significant changes in the overall security model. Some programs that run fine under JDK 1.1 throw security exceptions and won't run under JDK 1.2.

This lesson provides a brief introduction to the use of security policy files. You are referred to the documentation available for JDK 1.2 for a more complete discussion.

This lesson is also designed to get you over the initial hump and show you how to create security policy files to get your JDK 1.1 programs back up and running under JDK 1.2.

Policy-based, easily-configurable, fine-grained access control

Sun refers to the new security capability introduced in JDK 1.2 as "Policy-based, easily-configurable, fine-grained access control." When code is loaded, it is assigned "permissions" based on the security policy currently in effect.

Each individual permission specifies a permitted access to a particular resource. Typical permissions are:

Basis for permissions

Permissions can be based on the source of the code, the signer of the code, or both. The policy that specifies which permissions are available for code from various signers/locations can be initialized from an external configurable policy file. This enables the JVM to offer fine-grain, configurable, flexible, and extensible access control. Such control can be specified for all Java code, including applets, applications, beans, and servlets.

What is a permission?

A permission represents access to a system resource. In order for access to a resource to be allowed for an applet (or for an application running with a security manager), the corresponding permission must be explicitly granted to the code attempting the access.

When are permissions required?

If the application is running without a security manager, there is no requirement to establish permissions for that application. By default, the application has full access to all resources. Therefore, when migrating from JDK 1.1 to JDK 1.2, you are most likely to encounter security problems when running JDK 1.1 applications that use a security manager. This includes all RMI applications.

How are permissions granted?

Permissions are granted by creating (and invoking) policy configuration files. Policy configuration files are text files that can be created using a text editor, or by using the graphical policytool program that is part of the JDK download. By using policytool, you can avoid the requirement to know the syntax of the policy configuration files or the class names of the permission classes. (See the JDK 1.2 documentation for instructions on how to use policytool.) However, policytool provides no help in knowing which permissions to grant for a particular situation, and how to grant them. You must get that information from the JDK 1.2 documentation.

How can you invoke a policy file?

Certain default policy files are invoked automatically. Additional policy files can be invoked at runtime by starting the JVM using a statement such as the following:

java -Djava.security.policy=Rmi02Client.policy Rmi02Client

This statement causes the Rmi02Client application to be executed after setting a system property causing the file named Rmi02Client.policy to establish the security policy.

What is a Policy object?

A Policy object represents the policy for a Java application environment. The policy can be specified within one or more policy configuration files in the default Policy implementation. The policy file(s) specify the permissions that are granted to code from specified sources.

What are target names and actions?

A permission typically has a "target name" and, in some cases, a comma-separated list of one or more actions. For example, when included in a policy file, the following text grants permission for code that originates in the directory specified by the URL following the word codeBase to write a file named junk.txt. The target is junk.txt and the action is write.

grant 
codeBase 
  "file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/"{
permission java.io.FilePermission "junk.txt", "write";
};

Where can I learn more about permission types and associated risks?

The JDK 1.2 documentation contains tables that describe the built-in JDK 1.2 permission types and discuss the risks of granting each of the available permissions. It also contains tables showing the methods that require permissions to be in effect for successful execution of the method. The required permissions are shown for each such method.

The policy for a Java application environment (specifying which permissions are available for code from various sources) is represented by a Policy subclass providing an implementation of the abstract methods in the Policy class (which is in the java.security package).

Where are the policy configuration files?

The source location for the policy information depends on the Policy implementation. The default Policy implementation obtains its information from static policy configuration files.

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

By default, there is a single system-wide policy file, and a single (optional) user policy file. You can create additional policy configuration files and invoke them when you start the JVM.

Where is the system-wide policy configuration file located?

By default, the system-wide policy configuration file is located at:

In this representation, java.home refers to the value of the system property named "java.home", which specifies the directory into which the JDK was installed.

What is the purpose of the system-wide policy configuration file?

The system-wide policy file is intended to grant system-wide code permissions. The default java.policy file that is installed when you install the JDK

Where is the user policy configuration file located?

By default, the user policy file is located at

Note: user.home refers to the value of the system property named "user.home", which specifies the user's home directory.

On Windows systems the "user.home" property value defaults to

Loading Policy Files

The system policy is loaded first at initialization. Then the user policy is added to it. If neither policy is present, a built-in policy is used. According to the documentation, this built-in policy is the same as the original sandbox policy.

What and where is the security properties file?

The locations of the policy configuration files are also configurable. Policy file locations are specified in the security properties file, which is located at

If you need to modify the locations of the policy configuration files, see the JDK 1.2 documentation for more information on how to modify the security properties file.

Using Alternative Policy Files

As mentioned earlier, it is also possible to specify an additional or a different policy file when starting the JVM to execute an application. This is illustrated in the sample program presented later in this lesson.

To specify an alternative policy file when you start the JVM, use the following command line argument, which sets the value of the java.security.policy property.

"-Djava.security.policy"

For example, if myURL is a URL specifying the location of a policy file, and myApp is the name of an application, then

java -Djava.security.manager -Djava.security.policy=myURL myApp

will cause the specified policy file to be loaded in addition to all the policy files that are specified in the security properties file.

Note that "-Djava.security.manager" was specified in addition to the file containing the new security policy.

Why include -Djava.security.manager?

Inclusion of the "-Djava.security.manager" argument ensures that the default security manager is installed. This causes the application to be subject to policy checks. This argument is not required if the application installs a security manager.

Any limitations on the URL?

The URL can be any regular URL or simply the name of a policy file in the current directory, as shown below:

java -Djava.security.policy=Security03.policy Security03

This particular application installs its own security manager. Thus, there was no requirement to include the "-Djava.security.manager" argument

Using only one specific policy configuration file

The following format, which uses a double equal

java -Djava.security.manager -Djava.security.policy==myURL myApp

instructs that just the specified policy file will be used. All of the policy files specified in the security properties file will be ignored.

Using Alternative Policy Files with appletviewer

It is also possible to pass policy files to appletviewer using syntax such as the following. See the JDK 1.2 documentation for more information.

appletviewer -J-Djava.security.policy=myURL myApplet

Disabling Alternative Policy Files

It is also possible to disable the ability to specify an alternate security policy by setting the policy.allowSystemProperty property to false in the security properties file. The default is true.

Other aspects of security are configurable as well.

Once again, what are the policy configuration files used for?

The policy configuration file(s) for a JDK installation specify what permissions are allowed by code from specified code sources.

An applet, or an application running under a security manager, must be granted permission to perform secured actions (such as reading or writing a file) under JDK 1.2.

Exceptions to the rule

One exception is 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.

What is a grant entry?

Other than this exception, by default, a permission must be granted by a grant entry in a policy configuration file. The overall format of a policy configuration file is a list of entries.

What is a keystore entry?

There may be zero or one keystore entry and zero or more grant entries. (The concept of a keystore will be addressed in a separate lesson and won't be discussed further here.)

Code being executed is considered to come from a particular "code source." An object of type CodeSource represents the code-source).

What is the source of the code?

The code source includes

(Certificates, public keys, and private keys will be discussed in a separate lesson.)

Format of grant Entries

Each grant entry includes one or more "permission entries".

The permission entries are preceded by optional codeBase and signedBy name/value pairs. These name/value pairs specify the code to which you want to grant the permissions.

In case you need to know it, the basic format of a grant entry is as follows. (The use of the policytool program eliminates the requirement for you to be concerned about such formats.)

  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";
  };

The signedBy value

A signedBy value indicates the alias for a certificate stored in the keystore. As mentioned earlier, I will have more to say about certificates and keystore in a separate lesson. The signedBy value can be a comma-separated list of multiple aliases where the comma indicates an AND relationship.

To use the exact wording from the Sun documentation, a statement like "Code signed by Adam" means

"Code in a class file contained in a JAR file, where the JAR file was signed using the private key corresponding to the public key that appears in a keystore certificate in an entry aliased by Adam."

The signedBy field is optional. If it is omitted, it doesn't matter whether the code is signed or not or by whom.

The codeBase value

A codeBase value indicates the code source location. This field is also optional. By specifying a codeBase, you grant the specified permission(s) to code from that location. An empty codeBase entry signifies "any code." It doesn't matter where the code originates.

A codeBase value is a URL and must always use forward slashes (never backslashes) as the directory separator, even when the code source is actually on a Windows system. This is a requirement for you to know about even when using the policytool program to create your policy configuration files.

See the sample program later in this lesson for a URL representing a directory on the file system for a Windows 95 system.

The codeBase options

There are several optional formulations of codeBase. The exact meaning of a codeBase value depends on the characters at the end.

Permission Entries

A permission entry must begin with the word permission. A portion of the template presented above is repeated here for convenience.

permission permission_class_name "target_name", "action",
      signedBy "signer_names";

The permission_class_name is a specific permission type, such as java.io.FilePermission or java.lang.RuntimePermission. (Use of the policytool program eliminates the need for you to know the names of the permission classes.)

A permission type can require a target. For example, the "target_name" for java.io.FilePermission is the path/file name that specifies a particular directory or file.

Many, but not all, permission types require an "action" parameter. For example, java.io.FilePermission requires an action parameter to specify read, write, etc. (Use of the policytool program eliminates the need for you to know which permission types need action types. When it is not needed, the action field is "grayed out" in the dialog.)

The signedBy name/value pair for a permission entry is optional. It indicates that the permission class itself must be signed by the given alias(es) in order for the permission to be granted. For more details on this, see the Sun documentation.

Items in a Permission Entry

The order of the items in a permission entry must be as follows:

Tidbits

An entry is terminated with a semicolon.

Case is not important 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.

When you specify 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 must include two backslashes for each actual single backslash in the path,

Sample Program

Name: Security03.java

This application and the two related files listed below are designed to illustrate the use of policy configuration files in JDK 1.2.

What does the program do?

This application illustrates writing and then reading a file where the application creates a security manager that doesn't allow writing and reading files.

Because the security manager doesn't allow writing and reading files, the application cannot be executed under JDK 1.1. It also cannot be executed under JDK 1.2 without invoking a policy configuration file that overrides the security manager set by the application.

Granting file write/read permission

Under JDK 1.2, a policy configuration file is created to grant the application permission to write and then read the file. In order to use the policy file to grant the permissions, it must be invoked when the application is started.

To make things simple and avoid typing errors, the following statement is encapsulated in a batch file to start the application and invoke the policy file named Security03.policy:

java -Djava.security.policy=Security03.policy Security03

The output from the program is:

Start the program and write a file
Read, and print the file
Dick
End of program

 

Interesting Code Fragments

The following sections contain interesting code fragments from the three files. Complete listings of all three files are provided near the end of the lesson.

Program File

Defining a security manager class

The first fragment defines a security manager class for the application. Note that this class definition is completely empty.

Since this class doesn't override any of the methods of the SecurityManager class, an application that uses an object of this class as a security manger has almost no permission to access system resources.

class DummySecurityManager extends SecurityManager
{
}

Setting the security manager for the application

The next fragment shows

Setting the security manager in this fashion effectively eliminates most permissions for access of resources by the application including permission to write and read files. However, the invocation of the policy configuration file shown later overrides the security manager set by the application and gives the application permission to write and then read a specific file on the local file system.

class Security03{
  public static void main(String[] args){
    System.setSecurityManager(new DummySecurityManager());

Writing and reading the file

The next fragment writes and then reads a file named junk.txt. By now you should have no difficulty understanding this code. I have included it here simply for completeness, but won't discuss it further.

    System.out.println(
                    "Start the program and write a file");
    try{
      FileOutputStream outFile = 
                          new FileOutputStream("junk.txt");
  
      //Write four bytes to the file and close it
      outFile.write('D');
      outFile.write('i');
      outFile.write('c');
      outFile.write('k');
      outFile.close();
    }catch(IOException e){System.out.println(e);}

    System.out.println("Read, and print the file");
  
    try{
      FileInputStream inFile = 
                           new FileInputStream("junk.txt");
      int data;
  
      //Read and print until eof indicated by -1.
      while( (data = inFile.read()) != -1)
        System.out.print((char)data);
      inFile.close();
    }catch(IOException e){System.out.println(e);}
    System.out.println("\nEnd of program");
  }// end main
}//end class Security03

 

Policy File

The key to this lesson, and the key to making it possible for the above application to write and then read a file named junk.txt is the policy configuration file shown below.

/* File Security03.policy, rev 4/10/99, R.G.Baldwin*/

grant codeBase 
"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/" {
  permission java.io.FilePermission "junk.txt", "write";
};

grant codeBase 
"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/" {
  permission java.io.FilePermission "junk.txt", "read";
};

Granting very specific permission

When invoked to set security policy, the first entry in this file grants code originating at the URL permission to write a file named junk.txt on the local file system. This is true even though the security manager implemented by the application does not grant that privilege.

"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/"

The second entry grants code originating at the same URL permission to read the same file.

Batch File

The batch file that I used to start the program causes the policy configuration file named Security03.policy to be used to set security policy for the execution of the application. This, in turn, grants the write and read privileges discussed above.

java -Djava.security.policy=Security03.policy Security03

 

Program Listing

This section contains listing of all three files.

/* File Security03.java Copyright 1999, R.G.Baldwin
This application and two related files named 

Security03.bat
Security03.policy

are designed to illustrate the use of security policy files
in JDK 1.2.

This application illustrates writing and then reading a 
file one byte at a time where the application creates a
security manager to control itself.  The security manager
does not allow the writing and subsequent reading of disk
files.  Therefore, the application cannot be executed under
JDK 1.1.

Under JDK 1.2, a security policy file can be created
locally to grant the application permission to write and
then read the file.  In order to use the policy file to
grant the permissions, it must be invoked when the 
application is started.  The following statement is
encapsulated in a batch file to start the application and
invoke the policy file named Security03.policy:
  
java -Djava.security.policy=Security03.policy Security03

The contents of the policy file are shown below:

grant codeBase 
"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/" {
  permission java.io.FilePermission "junk.txt", "write";
};

grant codeBase 
"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/" {
  permission java.io.FilePermission "junk.txt", "read";
};

These two segments of text in the policy file make it
possible for class files loaded from the following URL

  file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/

to write and read a file named

  junk.txt

on the local file system.


The output from the program is:

Start the program and write a file
Read, and print the file
Dick
End of program
**********************************************************/

import java.io.*;

//Define a dummy security manager class.
class DummySecurityManager extends SecurityManager{}
//=======================================================//

class Security03{
  public static void main(String[] args){
    //Create a dummy security manager.
    System.setSecurityManager(new DummySecurityManager());
    
    System.out.println(
                    "Start the program and write a file");
    try{
      FileOutputStream outFile = 
                          new FileOutputStream("junk.txt");
  
      //Write four bytes to the file and close it
      outFile.write('D');
      outFile.write('i');
      outFile.write('c');
      outFile.write('k');
      outFile.close();
    }catch(IOException e){System.out.println(e);}

    System.out.println("Read, and print the file");
  
    try{
      FileInputStream inFile = 
                           new FileInputStream("junk.txt");
      int data;
  
      //Read and print until eof indicated by -1.
      while( (data = inFile.read()) != -1)
        System.out.print((char)data);
      inFile.close();
    }catch(IOException e){System.out.println(e);}
    System.out.println("\nEnd of program");
  }// end main
}//end class Security03
/* File Rmi02Server.policy, rev 4/10/99, R.G.Baldwin*/

grant codeBase 
"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/" {
  permission java.io.FilePermission "junk.txt", "write";
};

grant codeBase 
"file:/G:/Baldwin/AA-School/JavaProg/Combined/Java/" {
  permission java.io.FilePermission "junk.txt", "read";
};
rem File Secuity03.bat Rev 4/10/99 RGB

java -Djava.security.policy=Security03.policy Security03

-end-