summaryrefslogtreecommitdiff
path: root/vm/reference
diff options
context:
space:
mode:
authorMichael Koch <konqueror@gmx.de>2004-06-03 09:16:41 +0000
committerMichael Koch <konqueror@gmx.de>2004-06-03 09:16:41 +0000
commit4e450e3b7e2a0e95162a2c0c02d564796a89bea2 (patch)
tree68d1fd7959d83cb1768230f71017ce23f56ee604 /vm/reference
parentd01086467f65eb260dc22cc622c9c668b6e564fd (diff)
downloadclasspath-4e450e3b7e2a0e95162a2c0c02d564796a89bea2.tar.gz
2004-06-03 Casey Marshall <csm@gnu.org>
* java/security/AccessController.java (doPrivileged(PrivilegedAction,AccessControlContext)): call VMAccessController.pushContext and popContext. (doPrivileged(PrivilegedExceptionAction,AccessControlContext)): likewise. (getContext): call VMAccessController.getContext. * java/security/Makefile.am (EXTRA_DIST): add IntersectingDomainCombiner.java. * gnu/java/security/Makefile.am (EXTRA_DIST): add PolicyFile.java * vm/reference/java/Makefile.am (SUBDIRS): add security. * java/security/IntersectingDomainCombiner.java: new file. * gnu/java/security/PolicyFile.java: new file. * vm/reference/java/security/VMAccessController.java: new file. * vm/reference/java/security/Makefile.am: new file 2004-06-03 Michael Koch <konqerorq@gmx.de> * configure.ac: Added vm/runtime/java/security/Makefile to output files.
Diffstat (limited to 'vm/reference')
-rw-r--r--vm/reference/java/Makefile.am2
-rw-r--r--vm/reference/java/security/Makefile.am5
-rw-r--r--vm/reference/java/security/VMAccessController.java236
3 files changed, 242 insertions, 1 deletions
diff --git a/vm/reference/java/Makefile.am b/vm/reference/java/Makefile.am
index 8c16975d6..e842cd1de 100644
--- a/vm/reference/java/Makefile.am
+++ b/vm/reference/java/Makefile.am
@@ -1,3 +1,3 @@
# used by automake to generate Makefile.in
-SUBDIRS = lang io
+SUBDIRS = lang io security
diff --git a/vm/reference/java/security/Makefile.am b/vm/reference/java/security/Makefile.am
new file mode 100644
index 000000000..468d7cfe0
--- /dev/null
+++ b/vm/reference/java/security/Makefile.am
@@ -0,0 +1,5 @@
+# used by automake to generate Makefile.in
+
+
+EXTRA_DIST = \
+VMAccessController.java
diff --git a/vm/reference/java/security/VMAccessController.java b/vm/reference/java/security/VMAccessController.java
new file mode 100644
index 000000000..a9a580f92
--- /dev/null
+++ b/vm/reference/java/security/VMAccessController.java
@@ -0,0 +1,236 @@
+/* VMAccessController.java -- VM-specific access controller methods.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+final class VMAccessController
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * A mapping between pairs (<i>thread</i>, <i>classname</i>) to access
+ * control contexts. The <i>thread</i> and <i>classname</i> are the thread
+ * and <i>classname</i> current as of the last call to doPrivileged with
+ * an AccessControlContext argument.
+ */
+ private static final Map contexts = Collections.synchronizedMap(new HashMap());
+
+ private static final ThreadLocal inGetContext = new ThreadLocal();
+
+ private final static AccessControlContext DEFAULT_CONTEXT;
+ static
+ {
+ CodeSource source = new CodeSource(null, null);
+ Permissions permissions = new Permissions();
+ permissions.add(new AllPermission());
+ ProtectionDomain[] domain = new ProtectionDomain[] {
+ new ProtectionDomain(source, permissions)
+ };
+ DEFAULT_CONTEXT = new AccessControlContext(domain);
+ }
+
+ private static final boolean DEBUG = false;
+ private static void debug (String msg)
+ {
+ System.err.print (">>> VMAccessController: ");
+ System.err.println (msg);
+ }
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ private VMAccessController() { }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Relate a class (which should be an instance of {@link PrivilegedAction}
+ * with an access control context. This method is used by {@link
+ * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
+ * to set up the context that will be returned by {@link #getContext()}.
+ * This method relates the class to the current thread, so contexts
+ * pushed from one thread will not be available to another.
+ *
+ * @param acc The access control context.
+ * @param clazz The class that implements {@link PrivilegedAction}.
+ */
+ static void pushContext (AccessControlContext acc, Class clazz)
+ {
+ ArrayList pair = new ArrayList (2);
+ pair.add (Thread.currentThread());
+ pair.add (clazz);
+ if (DEBUG) debug ("pushing " + pair);
+ contexts.put (pair, acc);
+ }
+
+ /**
+ * Removes the relation of a class to an {@link AccessControlContext}.
+ * This method is used by {@link AccessController} when exiting from a
+ * call to {@link
+ * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}.
+ *
+ * @param clazz The class that implements {@link PrivilegedAction}.
+ */
+ static void popContext (Class clazz)
+ {
+ ArrayList pair = new ArrayList (2);
+ pair.add (Thread.currentThread());
+ pair.add (clazz);
+ if (DEBUG) debug ("popping " + pair);
+ contexts.remove (pair);
+ }
+
+ /**
+ * Examine the method stack of the currently running thread, and create
+ * an {@link AccessControlContext} filled in with the appropriate {@link
+ * ProtectionDomain} objects given this stack.
+ *
+ * @return The context.
+ */
+ static AccessControlContext getContext()
+ {
+ // If we are already in getContext, but called a method that needs
+ // a permission check, return the all-permissive context so methods
+ // called from here succeed.
+ //
+ // XXX is this necessary? We should verify if there are any calls in
+ // the stack below this method that require permission checks.
+ Boolean inCall = (Boolean) inGetContext.get();
+ if (inCall != null && inCall.booleanValue())
+ {
+ if (DEBUG) debug ("already in getContext");
+ return DEFAULT_CONTEXT;
+ }
+
+ Object[][] stack = getStack();
+ Class[] classes = (Class[]) stack[0];
+ String[] methods = (String[]) stack[1];
+
+ inGetContext.set (Boolean.TRUE);
+
+ if (DEBUG) debug (">>> got trace of length " + classes.length);
+
+ HashSet domains = new HashSet();
+ HashSet seenDomains = new HashSet();
+ AccessControlContext context = null;
+
+ // We walk down the stack, adding each ProtectionDomain for each
+ // class in the call stack. If we reach a call to doPrivileged,
+ // we don't add any more stack frames. We skip the first three stack
+ // frames, since they comprise the calls to getStack, getContext,
+ // and AccessController.getContext.
+ for (int i = 3; i < classes.length; i++)
+ {
+ Class clazz = classes[i];
+ String method = methods[i];
+
+ if (DEBUG) debug (">>> checking " + clazz + "." + method);
+
+ if (DEBUG) debug (">>> loader = " + clazz.getClassLoader());
+
+ if (clazz.equals (AccessController.class)
+ && method.equals ("doPrivileged"))
+ {
+ // If there was a call to doPrivileged with a supplied context,
+ // return that context.
+ List pair = new ArrayList(2);
+ pair.add (Thread.currentThread());
+ pair.add (classes[i-1]);
+ if (contexts.containsKey (pair))
+ context = (AccessControlContext) contexts.get (pair);
+ break;
+ }
+
+ ProtectionDomain domain = clazz.getProtectionDomain();
+
+ if (domain == null)
+ continue;
+ if (seenDomains.contains (domain))
+ continue;
+ seenDomains.add (domain);
+
+ // Create a static snapshot of this domain, which may change over time
+ // if the current policy changes.
+ domains.add (new ProtectionDomain (domain.getCodeSource(),
+ domain.getPermissions()));
+ }
+
+ if (DEBUG) debug ("created domains: " + domains);
+
+ ProtectionDomain[] result = (ProtectionDomain[])
+ domains.toArray (new ProtectionDomain[domains.size()]);
+
+ // Intersect the derived protection domain with the context supplied
+ // to doPrivileged.
+ if (context != null)
+ context = new AccessControlContext (result, context,
+ IntersectingDomainCombiner.SINGLETON);
+ // No context was supplied. Return the derived one.
+ else
+ context = new AccessControlContext (result);
+
+ inGetContext.set (Boolean.FALSE);
+ return context;
+ }
+
+ /**
+ * Returns a snapshot of the current call stack as a pair of arrays:
+ * the first an array of classes in the call stack, the second an array
+ * of strings containing the method names in the call stack. The two
+ * arrays match up, meaning that method <i>i</i> is declared in class
+ * <i>i</i>. The arrays are clean; it will only contain Java methods,
+ * and no element of the list should be null.
+ *
+ * <p>XXX note: this interface (VMAccessController) would possibly be
+ * cleaner if we had a method similar to this, but returned an array
+ * of java.lang.reflect.Method objects. Then, instead of having this
+ * much logic in this class, we put everything in AccessController,
+ * and simply have this single getStack method for a VM to implement.
+ */
+ private static native Object[][] getStack();
+}