Received: from SOUTH-STATION-ANNEX.MIT.EDU by po10.MIT.EDU (5.61/4.7) id AA17555; Thu, 28 Sep 00 07:27:03 EDT
Received: from hermes.javasoft.com by MIT.EDU with SMTP
	id AA26028; Thu, 28 Sep 00 07:25:20 EDT
Received: (from nobody@localhost)
	by hermes.java.sun.com (8.9.3+Sun/8.9.1) id LAA15017;
	Thu, 28 Sep 2000 11:27:54 GMT
Date: Thu, 28 Sep 2000 11:27:54 GMT
Message-Id: <200009281127.LAA15017@hermes.java.sun.com>
X-Authentication-Warning: hermes.java.sun.com: Processed from queue /bulkmail/data/ed_79/mqueue1
X-Mailing: 263
From: JDCTechTips@sun.com
Subject: JDC Tech Tips  September 26, 2000: Using SecurityManager;  Policies and the Policy File
To: JDCMember@sun.com
Reply-To: JDCTechTips@sun.com
Errors-To: bounced_mail@hermes.java.sun.com
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Mailer: Beyond Email 2.2


 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
September 26, 2000. This issue is about the class
java.lang.SecurityManager. This class is the backbone of 
context-based security in the Java(tm) platform. The 
SecurityManager class acts as a single point of control for 
potentially unsafe operations such as deleting a file; it 
decides whether the operations can proceed based on context.
This issue covers:
 
         * Using SecurityManager 
         * Policies and the Policy File
                
This tip was developed using Java(tm) 2 SDK, Standard Edition, 
v 1.3.

