summaryrefslogtreecommitdiffstats
path: root/security-kernel/src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /security-kernel/src
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'security-kernel/src')
-rw-r--r--security-kernel/src/main/java/java/security/AccessControlContext.java183
-rw-r--r--security-kernel/src/main/java/java/security/AccessController.java259
2 files changed, 442 insertions, 0 deletions
diff --git a/security-kernel/src/main/java/java/security/AccessControlContext.java b/security-kernel/src/main/java/java/security/AccessControlContext.java
new file mode 100644
index 0000000..22b1a30
--- /dev/null
+++ b/security-kernel/src/main/java/java/security/AccessControlContext.java
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+/**
+* @author Alexander V. Astapchuk
+* @version $Revision: 1.1.2.2.4.3 $
+*/
+
+package java.security;
+
+import java.util.ArrayList;
+import org.apache.harmony.security.fortress.PolicyUtils;
+
+/**
+ * @com.intel.drl.spec_ref
+ */
+public final class AccessControlContext {
+
+ // List of ProtectionDomains wrapped by the AccessControlContext
+ // It has the following characteristics:
+ // - 'context' can not be null
+ // - never contains null(s)
+ // - all elements are uniq (no dups)
+ ProtectionDomain[] context;
+
+ DomainCombiner combiner;
+
+ // An AccessControlContext inherited by the current thread from its parent
+ private AccessControlContext inherited;
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public AccessControlContext(AccessControlContext acc,
+ DomainCombiner combiner) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new SecurityPermission(
+ "createAccessControlContext"));
+ }
+ // no need to clone() here as ACC is immutable
+ this.context = acc.context;
+ this.combiner = combiner;
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public AccessControlContext(ProtectionDomain[] context) {
+ if (context == null) {
+ throw new NullPointerException("context can not be null");
+ }
+ if (context.length != 0) {
+ // remove dup entries
+ ArrayList<ProtectionDomain> a = new ArrayList<ProtectionDomain>();
+ for (int i = 0; i < context.length; i++) {
+ if (context[i] != null && !a.contains(context[i])) {
+ a.add(context[i]);
+ }
+ }
+ if (a.size() != 0) {
+ this.context = new ProtectionDomain[a.size()];
+ a.toArray(this.context);
+ }
+ }
+ if (this.context == null) {
+ // Prevent numerous checks for 'context==null'
+ this.context = new ProtectionDomain[0];
+ }
+ }
+
+ /**
+ * Package-level ctor which is used in AccessController.<br>
+ * ProtectionDomains passed as <code>stack</code> is then passed into
+ * {@link #AccessControlContext(ProtectionDomain[])}, therefore:<br>
+ * <il>
+ * <li>it must not be null
+ * <li>duplicates will be removed
+ * <li>null-s will be removed
+ * </li>
+ *
+ * @param stack - array of ProtectionDomains
+ * @param inherited - inherited context, which may be null
+ */
+ AccessControlContext(ProtectionDomain[] stack,
+ AccessControlContext inherited) {
+ this(stack); // removes dups, removes nulls, checks for stack==null
+ this.inherited = inherited;
+ }
+
+ /**
+ * Package-level ctor which is used in AccessController.<br>
+ * ProtectionDomains passed as <code>stack</code> is then passed into
+ * {@link #AccessControlContext(ProtectionDomain[])}, therefore:<br>
+ * <il>
+ * <li>it must not be null
+ * <li>duplicates will be removed
+ * <li>null-s will be removed
+ * </li>
+ *
+ * @param stack - array of ProtectionDomains
+ * @param inherited - inherited context, which may be null
+ */
+ AccessControlContext(ProtectionDomain[] stack,
+ DomainCombiner combiner) {
+ this(stack); // removes dups, removes nulls, checks for stack==null
+ this.combiner = combiner;
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public void checkPermission(Permission perm) throws AccessControlException {
+ if (perm == null) {
+ throw new NullPointerException("Permission cannot be null");
+ }
+ for (int i = 0; i < context.length; i++) {
+ if (!context[i].implies(perm)) {
+ throw new AccessControlException("Permission check failed "
+ + perm, perm);
+ }
+ }
+ if (inherited != null) {
+ inherited.checkPermission(perm);
+ }
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof AccessControlContext) {
+ AccessControlContext that = (AccessControlContext) obj;
+ if (!(PolicyUtils.matchSubset(context, that.context) && PolicyUtils
+ .matchSubset(that.context, context))) {
+ return false;
+ }
+ // 'combiner' is not taken into account - see the test
+ // AccessControllerTest.testEqualsObject_01
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public DomainCombiner getDomainCombiner() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new SecurityPermission("getDomainCombiner"));
+ }
+ return combiner;
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public int hashCode() {
+ int hash = 0;
+ for (int i = 0; i < context.length; i++) {
+ hash ^= context[i].hashCode();
+ }
+ return hash;
+ }
+
+}
diff --git a/security-kernel/src/main/java/java/security/AccessController.java b/security-kernel/src/main/java/java/security/AccessController.java
new file mode 100644
index 0000000..c504fc8
--- /dev/null
+++ b/security-kernel/src/main/java/java/security/AccessController.java
@@ -0,0 +1,259 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.WeakHashMap;
+
+import org.apache.harmony.security.fortress.SecurityUtils;
+
+/**
+ * @com.intel.drl.spec_ref
+ */
+public final class AccessController {
+
+ private AccessController() {
+ throw new Error("statics only.");
+ };
+
+ /**
+ * A map used to store a mapping between a given Thread and
+ * AccessControllerContext-s used in successive calls of doPrivileged(). A
+ * WeakHashMap is used to allow automagical wiping of the dead threads from
+ * the map. The thread (normally Thread.currentThread()) is used as a key
+ * for the map, and a value is ArrayList where all AccessControlContext-s are
+ * stored. ((ArrayList)contexts.get(Thread.currentThread())).lastElement() -
+ * is reference to the latest context passed to the doPrivileged() call.
+ */
+ private static final WeakHashMap<Thread, ArrayList<AccessControlContext>>
+ contexts = new WeakHashMap<Thread, ArrayList<AccessControlContext>>();
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static <T> T doPrivileged(PrivilegedAction<T> action) {
+ if (action == null) {
+ throw new NullPointerException("action can not be null");
+ }
+ return doPrivilegedImpl(action, null);
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static <T> T doPrivileged(PrivilegedAction<T> action,
+ AccessControlContext context) {
+ if (action == null) {
+ throw new NullPointerException("action can not be null");
+ }
+ return doPrivilegedImpl(action, context);
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static <T> T doPrivileged(PrivilegedExceptionAction<T> action)
+ throws PrivilegedActionException {
+ if (action == null) {
+ throw new NullPointerException("action can not be null");
+ }
+ return doPrivilegedImpl(action, null);
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static <T> T doPrivileged(PrivilegedExceptionAction<T> action,
+ AccessControlContext context) throws PrivilegedActionException {
+ if (action == null) {
+ throw new NullPointerException("action can not be null");
+ }
+ return doPrivilegedImpl(action, context);
+ }
+
+ /**
+ * The real implementation of doPrivileged() method.<br>
+ * It pushes the passed context into this thread's contexts stack,
+ * and then invokes <code>action.run()</code>.<br>
+ * The pushed context is then investigated in the {@link getContext()}
+ * which is called in the {@link checkPermission}.
+ */
+ private static <T> T doPrivilegedImpl(PrivilegedExceptionAction<T> action,
+ AccessControlContext context) throws PrivilegedActionException {
+
+ Thread currThread = Thread.currentThread();
+
+ ArrayList<AccessControlContext> a = null;
+ try {
+ // currThread==null means that VM warm up is in progress
+ if (currThread != null && contexts != null) {
+ synchronized (contexts) {
+ a = contexts.get(currThread);
+ if (a == null) {
+ a = new ArrayList<AccessControlContext>();
+ contexts.put(currThread, a);
+ }
+ }
+ a.add(context);
+ }
+ return action.run();
+
+ } catch (Exception ex) {
+ // Errors automagically go throught - they are not catched by this
+ // block
+
+ // Unchecked exceptions must pass through without modification
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException) ex;
+ }
+
+ // All other (==checked) exceptions get wrapped
+ throw new PrivilegedActionException(ex);
+ } finally {
+ if (currThread != null) {
+ // No need to sync() here, as each given 'a' will be accessed
+ // only from one Thread. 'contexts' still need sync() however,
+ // as it's accessed from different threads simultaneously
+ if (a != null) {
+ // it seems I will never have here [v.size() == 0]
+ a.remove(a.size() - 1);
+ }
+ }
+ }
+ }
+
+ /**
+ * The real implementation of appropriate doPrivileged() method.<br>
+ * It pushes the passed context into this thread's stack of contexts and
+ * then invokes <code>action.run()</code>.<br>
+ * The pushed context is then investigated in the {@link getContext()}
+ * which is called in the {@link checkPermission}.
+ */
+ private static <T> T doPrivilegedImpl(PrivilegedAction<T> action,
+ AccessControlContext context) {
+
+ Thread currThread = Thread.currentThread();
+
+ if (currThread == null || contexts == null) {
+ // Big boom time - VM is starting... No need to check permissions:
+ // 1st, I do believe there is no malicious code available here for
+ // this moment
+ // 2d, I cant use currentThread() as a key anyway - when it will
+ // turn into the real Thread, I'll be unable to retrieve the value
+ // stored with 'currThread==null' as a key.
+ return action.run();
+ }
+
+ ArrayList<AccessControlContext> a = null;
+ try {
+ synchronized (contexts) {
+ a = contexts.get(currThread);
+ if (a == null) {
+ a = new ArrayList<AccessControlContext>();
+ contexts.put(currThread, a);
+ }
+ }
+ a.add(context);
+
+ return action.run();
+
+ } finally {
+ // No need to sync() here, as each given 'a' will be accessed
+ // only from one Thread. 'contexts' still need sync() however,
+ // as it's accessed from different threads simultaneously
+ if (a != null) {
+ a.remove(a.size() - 1);
+ }
+ }
+ }
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static void checkPermission(Permission perm)
+ throws AccessControlException {
+ if (perm == null) {
+ throw new NullPointerException("permission can not be null");
+ }
+
+ getContext().checkPermission(perm);
+ }
+
+ /**
+ * Returns array of ProtectionDomains from the classes residing
+ * on the stack of the current thread, up to and including the caller
+ * of the nearest privileged frame. Reflection frames are skipped.
+ * The returned array is never null and never contains null elements,
+ * meaning that bootstrap classes are effectively ignored.
+ */
+ private static native ProtectionDomain[] getStackDomains();
+
+ /**
+ * @com.intel.drl.spec_ref
+ */
+ public static AccessControlContext getContext() {
+
+ // duplicates (if any) will be removed in ACC constructor
+ ProtectionDomain[] stack = getStackDomains();
+
+ Thread currThread = Thread.currentThread();
+ if (currThread == null || contexts == null) {
+ // Big boo time. No need to check anything ?
+ return new AccessControlContext(stack);
+ }
+
+ ArrayList<AccessControlContext> threadContexts;
+ synchronized (contexts) {
+ threadContexts = contexts.get(currThread);
+ }
+
+ AccessControlContext that;
+ if ((threadContexts == null) || (threadContexts.size() == 0)) {
+ // We were not in doPrivileged method, so
+ // have inherited context here
+ that = SecurityUtils.getContext(currThread);
+ } else {
+ // We were in doPrivileged method, so
+ // Use context passed to the doPrivileged()
+ that = threadContexts.get(threadContexts.size() - 1);
+ }
+
+ if (that != null && that.combiner != null) {
+ ProtectionDomain[] assigned = null;
+ if (that.context != null && that.context.length != 0) {
+ assigned = new ProtectionDomain[that.context.length];
+ System.arraycopy(that.context, 0, assigned, 0,
+ assigned.length);
+ }
+ ProtectionDomain[] allpds = that.combiner.combine(stack, assigned);
+ if (allpds == null) {
+ allpds = new ProtectionDomain[0];
+ }
+ return new AccessControlContext(allpds, that.combiner);
+ }
+
+ return new AccessControlContext(stack, that);
+ }
+
+ /*
+ * TEMPORARY, used for testing implementation.
+ */
+ //public static ProtectionDomain[] testStackDomains() {
+ // return getStackDomains();
+ //}
+}