rt/emul/compact/src/main/java/java/security/AccessController.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 04 Oct 2013 12:05:02 +0200
changeset 1341 b16f72c563f2
parent 1334 588d5bf7a560
permissions -rw-r--r--
Trivial access controller
     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 /**
    29  * <p> The AccessController class is used for access control operations
    30  * and decisions.
    31  *
    32  * <p> More specifically, the AccessController class is used for
    33  * three purposes:
    34  *
    35  * <ul>
    36  * <li> to decide whether an access to a critical system
    37  * resource is to be allowed or denied, based on the security policy
    38  * currently in effect,<p>
    39  * <li>to mark code as being "privileged", thus affecting subsequent
    40  * access determinations, and<p>
    41  * <li>to obtain a "snapshot" of the current calling context so
    42  * access-control decisions from a different context can be made with
    43  * respect to the saved context. </ul>
    44  *
    45  * <p> The {@link #checkPermission(Permission) checkPermission} method
    46  * determines whether the access request indicated by a specified
    47  * permission should be granted or denied. A sample call appears
    48  * below. In this example, <code>checkPermission</code> will determine
    49  * whether or not to grant "read" access to the file named "testFile" in
    50  * the "/temp" directory.
    51  *
    52  * <pre>
    53  *
    54  * FilePermission perm = new FilePermission("/temp/testFile", "read");
    55  * AccessController.checkPermission(perm);
    56  *
    57  * </pre>
    58  *
    59  * <p> If a requested access is allowed,
    60  * <code>checkPermission</code> returns quietly. If denied, an
    61  * AccessControlException is
    62  * thrown. AccessControlException can also be thrown if the requested
    63  * permission is of an incorrect type or contains an invalid value.
    64  * Such information is given whenever possible.
    65  *
    66  * Suppose the current thread traversed m callers, in the order of caller 1
    67  * to caller 2 to caller m. Then caller m invoked the
    68  * <code>checkPermission</code> method.
    69  * The <code>checkPermission </code>method determines whether access
    70  * is granted or denied based on the following algorithm:
    71  *
    72  *  <pre> {@code
    73  * for (int i = m; i > 0; i--) {
    74  *
    75  *     if (caller i's domain does not have the permission)
    76  *         throw AccessControlException
    77  *
    78  *     else if (caller i is marked as privileged) {
    79  *         if (a context was specified in the call to doPrivileged)
    80  *             context.checkPermission(permission)
    81  *         return;
    82  *     }
    83  * };
    84  *
    85  * // Next, check the context inherited when the thread was created.
    86  * // Whenever a new thread is created, the AccessControlContext at
    87  * // that time is stored and associated with the new thread, as the
    88  * // "inherited" context.
    89  *
    90  * inheritedContext.checkPermission(permission);
    91  * }</pre>
    92  *
    93  * <p> A caller can be marked as being "privileged"
    94  * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
    95  * When making access control decisions, the <code>checkPermission</code>
    96  * method stops checking if it reaches a caller that
    97  * was marked as "privileged" via a <code>doPrivileged</code>
    98  * call without a context argument (see below for information about a
    99  * context argument). If that caller's domain has the
   100  * specified permission, no further checking is done and
   101  * <code>checkPermission</code>
   102  * returns quietly, indicating that the requested access is allowed.
   103  * If that domain does not have the specified permission, an exception
   104  * is thrown, as usual.
   105  *
   106  * <p> The normal use of the "privileged" feature is as follows. If you
   107  * don't need to return a value from within the "privileged" block, do
   108  * the following:
   109  *
   110  *  <pre> {@code
   111  * somemethod() {
   112  *     ...normal code here...
   113  *     AccessController.doPrivileged(new PrivilegedAction<Void>() {
   114  *         public Void run() {
   115  *             // privileged code goes here, for example:
   116  *             System.loadLibrary("awt");
   117  *             return null; // nothing to return
   118  *         }
   119  *     });
   120  *     ...normal code here...
   121  * }}</pre>
   122  *
   123  * <p>
   124  * PrivilegedAction is an interface with a single method, named
   125  * <code>run</code>.
   126  * The above example shows creation of an implementation
   127  * of that interface; a concrete implementation of the
   128  * <code>run</code> method is supplied.
   129  * When the call to <code>doPrivileged</code> is made, an
   130  * instance of the PrivilegedAction implementation is passed
   131  * to it. The <code>doPrivileged</code> method calls the
   132  * <code>run</code> method from the PrivilegedAction
   133  * implementation after enabling privileges, and returns the
   134  * <code>run</code> method's return value as the
   135  * <code>doPrivileged</code> return value (which is
   136  * ignored in this example).
   137  *
   138  * <p> If you need to return a value, you can do something like the following:
   139  *
   140  *  <pre> {@code
   141  * somemethod() {
   142  *     ...normal code here...
   143  *     String user = AccessController.doPrivileged(
   144  *         new PrivilegedAction<String>() {
   145  *         public String run() {
   146  *             return System.getProperty("user.name");
   147  *             }
   148  *         });
   149  *     ...normal code here...
   150  * }}</pre>
   151  *
   152  * <p>If the action performed in your <code>run</code> method could
   153  * throw a "checked" exception (those listed in the <code>throws</code> clause
   154  * of a method), then you need to use the
   155  * <code>PrivilegedExceptionAction</code> interface instead of the
   156  * <code>PrivilegedAction</code> interface:
   157  *
   158  *  <pre> {@code
   159  * somemethod() throws FileNotFoundException {
   160  *     ...normal code here...
   161  *     try {
   162  *         FileInputStream fis = AccessController.doPrivileged(
   163  *         new PrivilegedExceptionAction<FileInputStream>() {
   164  *             public FileInputStream run() throws FileNotFoundException {
   165  *                 return new FileInputStream("someFile");
   166  *             }
   167  *         });
   168  *     } catch (PrivilegedActionException e) {
   169  *         // e.getException() should be an instance of FileNotFoundException,
   170  *         // as only "checked" exceptions will be "wrapped" in a
   171  *         // PrivilegedActionException.
   172  *         throw (FileNotFoundException) e.getException();
   173  *     }
   174  *     ...normal code here...
   175  *  }}</pre>
   176  *
   177  * <p> Be *very* careful in your use of the "privileged" construct, and
   178  * always remember to make the privileged code section as small as possible.
   179  *
   180  * <p> Note that <code>checkPermission</code> always performs security checks
   181  * within the context of the currently executing thread.
   182  * Sometimes a security check that should be made within a given context
   183  * will actually need to be done from within a
   184  * <i>different</i> context (for example, from within a worker thread).
   185  * The {@link #getContext() getContext} method and
   186  * AccessControlContext class are provided
   187  * for this situation. The <code>getContext</code> method takes a "snapshot"
   188  * of the current calling context, and places
   189  * it in an AccessControlContext object, which it returns. A sample call is
   190  * the following:
   191  *
   192  * <pre>
   193  *
   194  * AccessControlContext acc = AccessController.getContext()
   195  *
   196  * </pre>
   197  *
   198  * <p>
   199  * AccessControlContext itself has a <code>checkPermission</code> method
   200  * that makes access decisions based on the context <i>it</i> encapsulates,
   201  * rather than that of the current execution thread.
   202  * Code within a different context can thus call that method on the
   203  * previously-saved AccessControlContext object. A sample call is the
   204  * following:
   205  *
   206  * <pre>
   207  *
   208  * acc.checkPermission(permission)
   209  *
   210  * </pre>
   211  *
   212  * <p> There are also times where you don't know a priori which permissions
   213  * to check the context against. In these cases you can use the
   214  * doPrivileged method that takes a context:
   215  *
   216  *  <pre> {@code
   217  * somemethod() {
   218  *     AccessController.doPrivileged(new PrivilegedAction<Object>() {
   219  *         public Object run() {
   220  *             // Code goes here. Any permission checks within this
   221  *             // run method will require that the intersection of the
   222  *             // callers protection domain and the snapshot's
   223  *             // context have the desired permission.
   224  *         }
   225  *     }, acc);
   226  *     ...normal code here...
   227  * }}</pre>
   228  *
   229  * @see AccessControlContext
   230  *
   231  * @author Li Gong
   232  * @author Roland Schemers
   233  */
   234 
   235 public final class AccessController {
   236 
   237     /**
   238      * Don't allow anyone to instantiate an AccessController
   239      */
   240     private AccessController() { }
   241 
   242     /**
   243      * Performs the specified <code>PrivilegedAction</code> with privileges
   244      * enabled. The action is performed with <i>all</i> of the permissions
   245      * possessed by the caller's protection domain.
   246      *
   247      * <p> If the action's <code>run</code> method throws an (unchecked)
   248      * exception, it will propagate through this method.
   249      *
   250      * <p> Note that any DomainCombiner associated with the current
   251      * AccessControlContext will be ignored while the action is performed.
   252      *
   253      * @param action the action to be performed.
   254      *
   255      * @return the value returned by the action's <code>run</code> method.
   256      *
   257      * @exception NullPointerException if the action is <code>null</code>
   258      *
   259      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
   260      * @see #doPrivileged(PrivilegedExceptionAction)
   261      * @see #doPrivilegedWithCombiner(PrivilegedAction)
   262      * @see java.security.DomainCombiner
   263      */
   264 
   265     public static <T> T doPrivileged(PrivilegedAction<T> action) {
   266         return action.run();
   267     }
   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         return action.run();
   293     }
   294 
   295 
   296     /**
   297      * Performs the specified <code>PrivilegedAction</code> with privileges
   298      * enabled and restricted by the specified
   299      * <code>AccessControlContext</code>.
   300      * The action is performed with the intersection of the permissions
   301      * possessed by the caller's protection domain, and those possessed
   302      * by the domains represented by the specified
   303      * <code>AccessControlContext</code>.
   304      * <p>
   305      * If the action's <code>run</code> method throws an (unchecked) exception,
   306      * it will propagate through this method.
   307      *
   308      * @param action the action to be performed.
   309      * @param context an <i>access control context</i>
   310      *                representing the restriction to be applied to the
   311      *                caller's domain's privileges before performing
   312      *                the specified action.  If the context is
   313      *                <code>null</code>,
   314      *                then no additional restriction is applied.
   315      *
   316      * @return the value returned by the action's <code>run</code> method.
   317      *
   318      * @exception NullPointerException if the action is <code>null</code>
   319      *
   320      * @see #doPrivileged(PrivilegedAction)
   321      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
   322      */
   323 //    public static native <T> T doPrivileged(PrivilegedAction<T> action,
   324 //                                            AccessControlContext context);
   325 
   326     /**
   327      * Performs the specified <code>PrivilegedExceptionAction</code> with
   328      * privileges enabled.  The action is performed with <i>all</i> of the
   329      * permissions possessed by the caller's protection domain.
   330      *
   331      * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
   332      * exception, it will propagate through this method.
   333      *
   334      * <p> Note that any DomainCombiner associated with the current
   335      * AccessControlContext will be ignored while the action is performed.
   336      *
   337      * @param action the action to be performed
   338      *
   339      * @return the value returned by the action's <code>run</code> method
   340      *
   341      * @exception PrivilegedActionException if the specified action's
   342      *         <code>run</code> method threw a <i>checked</i> exception
   343      * @exception NullPointerException if the action is <code>null</code>
   344      *
   345      * @see #doPrivileged(PrivilegedAction)
   346      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
   347      * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
   348      * @see java.security.DomainCombiner
   349      */
   350     public static <T> T
   351         doPrivileged(PrivilegedExceptionAction<T> action)
   352         throws PrivilegedActionException {
   353         try {
   354             return action.run();
   355         } catch (Exception ex) {
   356             throw new PrivilegedActionException(ex);
   357         }
   358     }
   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         return doPrivileged(action);
   389     }
   390 
   391     /**
   392      * Performs the specified <code>PrivilegedExceptionAction</code> with
   393      * privileges enabled and restricted by the specified
   394      * <code>AccessControlContext</code>.  The action is performed with the
   395      * intersection of the permissions possessed by the caller's
   396      * protection domain, and those possessed by the domains represented by the
   397      * specified <code>AccessControlContext</code>.
   398      * <p>
   399      * If the action's <code>run</code> method throws an <i>unchecked</i>
   400      * exception, it will propagate through this method.
   401      *
   402      * @param action the action to be performed
   403      * @param context an <i>access control context</i>
   404      *                representing the restriction to be applied to the
   405      *                caller's domain's privileges before performing
   406      *                the specified action.  If the context is
   407      *                <code>null</code>,
   408      *                then no additional restriction is applied.
   409      *
   410      * @return the value returned by the action's <code>run</code> method
   411      *
   412      * @exception PrivilegedActionException if the specified action's
   413      *         <code>run</code> method
   414      *         threw a <i>checked</i> exception
   415      * @exception NullPointerException if the action is <code>null</code>
   416      *
   417      * @see #doPrivileged(PrivilegedAction)
   418      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
   419      */
   420 //    public static native <T> T
   421 //        doPrivileged(PrivilegedExceptionAction<T> action,
   422 //                     AccessControlContext context)
   423 //        throws PrivilegedActionException;
   424 
   425     /**
   426      * This method takes a "snapshot" of the current calling context, which
   427      * includes the current Thread's inherited AccessControlContext,
   428      * and places it in an AccessControlContext object. This context may then
   429      * be checked at a later point, possibly in another thread.
   430      *
   431      * @see AccessControlContext
   432      *
   433      * @return the AccessControlContext based on the current context.
   434      */
   435 
   436 //    public static AccessControlContext getContext()
   437 //    {
   438 //        AccessControlContext acc = getStackAccessControlContext();
   439 //        if (acc == null) {
   440 //            // all we had was privileged system code. We don't want
   441 //            // to return null though, so we construct a real ACC.
   442 //            return new AccessControlContext(null, true);
   443 //        } else {
   444 //            return acc.optimize();
   445 //        }
   446 //    }
   447 
   448     /**
   449      * Determines whether the access request indicated by the
   450      * specified permission should be allowed or denied, based on
   451      * the current AccessControlContext and security policy.
   452      * This method quietly returns if the access request
   453      * is permitted, or throws an AccessControlException otherwise. The
   454      * getPermission method of the AccessControlException returns the
   455      * <code>perm</code> Permission object instance.
   456      *
   457      * @param perm the requested permission.
   458      *
   459      * @exception AccessControlException if the specified permission
   460      *            is not permitted, based on the current security policy.
   461      * @exception NullPointerException if the specified permission
   462      *            is <code>null</code> and is checked based on the
   463      *            security policy currently in effect.
   464      */
   465 
   466 //    public static void checkPermission(Permission perm)
   467 //                 throws AccessControlException
   468 //    {
   469 //        //System.err.println("checkPermission "+perm);
   470 //        //Thread.currentThread().dumpStack();
   471 //
   472 //        if (perm == null) {
   473 //            throw new NullPointerException("permission can't be null");
   474 //        }
   475 //
   476 //        AccessControlContext stack = getStackAccessControlContext();
   477 //        // if context is null, we had privileged system code on the stack.
   478 //        if (stack == null) {
   479 //            Debug debug = AccessControlContext.getDebug();
   480 //            boolean dumpDebug = false;
   481 //            if (debug != null) {
   482 //                dumpDebug = !Debug.isOn("codebase=");
   483 //                dumpDebug &= !Debug.isOn("permission=") ||
   484 //                    Debug.isOn("permission=" + perm.getClass().getCanonicalName());
   485 //            }
   486 //
   487 //            if (dumpDebug && Debug.isOn("stack")) {
   488 //                Thread.currentThread().dumpStack();
   489 //            }
   490 //
   491 //            if (dumpDebug && Debug.isOn("domain")) {
   492 //                debug.println("domain (context is null)");
   493 //            }
   494 //
   495 //            if (dumpDebug) {
   496 //                debug.println("access allowed "+perm);
   497 //            }
   498 //            return;
   499 //        }
   500 //
   501 //        AccessControlContext acc = stack.optimize();
   502 //        acc.checkPermission(perm);
   503 //    }
   504 }