This issue of the JDC Tech Tips is written by Stuart Halloway,
a Java specialist at DevelopMentor (http://www.develop.com/java).

You can view this issue of the Tech Tips on the Web at
http://java.sun.com/jdc/TechTips/2000/tt0926.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
USING SECURITYMANAGER

The basic SecurityManager architecture is simple. Throughout the 
JDK, the Java security team had to:

o Identify operations in the code that might pose a security 
  risk. 
  
o Find places in the code where checks could be placed to guard 
  these operations (but do so with the smallest number of 
  bottlenecks). 
   
o Throw an exception if the caller is not allowed to proceed.

This is how the SecurityManager class is used in the JDK source. 
For example, writing to a file on a user's local hard drive is an 
operation that needs to be secured. All file writes must at some 
point involve a FileOutputStream constructor. So you should expect 
to find a security checkpoint there:

//from the JDK 1.3 source...
public FileOutputStream(String name, boolean append)
    throws FileNotFoundException
{
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkWrite(name);
    }
    //go on and actually construct the object
    
This is a representative example of the security checks you find 
throughout the JDK. Before the actual work of the constructor 
begins, there is a check with the System class to see if a 
security manager is installed. If there is one, the constructor 
calls an appropriate method on the security manager, passing in 
any additional information that might influence the outcome. In 
the case of writing to a file, the relevant method is 
checkWrite() and the extra information is the name of a file.  

Because the hooks are already in place throughout the JDK, you 
can customize security by writing your own subclass of 
SecurityManager. Here is a simple example that only permits 
writing to a file named "temp" in the current directory.

import java.io.*;

class TempfileSecurityManager extends SecurityManager {
    
    public void checkWrite(String name) {
        if (!("temp".equals(name))) {
            throw new SecurityException("Access to '" + name + "' denied");
        }
    }
}

public class TestSecurityManager {

    public static void writeFile(String name) throws IOException {
        System.out.println("Writing to file " + name);
        FileOutputStream fos = new FileOutputStream(name);
        //write something here...
        fos.close();
    }
    
    public static void main(String[] args) throws IOException {
        System.setSecurityManager(new TempfileSecurityManager());
        writeFile("temp");
        writeFile("other");
    }
}

The TestSecurityManager class installs a TempfileSecurityManager 
through the System.setSecurityManager method.  If you run 
TestSecurityManager, you should see that the writeFile method 
works fine when the file passed in is named "temp" but fails 
when "other" is passed in as the filename.

The TempfileSecurityManager is simple, but it has a major 
weakness. A particular capability is either granted to all the 
code running in the VM*, or not granted at all. Real systems 
need to assign different abilities to different pieces of code 
running in the same VM. For example, it would be nice to have 
a logging facility that could write to a logfile, but prevent 
any other code from writing to the local file system. The 
TempfileSecurityManager cannot handle this because it only looks 
at the filename being opened. A better implementation would also 
look at the context in which the file is opened.  

The SecurityManager base class provides the needed context 
information. The protected method getClassContext() returns an 
array of all the classes currently on the callstack. This enables 
a security manager to examine all the classes and decide if they 
should be trusted to perform the operation in question. For 
example, the following callstack array could be trusted:

Class java.io.FileOutputStream
Class com.develop.log.EventLog
etc.

But the following callstack array will probably not be trusted.

Class java.io.FileOutputStream
Class org.fierypit.EvilApplet
etc.

Of course, the perpetrators of evil will not normally indicate
their intent by naming a class "EvilApplet." So more work is 
necessary. For each class on the callstack, a security manager 
implementation could call getClassLoader to determine the 
class loader for the class. Given smart implementations of a 
class loader such as the JDK's java.net.URLClassLoader, it would 
then be possible to determine where on the web a class came from, 
and even check its digital signature.  

At this point implementing your own security manager is starting 
to sound like a lot of work. The checkWrite() method shown above 
is only one of several dozen methods that you might need to 
implement. Others cover operations such as accessing the network, 
accessing system properties, and invoking native code methods.  
For every one of these methods, a security manager needs to analyze 
the callstack returned by getClassContext. For each class on the 
stack, it might be necessary to collaborate with a class loader to 
determine the class's origin. Even worse, the code can be tricky 
to write and debug. In JDK 1.1, subclassing SecurityManager was 
the only way to do context-based security, and because it was so 
difficult, only a few people wrote security managers.  

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
POLICIES AND THE POLICY FILE

What JDK(tm) 1.1 needed was a security system that was declarative 
instead of procedural; in other words, a system where application 
developers and system administrators describe what security 
settings they want instead of how to implement them.  

JDK(tm) 1.2 and later provide declarative, policy-based security 
through a new class java.security.AccessController. 
AccessController and related classes build on the pre-existing 
SecurityManager. You can still write your own security manager, 
but if you choose to rely on the new, policy-based security, 
you do not have to write any code. Starting with JDK 1.2, 
SecurityManager is a concrete class that delegates to the 
AccessController to implement a fine-grained, context-based 
security policy. Sun Microsystems provides a reference 
implementation of this policy that is controlled by a text file 
called the policy file.  

To see a policy file in use, examine the following variation of
the TestSecurityManager class:

import java.io.*;

public class TestSecurityManager {

    public static void writeFile(String name) throws IOException {
        System.out.println("Writing to file " + name);
        FileOutputStream fos = new FileOutputStream(name);
        //write something here...
        fos.close();
    }
    
    public static void main(String[] args) throws IOException {
        writeFile("temp");
        writeFile("other");
    }
}

This version of the class is different in that is does not call 
System.setSecurityManager. So, the class should run without 
security checks and write to both the "temp" and "other" files. 
To enable 1.2 security, you can either use setSecurityManager 
to install an instance of the SecurityManager class, or specify 
the following property on the command line:

java -Djava.security.manager TestSecurityManager

By default, the permissions granted to your local code are minimal.
So you should see an AccessControlException when trying to access 
the"temp" file: 

java.security.AccessControlException: access denied 
        (java.io.FilePermission temp write)
        
In order to enable writing to the temp file, you need to specify a 
policy in a policy file, which might look like this: 

//file my.policy
grant {
    permission java.io.FilePermission "temp", "write";
};

You can instruct the virtual machine to use this policy file by
specifying the java.security.policy property:

java -Djava.security.manager 
    -Djava.security.policy=my.policy
    TestSecurityManager

With this command line, you should be able to write to the "temp" 
file, but not to the "other" file. Notice that this new solution 
provides the same capability as the custom TempfileSecurityManager 
class. However, you didn't have to write any Java code to use the 
policy file. The only work was making the correct settings in the 
policy file and on the command line.  While not foolproof, this 
declarative approach is far less prone to error than coding it 
yourself.  

The simple example above only begins to show the capabilities of 
the policy file. More generally, the syntax of a grant block in 
a policy file looks like this: 

grant [codeBase "URL"] {
    permission permissionClassName "target", "action";
    //...
};

JDK 1.2 includes permission classes for all of the security hooks 
in the virtual machine. So, for example, you could enable 
connecting to any machine's HTTP port with the following entry:

grant {
    permission java.io.SocketPermission "*:80", "connect";
};

The asterisk in the target string "*:80" is a wildcard for the 
machine address, so the connect action is allowed to target port 
80 of any machine.  

By default, grant entries apply to all the classes running in the 
JVM. As mentioned before, it is important to have a way to divide 
classes into different protection domains, each with their 
own set of permissions. The optional codeBase field accomplishes 
this by limiting the grant to classes loaded from a specific URL. 
Consider the following policy file:

grant codeBase "file:." {
    permission java.security.AllPermission;
}
grant codeBase "http://www.develop.com/TrustWorthyApplets/" {
    permission java.io.SocketPermission "*:80", "connect";
}

The first grant entry uses a file URL to give classes from the 
current directory the special permission "AllPermission." This 
permission basically disables security checks, and is useful only 
for very trusted code. In this example the trusted code is in the 
current directory (presumably you wrote that code yourself). The 
second entry uses an HTTP URL to specify that applets downloaded 
from a specific website can connect to any machine's HTTP port.  
The codeBase field makes it easy to configure fine-grained access 
control, without writing any code. This flexible control is 
essential for distributed systems built with higher level 
technologies such as RMI, JINI, or EJB.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The JDK 1.2 security architecture supports several interesting 
capabilities not covered here, including digital signing, custom 
permissions, custom policy implementations, and privileged scopes.  
For more information on these security features, examine the 
security documentation at: 

http://java.sun.com/j2se/1.3/docs/guide/security/index.html

Java supports user-based security through the Java 
Authentication and Authorization Service (JAAS). For 
information about JAAS, see:

http://java.sun.com/products/jaas/

For a comprehensive description of security in the Java 2 
Platform, see the book "Inside Java 2 Platform Security: 
Architecture, API Design, and Implementation" by Li Gong
(http://java.sun.com/docs/books/security/index.html).

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only. To remove your name from the list,
see Subscribe/Unsubscribe below.


- FEEDBACK
Comments? Send your feedback on the JDC Tech Tips to:

jdc-webmaster@sun.com


- SUBSCRIBE/UNSUBSCRIBE
The JDC newsletter mailing lists are used for internal 
Sun Microsystems(TM) purposes only. The JDC Tech Tips are 
sent to you because you elected to subscribe.

To remove your name from a JDC newsletter mailing list:

o Go to the JDC Front page. (http://java.sun.com/jdc/)
o Select Subscribe to free JDC newsletters.
  If you are not logged in automatically, type in your 
  UserID and password.
o Update your newsletter preferences and click Update.

To subscribe to a JDC newsletter mailing list:

o Go to the JDC Front page. (http://java.sun.com/jdc/)
o If you are already a member of the JDC, log in. 
  If you are not a member, select Register (It's free!) 
  and fill out the requested information.
o Select Subscribe to free JDC newsletters.
o Choose the newsletters you want to subscribe to and click Update.


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://java.sun.com/jdc/TechTips/index.html


- COPYRIGHT
Copyright 2000 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright. For more information, see:

http://java.sun.com/jdc/copyright.html


JDC Tech Tips 
September 26, 2000


* As used in this document, the terms "Java virtual machine" 
  or "JVM" mean a virtual machine for the Java platform. 








