/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.security; /** * This class must be implemented by the vm vendor, or the reference * implementation can be used if the documented native is implemented. * * Checks access to system resources. Supports marking of code as priveleged. * Makes context snapshots to allow checking from other contexts. */ public final class AccessController { static { // Initialize vm-internal caches initializeInternal(); } private static void initializeInternal() { } /** * Prevents this class from being instantiated. */ private AccessController() { } /** * This native must be implemented to use the reference implementation of * this class. It is used by checkPermission() and getContext(), which call * this native with depth = 1. * * Returns an array of ProtectionDomain from the classes on the stack, from * the specified depth up to the first privileged frame, or the end of the * stack if there is not a privileged frame. The array may be larger than * required, but must be null terminated. As bootstrap classes have all * permissions, bootstrap class frames SHOULD be skipped. Bootstrap class * frames MUST be skipped if the ProtectionDomain of bootstrap classes is * null. Duplicate ProtectionDomains SHOULD be removed. * * The first element of the result is the AccessControlContext, which may be * null, either from the privileged frame, or from the current Thread if * there is not a privileged frame. * * A privileged frame is any frame running one of the following methods: * * <code><ul> * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;</li> * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;</li> * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li> * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li> * </ul></code> * * @param depth * The stack depth at which to start. Depth 0 is the current * frame (the caller of this native). * * @return an Object[] where the first element is AccessControlContext, and * the other elements are ProtectionsDomain. */ private static Object[] getProtectionDomains(int depth) { throw new Error("TODO"); } /** * Checks whether the running program is allowed to access the resource * being guarded by the given Permission argument. * * * @param perm * the permission to check * @exception AccessControlException * if access is not allowed. */ public static void checkPermission(Permission perm) throws AccessControlException { // TODO: implement access permissions if (true) return; if (perm == null) throw new NullPointerException(); Object[] domains = getProtectionDomains(1); AccessControlContext acc = (AccessControlContext) domains[0]; ProtectionDomain[] pDomains = null; if (acc != null && acc.domainCombiner != null) { pDomains = acc.domainCombiner.combine(toArrayOfProtectionDomains( domains, null), acc.domainsArray); } else { pDomains = toArrayOfProtectionDomains(domains, acc); } for (int i = 0, length = pDomains.length; i < length; i++) { if (!pDomains[i].implies(perm)) { throw new AccessControlException("Access Denied " + perm, perm); //$NON-NLS-1$ } } } /** * Used to keep the context live during doPrivileged(). * * @see #doPrivileged(PrivilegedAction, AccessControlContext) */ private static void keepalive(AccessControlContext context) { } /** * Answers the access controller context of the current thread, including * the inherited ones. It basically retrieves all the protection domains * from the calling stack and creates an <code>AccessControlContext</code> * with them. * * @return the access control context of the current thread * @see AccessControlContext */ public static AccessControlContext getContext() { // TODO: implement access permissions if (true) return null; Object[] domains = getProtectionDomains(1); AccessControlContext acc = (AccessControlContext) domains[0]; ProtectionDomain[] pDomains = null; if (acc != null && acc.domainCombiner != null) { pDomains = acc.domainCombiner.combine(toArrayOfProtectionDomains( domains, null), acc.domainsArray); AccessControlContext result = new AccessControlContext(pDomains, false); result.domainCombiner = acc.domainCombiner; return result; } return new AccessControlContext( toArrayOfProtectionDomains(domains, acc), false); } private static ProtectionDomain[] toArrayOfProtectionDomains( Object[] domains, AccessControlContext acc) { int len = 0, size = domains.length - 1; int extra = acc == null ? 0 : acc.domainsArray.length; ProtectionDomain[] answer = new ProtectionDomain[size + extra]; for (int i = 1; i <= size; i++) { boolean found = false; if ((answer[len] = (ProtectionDomain) domains[i]) == null) break; if (acc != null) { for (int j = 0; j < acc.domainsArray.length; j++) { if (answer[len] == acc.domainsArray[j]) { found = true; break; } } } if (!found) len++; } if (len == 0 && acc != null) return acc.domainsArray; else if (len < size) { ProtectionDomain[] copy = new ProtectionDomain[len + extra]; System.arraycopy(answer, 0, copy, 0, len); answer = copy; } if (acc != null) System.arraycopy(acc.domainsArray, 0, answer, len, acc.domainsArray.length); return answer; } /** * Performs the privileged action specified by <code>action</code>. * * When permission checks are made, if the permission has been granted by * all frames below and including the one representing the call to this * method, then the permission is granted. In otherwords, the check stops * here. * * Any unchecked exception generated by this method will propagate up the * chain. * * @param action * the action being performed * @param <T> * the return type for the privileged action * @return the result of evaluating the action * * @see #doPrivileged(PrivilegedAction) */ public static <T> T doPrivileged(PrivilegedAction<T> action) { return action.run(); } /** * Performs the privileged action specified by <code>action</code>. * * When permission checks are made, if the permission has been granted by * all frames below and including the one representing the call to this * method, then the permission is granted iff it is granted by the * AccessControlContext <code>context</code>. In otherwords, no more * checking of the current stack is performed. Instead, the passed in * context is checked. * * Any unchecked exception generated by this method will propagate up the * chain. * * @param action * the action being performed * @param <T> * the return type for the privileged action * @param context * the context being checked for the privileged action * @return the result of evaluating the action * * @see #doPrivileged(PrivilegedAction) */ public static <T> T doPrivileged(PrivilegedAction<T> action, AccessControlContext context) { T result = action.run(); keepalive(context); return result; } /** * Performs the privileged action specified by <code>action</code>. * * When permission checks are made, if the permission has been granted by * all frames below and including the one representing the call to this * method, then the permission is granted. In otherwords, the check stops * here. * * Any unchecked exception generated by this method will propagate up the * chain. However, checked exceptions will be caught an re-thrown as * PrivilegedActionExceptions. * * @param action * the action being performed * @param <T> * the return type for the privileged action * @return the result of evaluating the action * @throws PrivilegedActionException * if a checked exception was thrown * @see #doPrivileged(PrivilegedAction) */ public static <T> T doPrivileged(PrivilegedExceptionAction<T> action) throws PrivilegedActionException { try { return action.run(); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new PrivilegedActionException(ex); } } /** * Performs the privileged action specified by <code>action</code>. * * When permission checks are made, if the permission has been granted by * all frames below and including the one representing the call to this * method, then the permission is granted iff it is granted by the * AccessControlContext <code>context</code>. In otherwords, no more * checking of the current stack is performed. Instead, the passed in * context is checked. * * Any unchecked exception generated by this method will propagate up the * chain. However, checked exceptions will be caught an re-thrown as * PrivilegedActionExceptions * * @param action * the action being performed * @param <T> * the return type for the privileged action * @param context * the context being checked for the privileged action * @return the result of evaluating the action * @throws PrivilegedActionException * if a checked exception was thrown * * @see #doPrivileged(PrivilegedAction) */ public static <T> T doPrivileged(PrivilegedExceptionAction<T> action, AccessControlContext context) throws PrivilegedActionException { try { T result = action.run(); keepalive(context); return result; } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new PrivilegedActionException(ex); } } }