Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    1   /*
    2    * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.security;
   27   
   28   import sun.security.util.Debug;
   29   
   30   /**
   31    * <p> The AccessController class is used for access control operations
   32    * and decisions.
   33    *
   34    * <p> More specifically, the AccessController class is used for
   35    * three purposes:
   36    *
   37    * <ul>
   38    * <li> to decide whether an access to a critical system
   39    * resource is to be allowed or denied, based on the security policy
   40    * currently in effect,<p>
   41    * <li>to mark code as being "privileged", thus affecting subsequent
   42    * access determinations, and<p>
   43    * <li>to obtain a "snapshot" of the current calling context so
   44    * access-control decisions from a different context can be made with
   45    * respect to the saved context. </ul>
   46    *
   47    * <p> The {@link #checkPermission(Permission) checkPermission} method
   48    * determines whether the access request indicated by a specified
   49    * permission should be granted or denied. A sample call appears
   50    * below. In this example, <code>checkPermission</code> will determine
   51    * whether or not to grant "read" access to the file named "testFile" in
   52    * the "/temp" directory.
   53    *
   54    * <pre>
   55    *
   56    * FilePermission perm = new FilePermission("/temp/testFile", "read");
   57    * AccessController.checkPermission(perm);
   58    *
   59    * </pre>
   60    *
   61    * <p> If a requested access is allowed,
   62    * <code>checkPermission</code> returns quietly. If denied, an
   63    * AccessControlException is
   64    * thrown. AccessControlException can also be thrown if the requested
   65    * permission is of an incorrect type or contains an invalid value.
   66    * Such information is given whenever possible.
   67    *
   68    * Suppose the current thread traversed m callers, in the order of caller 1
   69    * to caller 2 to caller m. Then caller m invoked the
   70    * <code>checkPermission</code> method.
   71    * The <code>checkPermission </code>method determines whether access
   72    * is granted or denied based on the following algorithm:
   73    *
   74    *  <pre> {@code
   75    * for (int i = m; i > 0; i--) {
   76    *
   77    *     if (caller i's domain does not have the permission)
   78    *         throw AccessControlException
   79    *
   80    *     else if (caller i is marked as privileged) {
   81    *         if (a context was specified in the call to doPrivileged)
   82    *             context.checkPermission(permission)
   83    *         return;
   84    *     }
   85    * };
   86    *
   87    * // Next, check the context inherited when the thread was created.
   88    * // Whenever a new thread is created, the AccessControlContext at
   89    * // that time is stored and associated with the new thread, as the
   90    * // "inherited" context.
   91    *
   92    * inheritedContext.checkPermission(permission);
   93    * }</pre>
   94    *
   95    * <p> A caller can be marked as being "privileged"
   96    * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
   97    * When making access control decisions, the <code>checkPermission</code>
   98    * method stops checking if it reaches a caller that
   99    * was marked as "privileged" via a <code>doPrivileged</code>
  100    * call without a context argument (see below for information about a
  101    * context argument). If that caller's domain has the
  102    * specified permission, no further checking is done and
  103    * <code>checkPermission</code>
  104    * returns quietly, indicating that the requested access is allowed.
  105    * If that domain does not have the specified permission, an exception
  106    * is thrown, as usual.
  107    *
  108    * <p> The normal use of the "privileged" feature is as follows. If you
  109    * don't need to return a value from within the "privileged" block, do
  110    * the following:
  111    *
  112    *  <pre> {@code
  113    * somemethod() {
  114    *     ...normal code here...
  115    *     AccessController.doPrivileged(new PrivilegedAction<Void>() {
  116    *         public Void run() {
  117    *             // privileged code goes here, for example:
  118    *             System.loadLibrary("awt");
  119    *             return null; // nothing to return
  120    *         }
  121    *     });
  122    *     ...normal code here...
  123    * }}</pre>
  124    *
  125    * <p>
  126    * PrivilegedAction is an interface with a single method, named
  127    * <code>run</code>.
  128    * The above example shows creation of an implementation
  129    * of that interface; a concrete implementation of the
  130    * <code>run</code> method is supplied.
  131    * When the call to <code>doPrivileged</code> is made, an
  132    * instance of the PrivilegedAction implementation is passed
  133    * to it. The <code>doPrivileged</code> method calls the
  134    * <code>run</code> method from the PrivilegedAction
  135    * implementation after enabling privileges, and returns the
  136    * <code>run</code> method's return value as the
  137    * <code>doPrivileged</code> return value (which is
  138    * ignored in this example).
  139    *
  140    * <p> If you need to return a value, you can do something like the following:
  141    *
  142    *  <pre> {@code
  143    * somemethod() {
  144    *     ...normal code here...
  145    *     String user = AccessController.doPrivileged(
  146    *         new PrivilegedAction<String>() {
  147    *         public String run() {
  148    *             return System.getProperty("user.name");
  149    *             }
  150    *         });
  151    *     ...normal code here...
  152    * }}</pre>
  153    *
  154    * <p>If the action performed in your <code>run</code> method could
  155    * throw a "checked" exception (those listed in the <code>throws</code> clause
  156    * of a method), then you need to use the
  157    * <code>PrivilegedExceptionAction</code> interface instead of the
  158    * <code>PrivilegedAction</code> interface:
  159    *
  160    *  <pre> {@code
  161    * somemethod() throws FileNotFoundException {
  162    *     ...normal code here...
  163    *     try {
  164    *         FileInputStream fis = AccessController.doPrivileged(
  165    *         new PrivilegedExceptionAction<FileInputStream>() {
  166    *             public FileInputStream run() throws FileNotFoundException {
  167    *                 return new FileInputStream("someFile");
  168    *             }
  169    *         });
  170    *     } catch (PrivilegedActionException e) {
  171    *         // e.getException() should be an instance of FileNotFoundException,
  172    *         // as only "checked" exceptions will be "wrapped" in a
  173    *         // PrivilegedActionException.
  174    *         throw (FileNotFoundException) e.getException();
  175    *     }
  176    *     ...normal code here...
  177    *  }}</pre>
  178    *
  179    * <p> Be *very* careful in your use of the "privileged" construct, and
  180    * always remember to make the privileged code section as small as possible.
  181    *
  182    * <p> Note that <code>checkPermission</code> always performs security checks
  183    * within the context of the currently executing thread.
  184    * Sometimes a security check that should be made within a given context
  185    * will actually need to be done from within a
  186    * <i>different</i> context (for example, from within a worker thread).
  187    * The {@link #getContext() getContext} method and
  188    * AccessControlContext class are provided
  189    * for this situation. The <code>getContext</code> method takes a "snapshot"
  190    * of the current calling context, and places
  191    * it in an AccessControlContext object, which it returns. A sample call is
  192    * the following:
  193    *
  194    * <pre>
  195    *
  196    * AccessControlContext acc = AccessController.getContext()
  197    *
  198    * </pre>
  199    *
  200    * <p>
  201    * AccessControlContext itself has a <code>checkPermission</code> method
  202    * that makes access decisions based on the context <i>it</i> encapsulates,
  203    * rather than that of the current execution thread.
  204    * Code within a different context can thus call that method on the
  205    * previously-saved AccessControlContext object. A sample call is the
  206    * following:
  207    *
  208    * <pre>
  209    *
  210    * acc.checkPermission(permission)
  211    *
  212    * </pre>
  213    *
  214    * <p> There are also times where you don't know a priori which permissions
  215    * to check the context against. In these cases you can use the
  216    * doPrivileged method that takes a context:
  217    *
  218    *  <pre> {@code
  219    * somemethod() {
  220    *     AccessController.doPrivileged(new PrivilegedAction<Object>() {
  221    *         public Object run() {
  222    *             // Code goes here. Any permission checks within this
  223    *             // run method will require that the intersection of the
  224    *             // callers protection domain and the snapshot's
  225    *             // context have the desired permission.
  226    *         }
  227    *     }, acc);
  228    *     ...normal code here...
  229    * }}</pre>
  230    *
  231    * @see AccessControlContext
  232    *
  233    * @author Li Gong
  234    * @author Roland Schemers
  235    */
  236   
  237   public final class AccessController {
  238   
  239       /**
  240        * Don't allow anyone to instantiate an AccessController
  241        */
  242       private AccessController() { }
  243   
  244       /**
  245        * Performs the specified <code>PrivilegedAction</code> with privileges
  246        * enabled. The action is performed with <i>all</i> of the permissions
  247        * possessed by the caller's protection domain.
  248        *
  249        * <p> If the action's <code>run</code> method throws an (unchecked)
  250        * exception, it will propagate through this method.
  251        *
  252        * <p> Note that any DomainCombiner associated with the current
  253        * AccessControlContext will be ignored while the action is performed.
  254        *
  255        * @param action the action to be performed.
  256        *
  257        * @return the value returned by the action's <code>run</code> method.
  258        *
  259        * @exception NullPointerException if the action is <code>null</code>
  260        *
  261        * @see #doPrivileged(PrivilegedAction,AccessControlContext)
  262        * @see #doPrivileged(PrivilegedExceptionAction)
  263        * @see #doPrivilegedWithCombiner(PrivilegedAction)
  264        * @see java.security.DomainCombiner
  265        */
  266   
  267       public static native <T> T doPrivileged(PrivilegedAction<T> action);
  268   
  269       /**
  270        * Performs the specified <code>PrivilegedAction</code> with privileges
  271        * enabled. The action is performed with <i>all</i> of the permissions
  272        * possessed by the caller's protection domain.
  273        *
  274        * <p> If the action's <code>run</code> method throws an (unchecked)
  275        * exception, it will propagate through this method.
  276        *
  277        * <p> This method preserves the current AccessControlContext's
  278        * DomainCombiner (which may be null) while the action is performed.
  279        *
  280        * @param action the action to be performed.
  281        *
  282        * @return the value returned by the action's <code>run</code> method.
  283        *
  284        * @exception NullPointerException if the action is <code>null</code>
  285        *
  286        * @see #doPrivileged(PrivilegedAction)
  287        * @see java.security.DomainCombiner
  288        *
  289        * @since 1.6
  290        */
  291       public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
  292   
  293           DomainCombiner dc = null;
  294           AccessControlContext acc = getStackAccessControlContext();
  295           if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
  296               return AccessController.doPrivileged(action);
  297           }
  298           return AccessController.doPrivileged(action, preserveCombiner(dc));
  299       }
  300   
  301   
  302       /**
  303        * Performs the specified <code>PrivilegedAction</code> with privileges
  304        * enabled and restricted by the specified
  305        * <code>AccessControlContext</code>.
  306        * The action is performed with the intersection of the permissions
  307        * possessed by the caller's protection domain, and those possessed
  308        * by the domains represented by the specified
  309        * <code>AccessControlContext</code>.
  310        * <p>
  311        * If the action's <code>run</code> method throws an (unchecked) exception,
  312        * it will propagate through this method.
  313        *
  314        * @param action the action to be performed.
  315        * @param context an <i>access control context</i>
  316        *                representing the restriction to be applied to the
  317        *                caller's domain's privileges before performing
  318        *                the specified action.  If the context is
  319        *                <code>null</code>,
  320        *                then no additional restriction is applied.
  321        *
  322        * @return the value returned by the action's <code>run</code> method.
  323        *
  324        * @exception NullPointerException if the action is <code>null</code>
  325        *
  326        * @see #doPrivileged(PrivilegedAction)
  327        * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  328        */
  329       public static native <T> T doPrivileged(PrivilegedAction<T> action,
  330                                               AccessControlContext context);
  331   
  332       /**
  333        * Performs the specified <code>PrivilegedExceptionAction</code> with
  334        * privileges enabled.  The action is performed with <i>all</i> of the
  335        * permissions possessed by the caller's protection domain.
  336        *
  337        * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
  338        * exception, it will propagate through this method.
  339        *
  340        * <p> Note that any DomainCombiner associated with the current
  341        * AccessControlContext will be ignored while the action is performed.
  342        *
  343        * @param action the action to be performed
  344        *
  345        * @return the value returned by the action's <code>run</code> method
  346        *
  347        * @exception PrivilegedActionException if the specified action's
  348        *         <code>run</code> method threw a <i>checked</i> exception
  349        * @exception NullPointerException if the action is <code>null</code>
  350        *
  351        * @see #doPrivileged(PrivilegedAction)
  352        * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  353        * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
  354        * @see java.security.DomainCombiner
  355        */
  356       public static native <T> T
  357           doPrivileged(PrivilegedExceptionAction<T> action)
  358           throws PrivilegedActionException;
  359   
  360   
  361       /**
  362        * Performs the specified <code>PrivilegedExceptionAction</code> with
  363        * privileges enabled.  The action is performed with <i>all</i> of the
  364        * permissions possessed by the caller's protection domain.
  365        *
  366        * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
  367        * exception, it will propagate through this method.
  368        *
  369        * <p> This method preserves the current AccessControlContext's
  370        * DomainCombiner (which may be null) while the action is performed.
  371        *
  372        * @param action the action to be performed.
  373        *
  374        * @return the value returned by the action's <code>run</code> method
  375        *
  376        * @exception PrivilegedActionException if the specified action's
  377        *         <code>run</code> method threw a <i>checked</i> exception
  378        * @exception NullPointerException if the action is <code>null</code>
  379        *
  380        * @see #doPrivileged(PrivilegedAction)
  381        * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  382        * @see java.security.DomainCombiner
  383        *
  384        * @since 1.6
  385        */
  386       public static <T> T doPrivilegedWithCombiner
  387           (PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
  388   
  389           DomainCombiner dc = null;
  390           AccessControlContext acc = getStackAccessControlContext();
  391           if (acc == null || (dc = acc.getAssignedCombiner()) == null) {
  392               return AccessController.doPrivileged(action);
  393           }
  394           return AccessController.doPrivileged(action, preserveCombiner(dc));
  395       }
  396   
  397       /**
  398        * preserve the combiner across the doPrivileged call
  399        */
  400       private static AccessControlContext preserveCombiner
  401                                           (DomainCombiner combiner) {
  402   
  403           /**
  404            * callerClass[0] = Reflection.getCallerClass
  405            * callerClass[1] = AccessController.preserveCombiner
  406            * callerClass[2] = AccessController.doPrivileged
  407            * callerClass[3] = caller
  408            */
  409           final Class callerClass = sun.reflect.Reflection.getCallerClass(3);
  410           ProtectionDomain callerPd = doPrivileged
  411               (new PrivilegedAction<ProtectionDomain>() {
  412               public ProtectionDomain run() {
  413                   return callerClass.getProtectionDomain();
  414               }
  415           });
  416   
  417           // perform 'combine' on the caller of doPrivileged,
  418           // even if the caller is from the bootclasspath
  419           ProtectionDomain[] pds = new ProtectionDomain[] {callerPd};
  420           return new AccessControlContext(combiner.combine(pds, null), combiner);
  421       }
  422   
  423   
  424       /**
  425        * Performs the specified <code>PrivilegedExceptionAction</code> with
  426        * privileges enabled and restricted by the specified
  427        * <code>AccessControlContext</code>.  The action is performed with the
  428        * intersection of the permissions possessed by the caller's
  429        * protection domain, and those possessed by the domains represented by the
  430        * specified <code>AccessControlContext</code>.
  431        * <p>
  432        * If the action's <code>run</code> method throws an <i>unchecked</i>
  433        * exception, it will propagate through this method.
  434        *
  435        * @param action the action to be performed
  436        * @param context an <i>access control context</i>
  437        *                representing the restriction to be applied to the
  438        *                caller's domain's privileges before performing
  439        *                the specified action.  If the context is
  440        *                <code>null</code>,
  441        *                then no additional restriction is applied.
  442        *
  443        * @return the value returned by the action's <code>run</code> method
  444        *
  445        * @exception PrivilegedActionException if the specified action's
  446        *         <code>run</code> method
  447        *         threw a <i>checked</i> exception
  448        * @exception NullPointerException if the action is <code>null</code>
  449        *
  450        * @see #doPrivileged(PrivilegedAction)
  451        * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  452        */
  453       public static native <T> T
  454           doPrivileged(PrivilegedExceptionAction<T> action,
  455                        AccessControlContext context)
  456           throws PrivilegedActionException;
  457   
  458       /**
  459        * Returns the AccessControl context. i.e., it gets
  460        * the protection domains of all the callers on the stack,
  461        * starting at the first class with a non-null
  462        * ProtectionDomain.
  463        *
  464        * @return the access control context based on the current stack or
  465        *         null if there was only privileged system code.
  466        */
  467   
  468       private static native AccessControlContext getStackAccessControlContext();
  469   
  470       /**
  471        * Returns the "inherited" AccessControl context. This is the context
  472        * that existed when the thread was created. Package private so
  473        * AccessControlContext can use it.
  474        */
  475   
  476       static native AccessControlContext getInheritedAccessControlContext();
  477   
  478       /**
  479        * This method takes a "snapshot" of the current calling context, which
  480        * includes the current Thread's inherited AccessControlContext,
  481        * and places it in an AccessControlContext object. This context may then
  482        * be checked at a later point, possibly in another thread.
  483        *
  484        * @see AccessControlContext
  485        *
  486        * @return the AccessControlContext based on the current context.
  487        */
  488   
  489       public static AccessControlContext getContext()
  490       {
  491           AccessControlContext acc = getStackAccessControlContext();
  492           if (acc == null) {
  493               // all we had was privileged system code. We don't want
  494               // to return null though, so we construct a real ACC.
  495               return new AccessControlContext(null, true);
  496           } else {
  497               return acc.optimize();
  498           }
  499       }
  500   
  501       /**
  502        * Determines whether the access request indicated by the
  503        * specified permission should be allowed or denied, based on
  504        * the current AccessControlContext and security policy.
  505        * This method quietly returns if the access request
  506        * is permitted, or throws an AccessControlException otherwise. The
  507        * getPermission method of the AccessControlException returns the
  508        * <code>perm</code> Permission object instance.
  509        *
  510        * @param perm the requested permission.
  511        *
  512        * @exception AccessControlException if the specified permission
  513        *            is not permitted, based on the current security policy.
  514        * @exception NullPointerException if the specified permission
  515        *            is <code>null</code> and is checked based on the
  516        *            security policy currently in effect.
  517        */
  518   
  519       public static void checkPermission(Permission perm)
  520                    throws AccessControlException
  521       {
  522           //System.err.println("checkPermission "+perm);
  523           //Thread.currentThread().dumpStack();
  524   
  525           if (perm == null) {
  526               throw new NullPointerException("permission can't be null");
  527           }
  528   
  529           AccessControlContext stack = getStackAccessControlContext();
  530           // if context is null, we had privileged system code on the stack.
  531           if (stack == null) {
  532               Debug debug = AccessControlContext.getDebug();
  533               boolean dumpDebug = false;
  534               if (debug != null) {
  535                   dumpDebug = !Debug.isOn("codebase=");
  536                   dumpDebug &= !Debug.isOn("permission=") ||
  537                       Debug.isOn("permission=" + perm.getClass().getCanonicalName());
  538               }
  539   
  540               if (dumpDebug && Debug.isOn("stack")) {
  541                   Thread.currentThread().dumpStack();
  542               }
  543   
  544               if (dumpDebug && Debug.isOn("domain")) {
  545                   debug.println("domain (context is null)");
  546               }
  547   
  548               if (dumpDebug) {
  549                   debug.println("access allowed "+perm);
  550               }
  551               return;
  552           }
  553   
  554           AccessControlContext acc = stack.optimize();
  555           acc.checkPermission(perm);
  556       }
  557   }

Save This Page
Home » openjdk-7 » java » security » [javadoc | source]