home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / security / AccessController.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  9.5 KB  |  281 lines

  1. /*
  2.  * @(#)AccessController.java    1.34 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. /** 
  18.  * <p> The AccessController class is used for three purposes, each of
  19.  * which is described in further detail below:
  20.  * 
  21.  * <ul>
  22.  * <li> to decide whether an access to a critical system
  23.  * resource is to be allowed or denied, based on the security policy
  24.  * currently in effect,<p> 
  25.  * <li>to mark code as being "privileged", thus affecting subsequent
  26.  * access determinations, and<p>
  27.  * <li>to obtain a "snapshot" of the current calling context so
  28.  * access-control decisions from a different context can be made with
  29.  * respect to the saved context.
  30.  * </ul>
  31.  * 
  32.  * <p> There is only one instance of AccessController in each
  33.  * Java runtime.
  34.  *
  35.  * <p> The <a href = "#checkPermission">checkPermission</a> method
  36.  * determines whether the access request indicated by a specified
  37.  * permission should be granted or denied. A sample call appears
  38.  * below. In this example, <code>checkPermission</code> will determine 
  39.  * whether or not to grant "read" access to the file named "testFile" in 
  40.  * the "/temp" directory.
  41.  * 
  42.  * <pre>
  43.  * 
  44.  *    FilePermission perm = new FilePermission("/temp/testFile", "read");
  45.  *    AccessController.checkPermission(perm);
  46.  * 
  47.  * </pre>
  48.  *
  49.  * <p> If a requested access is allowed, 
  50.  * <code>checkPermission</code> returns quietly. If denied, an 
  51.  * AccessControlException is
  52.  * thrown. AccessControlException can also be thrown if the requested
  53.  * permission is of an incorrect type or contains an invalid value.
  54.  * Such information is given whenever possible.
  55.  * 
  56.  * Suppose the current thread traversed m callers, in the order of caller 1 
  57.  * to caller 2 to caller m. Then caller m invoked the 
  58.  * <code>checkPermission</code> method.
  59.  * The <code>checkPermission </code>method determines whether access 
  60.  * is granted or denied based on the following algorithm:
  61.  * 
  62.  * <pre>
  63.  * i = m;
  64.  * 
  65.  * while (i > 0) {
  66.  * 
  67.  *     if (caller i's domain does not have the permission)
  68.  *         throw AccessControlException
  69.  * 
  70.  *     else if (caller i is marked as privileged) {
  71.  *         if (a context was specified in the call to beginPrivileged) 
  72.  *             context.checkPermission(permission)
  73.  *         else
  74.  *             return;
  75.  *     }
  76.  *     i = i - 1;
  77.  * };
  78.  *
  79.  *    // Next, check the context inherited when
  80.  *    // the thread was created. Whenever a new thread is created, the
  81.  *    // AccessControlContext at that time is
  82.  *    // stored and associated with the new thread, as the "inherited"
  83.  *    // context.
  84.  * 
  85.  * inheritedContext.checkPermission(permission);
  86.  * </pre>
  87.  * 
  88.  * <p> A caller can be marked as being "privileged" 
  89.  * (see <a href = "#beginPrivileged">beginPrivileged</a> and below). 
  90.  * When making access control decisions, the <code>checkPermission</code>
  91.  * method stops checking if it reaches a caller that 
  92.  * was marked as "privileged" via a <code>beginPrivileged</code> 
  93.  * call without a context argument (see below for information about a
  94.  * context argument). If that caller's domain has the
  95.  * specified permission, no further checking is done and <code>checkPermission</code>
  96.  * returns quietly, indicating that the requested access is allowed.
  97.  * If that domain does not have the specified permission, an exception is thrown,
  98.  * as usual.
  99.  * 
  100.  * <p> The normal use of the "privileged" feature is as follows. Note the use of
  101.  * the <code>try/finally</code> block to ensure the privileged section is always
  102.  * exited:
  103.  *
  104.  * <pre>
  105.  *   somemethod() {
  106.  *        ...normal code here...
  107.  *        try {
  108.  *           AccessController.beginPrivileged();
  109.  *           // privileged code goes here, for example:
  110.  *           System.loadLibrary("awt");
  111.  *        } finally {
  112.  *           AccessController.endPrivileged();
  113.  *        }
  114.  *     ...normal code here...
  115.  *  }
  116.  * </pre>
  117.  * 
  118.  * <p> Be *very* careful in your use of the "privileged" construct, and 
  119.  * always remember to make the privileged code section as small as possible.
  120.  * 
  121.  * <p> Note that <code>checkPermission</code> always performs security checks
  122.  * within the context of the currently executing thread.
  123.  * Sometimes a security check that should be made within a given context
  124.  * will actually need to be done from within a
  125.  * <i>different</i> context (for example, from within a worker thread).
  126.  * The <a href = "#getContext">getContext</a> method and 
  127.  * AccessControlContext class are provided 
  128.  * for this situation. The <code>getContext</code> method takes a "snapshot"
  129.  * of the current calling context, and places
  130.  * it in an AccessControlContext object, which it returns. A sample call is
  131.  * the following:
  132.  * 
  133.  * <pre>
  134.  * 
  135.  *   AccessControlContext acc = AccessController.getContext()
  136.  * 
  137.  * </pre>
  138.  * 
  139.  * <p>
  140.  * AccessControlContext itself has a <code>checkPermission</code> method
  141.  * that makes access decisions based on the context <i>it</i> encapsulates,
  142.  * rather than that of the current execution thread.
  143.  * Code within a different context can thus call that method on the
  144.  * previously-saved AccessControlContext object. A sample call is the
  145.  * following:
  146.  * 
  147.  * <pre>
  148.  * 
  149.  *   acc.checkPermission(permission)
  150.  * 
  151.  * </pre> 
  152.  *
  153.  * <p> There are also times where you don't know a priori which permissions
  154.  * to check the context against. In these cases you can use the
  155.  * beginPrivileged method that takes a context:
  156.  * 
  157.  * <pre>
  158.  *   somemethod() {
  159.  *        ...normal code here...
  160.  *        try {
  161.  *           AccessController.beginPrivileged(acc);
  162.  *           // Code goes here. Any permission checks from this
  163.  *           // point forward require both the current context and
  164.  *           // the snapshot's context to have the desired permission.
  165.  *        } finally {
  166.  *           AccessController.endPrivileged();
  167.  *        }
  168.  *     ...normal code here...
  169.  * </pre>
  170.  * 
  171.  * @see AccessControlContext
  172.  *
  173.  * @version 1.34 98/03/18
  174.  * @author Li Gong 
  175.  * @author Roland Schemers
  176.  */
  177.  
  178. public final class AccessController {
  179.  
  180.     /** 
  181.      * Don't allow anyone to instantiate an AccessController
  182.      */
  183.     private AccessController() { }
  184.  
  185.     /**
  186.      * Marks the calling thread's stack frame as "privileged".
  187.      */
  188.     public static native void beginPrivileged();
  189.  
  190.     /**
  191.      * Marks the calling thread's stack frame as "privileged" and 
  192.      * associates the given AccessControlContext with the 
  193.      * privileged frame. The context will be included in all future
  194.      * access control checks, and will be checked after the 
  195.      * privileged frame's ProtectionDomain is checked.
  196.      */
  197.     public static native void beginPrivileged(AccessControlContext context);
  198.  
  199.     /**
  200.      * Unmarks the calling thread's stack frame, indicating it is no longer
  201.      * "privileged". This call may only be done
  202.      * in the same frame as the <code>beginPrivileged</code> call.
  203.      */
  204.     public static native void endPrivileged();
  205.  
  206.     /**
  207.      * Returns the AccessControl context. i.e., it gets 
  208.      * the protection domains of all the callers on the stack,
  209.      * starting at the first class with a non-null 
  210.      * ProtectionDomain. 
  211.      *
  212.      * @return the access control context based on the current stack or
  213.      *         null if there was only privileged system code.
  214.      * 
  215.      * 
  216.      */
  217.  
  218.     private static native AccessControlContext getStackAccessControlContext();
  219.  
  220.     /**
  221.      * Returns the "inherited" AccessControl context. This is the context
  222.      * that existed when the thread was created. Package private so 
  223.      * AccessControlContext can use it.
  224.      */
  225.  
  226.     static native AccessControlContext getInheritedAccessControlContext();
  227.  
  228.     /** 
  229.      * This method takes a "snapshot" of the current calling context, which
  230.      * includes the current Thread's inherited AccessControlContext,
  231.      * and places it in an AccessControlContext object. This context may then
  232.      * be checked at a later point, possibly in another thread.
  233.      *
  234.      * @see AccessControlContext
  235.      *
  236.      * @return the AccessControlContext based on the current context.
  237.      */
  238.  
  239.     public static AccessControlContext getContext()
  240.     {
  241.     AccessControlContext acc = getStackAccessControlContext();
  242.     if (acc == null) {
  243.         // all we had was privileged system code. We don't want
  244.         // to return null though, so we construct a real ACC.
  245.         return new AccessControlContext(null, true);
  246.     } else {
  247.         return acc.optimize();
  248.     }
  249.     }
  250.  
  251.     /** 
  252.      * Determines whether the access request indicated by the
  253.      * specified permission should be allowed or denied, based on
  254.      * the security policy currently in effect. 
  255.      * This method quietly returns if the access request
  256.      * is permitted, or throws a suitable AccessControlException otherwise. 
  257.      *
  258.      * @param perm the requested permission.
  259.      * 
  260.      * @exception AccessControlException if the specified permission
  261.      * is not permitted, based on the current security policy.
  262.      */
  263.  
  264.     public static void checkPermission(Permission perm)
  265.          throws AccessControlException 
  266.     {
  267.     //System.err.println("checkPermission "+perm);
  268.     //Thread.currentThread().dumpStack();
  269.  
  270.     AccessControlContext stack = getStackAccessControlContext();
  271.     // if context is null, we had privileged system code on the stack.
  272.     if (stack == null)
  273.         return;
  274.  
  275.     AccessControlContext acc = stack.optimize();
  276.  
  277.     acc.checkPermission(perm);
  278.  
  279.     }
  280. }
  281.