rt/emul/compact/src/main/java/java/security/AccessController.java
author Jaroslav Tulach <jtulach@netbeans.org>
Thu, 03 Oct 2013 15:40:35 +0200
branchjdk7-b147
changeset 1334 588d5bf7a560
child 1341 b16f72c563f2
permissions -rw-r--r--
Set of JDK classes needed to run javac
     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 }