* FYI: AccessController.getContext() checks
@ 2006-07-25 16:01 Gary Benson
0 siblings, 0 replies; only message in thread
From: Gary Benson @ 2006-07-25 16:01 UTC (permalink / raw)
To: mauve-patches
[-- Attachment #1: Type: text/plain, Size: 210 bytes --]
Hi all,
This commit adds some basic checks for AccessController.getContext().
I'd like to have made it more complete, but I can't really see how to
and all the reflection is making my head ache.
Cheers,
Gary
[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 8899 bytes --]
Index: ChangeLog
===================================================================
RCS file: /cvs/mauve/mauve/ChangeLog,v
retrieving revision 1.1827
diff -u -r1.1827 ChangeLog
--- ChangeLog 25 Jul 2006 09:23:22 -0000 1.1827
+++ ChangeLog 25 Jul 2006 15:57:37 -0000
@@ -1,3 +1,7 @@
+2006-07-25 Gary Benson <gbenson@redhat.com>
+
+ * gnu/testlet/java/security/AccessController/contexts.java: New test.
+
2006-07-25 David Gilbert <david.gilbert@object-refinery.com>
* gnu/testlet/javax/swing/text/TabSet/constructor.java: New test,
Index: gnu/testlet/java/security/AccessController/contexts.java
===================================================================
RCS file: gnu/testlet/java/security/AccessController/contexts.java
diff -N gnu/testlet/java/security/AccessController/contexts.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gnu/testlet/java/security/AccessController/contexts.java 25 Jul 2006 15:57:37 -0000
@@ -0,0 +1,239 @@
+// Copyright (C) 2006 Red Hat, Inc.
+// Written by Gary Benson <gbenson@redhat.com>
+
+// This file is part of Mauve.
+
+// Mauve 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.
+
+// Mauve 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 Mauve; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+package gnu.testlet.java.security.AccessController;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilePermission;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.ProtectionDomain;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import gnu.testlet.Testlet;
+import gnu.testlet.TestHarness;
+
+// In this test we load three different instances of ourself from
+// three different jarfiles with three different classloaders. Each
+// classloader has a different protection domain in which that
+// classloader's jarfile is readable. Some context-hopping is done,
+// and we determine success by checking our protection domains to see
+// which jarfile read permissions we find.
+
+public class contexts implements Testlet
+{
+ public void test(TestHarness harness)
+ {
+ // The bits where we access protection domains is Classpath-specific.
+ if (System.getProperty("gnu.classpath.version") == null)
+ return;
+
+ File jars[] = new File[] {null, null};
+ try {
+ harness.checkPoint("setup");
+
+ // Make jarfiles containing this class and its dependencies
+ String base = new File(harness.getTempDirectory(), "ac").getPath();
+
+ jars[0] = new File(base + "1.jar");
+ JarOutputStream jos = new JarOutputStream(new FileOutputStream(jars[0]));
+ copyClass(harness.getSourceDirectory(), jos, getClass());
+ copyClass(harness.getSourceDirectory(), jos, TestHarness.class);
+ copyClass(harness.getSourceDirectory(), jos, TestObject.class);
+ jos.close();
+
+ for (int i = 1; i < jars.length; i++) {
+ jars[i] = new File(base + (i + 1) + ".jar");
+ copyFile(jars[0], jars[i]);
+ }
+
+ // Create instances of ourself loaded from different loaders
+ TestObject testObjects[] = new TestObject[jars.length];
+ for (int i = 0; i < jars.length; i++) {
+ Class testClass = new URLClassLoader(new URL[] {
+ jars[i].toURL()}, null).loadClass(getClass().getName());
+ harness.check(
+ getClass().getClassLoader() != testClass.getClassLoader());
+ Constructor c = testClass.getConstructor(new Class[] {String.class});
+ testObjects[i] = new TestObject(c.newInstance(new Object[] {base}));
+ }
+
+ // Run the tests
+ test(harness, testObjects[0], testObjects[1]);
+ }
+ catch (Exception ex) {
+ harness.debug(ex);
+ harness.check(false, "Unexpected exception");
+ }
+ finally {
+ for (int i = 0; i < jars.length; i++) {
+ if (jars[i].exists())
+ jars[i].delete();
+ }
+ }
+ }
+
+ // Copy a classfile and its dependencies into a jarfile
+ private static void copyClass(String srcdir, JarOutputStream jos, Class cls)
+ throws Exception
+ {
+ String relpath = cls.getName().replace(".", File.separator) + ".class";
+
+ File file = new File(srcdir, relpath);
+ if (file.exists()) {
+ byte[] bytes = new byte[(int) file.length()];
+ FileInputStream fis = new FileInputStream(file);
+ fis.read(bytes);
+ fis.close();
+
+ jos.putNextEntry(new JarEntry(relpath));
+ jos.write(bytes, 0, bytes.length);
+ }
+
+ Class superclass = cls.getSuperclass();
+ if (superclass != null)
+ copyClass(srcdir, jos, superclass);
+ Class[] interfaces = cls.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ copyClass(srcdir, jos, interfaces[i]);
+ }
+
+ // Make a copy of a file
+ private static void copyFile(File src, File dst) throws Exception
+ {
+ byte[] bytes = new byte[(int) src.length()];
+ FileInputStream fis = new FileInputStream(src);
+ fis.read(bytes);
+ fis.close();
+
+ FileOutputStream fos = new FileOutputStream(dst);
+ fos.write(bytes);
+ fos.close();
+ }
+
+ // Constructor for the main object that Mauve creates
+ public contexts()
+ {
+ }
+
+ // Constructor for the sub-objects that the main object creates
+ private String base = null;
+ public contexts(String base)
+ {
+ this.base = base;
+ }
+
+ // Wrapper to hide the pain of reflection
+ private static class TestObject
+ {
+ private Object object;
+
+ public TestObject(Object object)
+ {
+ this.object = object;
+ }
+
+ public String[] listJarsOf(TestObject other) throws Exception
+ {
+ Method method = object.getClass().getMethod(
+ "listJarsOf", new Class[] {Object.class});
+ return (String[]) method.invoke(object, new Object[] {other.object});
+ }
+ }
+
+ public String[] listJarsOf(Object object) throws Exception
+ {
+ Method method = object.getClass().getMethod("listJars", new Class[0]);
+ return (String[]) method.invoke(object, new Object[0]);
+ }
+
+ public String[] listJars() throws Exception
+ {
+ AccessControlContext ctx = AccessController.getContext();
+ // XXX start of classpath-specific code
+ Field field = ctx.getClass().getDeclaredField("protectionDomains");
+ field.setAccessible(true);
+ ProtectionDomain[] domains = (ProtectionDomain[]) field.get(ctx);
+ // XXX end of classpath-specific code
+
+ LinkedList jars = new LinkedList();
+ for (int i = 0; i < domains.length; i++) {
+ PermissionCollection perms = domains[i].getPermissions();
+ for (Enumeration e = perms.elements(); e.hasMoreElements() ;) {
+ Permission p = (Permission) e.nextElement();
+ if (!(p instanceof FilePermission))
+ continue;
+ String path = p.getName();
+ if (path.length() == base.length() + 5
+ && path.startsWith(base)
+ && Character.isDigit(path.charAt(base.length()))
+ && path.endsWith(".jar"))
+ jars.add(path);
+ }
+ }
+ return (String[]) jars.toArray(new String[jars.size()]);
+ }
+
+ // Perform the tests
+ private static void test(
+ TestHarness harness, TestObject caller, TestObject callee)
+ throws Exception
+ {
+ // Each object should see only its own jar when listing itself
+ harness.checkPoint("self-listing");
+
+ String[] jars = caller.listJarsOf(caller);
+ harness.check(jars.length == 1);
+ String caller_jar = jars[0];
+
+ jars = callee.listJarsOf(callee);
+ harness.check(jars.length == 1);
+ String callee_jar = jars[0];
+
+ harness.check(!caller_jar.equals(callee_jar));
+
+ // When one object calls another's lister both object's jars
+ // should be visible.
+ harness.checkPoint("straight other-listing");
+
+ jars = caller.listJarsOf(callee);
+ boolean caller_seen = false;
+ boolean callee_seen = false;
+ for (int i = 0; i < jars.length; i++) {
+ if (jars[i].equals(caller_jar))
+ caller_seen = true;
+ else if (jars[i].equals(callee_jar))
+ callee_seen = true;
+ }
+ harness.check(jars.length == 2 && caller_seen && callee_seen);
+ }
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-07-25 16:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-07-25 16:01 FYI: AccessController.getContext() checks Gary Benson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).