diff options
27 files changed, 4260 insertions, 9 deletions
diff --git a/java/jdk14/Makefile b/java/jdk14/Makefile index 6ab93e3cb8e4..169a67f7b96d 100644 --- a/java/jdk14/Makefile +++ b/java/jdk14/Makefile @@ -7,7 +7,7 @@ PORTNAME= jdk PORTVERSION= ${JDK_VERSION}p${JDK_PATCHSET_VERSION} -PORTREVISION= 6 +PORTREVISION= 7 CATEGORIES= java devel MASTER_SITES= # http://www.sun.com/software/java2/download.html # http://www.eyesbeyond.com/freebsddom/java/jdk14.html @@ -99,8 +99,6 @@ MAKE_ENV= ALT_BOOTDIR="${JDK14DIR}" \ .if defined(MINIMAL) MAKE_ENV+= NO_PLUGIN="YES" \ NO_JAVAWS="YES" -.else -FORBIDDEN= Vulnerabilities in the browser plugin .endif ALL_TARGET= all PLIST_SUB+= JDK_VERSION=${JDK_VERSION} diff --git a/java/jdk14/files/patch-javascript_JSClassLoader.java b/java/jdk14/files/patch-javascript_JSClassLoader.java new file mode 100644 index 000000000000..1e3a9ad3080b --- /dev/null +++ b/java/jdk14/files/patch-javascript_JSClassLoader.java @@ -0,0 +1,243 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSClassLoader.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSClassLoader.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,238 @@ ++/* ++ * @(#)JSClassLoader.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++ ++package sun.plugin.javascript; ++ ++import java.security.AllPermission; ++import java.security.AccessController; ++import java.security.PermissionCollection; ++import java.security.SecureClassLoader; ++import java.security.PrivilegedExceptionAction; ++import java.security.CodeSource; ++import java.io.InputStream; ++import java.io.BufferedInputStream; ++import java.io.IOException; ++import java.net.URL; ++import java.net.URLConnection; ++import java.net.HttpURLConnection; ++import java.lang.reflect.Method; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.AccessibleObject; ++import sun.net.www.ParseUtil; ++import sun.security.util.SecurityConstants; ++ ++/* ++ * Create a trampoline class for JavaScript to Java ++ * method invocations. ++ * ++ */ ++public final class JSClassLoader extends SecureClassLoader { ++ private static String JS_PROXY_PKG = "sun.plugin.javascript.invoke."; ++ private static String TRAMPOLINE = JS_PROXY_PKG + "JSInvoke"; ++ private static Method bounce; ++ ++ /* ++ * Bounce through the trampoline. ++ */ ++ public static Object invoke(Method m, Object obj, Object[] params) ++ throws Exception { ++ try { ++ return bounce().invoke(null, new Object[] {m, obj, params}); ++ } catch (InvocationTargetException ie) { ++ Throwable t = ie.getCause(); ++ ++ if (t instanceof InvocationTargetException) { ++ throw (InvocationTargetException)t; ++ } else { ++ throw ie; ++ } ++ } ++ } ++ ++ /** ++ * Check the package access permission by giving a class ++ * ++ * @param clazz: The Class object trying to get access to ++ * ++ */ ++ public static void checkPackageAccess(Class clazz) { ++ String clsname = clazz.getName(); ++ int index = clsname.lastIndexOf("."); ++ if (index != -1) { ++ String pkgname = clsname.substring(0, index); ++ SecurityManager s = System.getSecurityManager(); ++ if (s != null) { ++ s.checkPackageAccess(pkgname); ++ } ++ } ++ } ++ ++ public static boolean isPackageAccessible(Class clazz) { ++ try { ++ checkPackageAccess(clazz); ++ } catch (SecurityException e) { ++ return false; ++ } ++ return true; ++ } ++ ++ ++ private synchronized static Method bounce() throws Exception { ++ if (bounce == null) { ++ bounce = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { ++ public Object run() throws Exception { ++ Class[] types; ++ Class t = getTrampoline(); ++ Method b; ++ ++ types = new Class[] {Method.class, Object.class, Object[].class}; ++ b = t.getDeclaredMethod("invoke", types); ++ ((AccessibleObject)b).setAccessible(true); ++ return b; ++ } ++ }); ++ } ++ return bounce; ++ } ++ ++ private static Class getTrampoline() { ++ try { ++ return Class.forName(TRAMPOLINE, true, new JSClassLoader()); ++ } catch (ClassNotFoundException e) { ++ } ++ return null; ++ } ++ ++ ++ protected synchronized Class loadClass(String name, boolean resolve) ++ throws ClassNotFoundException ++ { ++ SecurityManager s = System.getSecurityManager(); ++ if (s != null) { ++ String cname = name.replace('/', '.'); ++ if (cname.startsWith("[")) { ++ int b = cname.lastIndexOf('[') + 2; ++ if (b > 1 && b < cname.length()) { ++ cname = cname.substring(b); ++ } ++ } ++ int i = cname.lastIndexOf('.'); ++ if (i != -1) { ++ s.checkPackageAccess(cname.substring(0, i)); ++ } ++ } ++ // First, check if the class has already been loaded ++ Class c = findLoadedClass(name); ++ if (c == null) { ++ try { ++ c = findClass(name); ++ } catch (ClassNotFoundException e) { ++ // Fall through ... ++ } ++ if (c == null) { ++ c = getParent().loadClass(name); ++ } ++ } ++ if (resolve) { ++ resolveClass(c); ++ } ++ return c; ++ } ++ ++ ++ protected Class findClass(final String name) ++ throws ClassNotFoundException ++ { ++ if (!name.startsWith(JS_PROXY_PKG)) { ++ throw new ClassNotFoundException(name); ++ } ++ String path = name.replace('.', '/').concat(".class"); ++ URL res = getResource(path); ++ if (res != null) { ++ try { ++ return defineClass(name, res); ++ } catch (IOException e) { ++ throw new ClassNotFoundException(name, e); ++ } ++ } else { ++ throw new ClassNotFoundException(name); ++ } ++ } ++ ++ ++ /* ++ * Define the JavaScript proxy classes ++ */ ++ private Class defineClass(String name, URL url) throws IOException { ++ byte[] b = getBytes(url); ++ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null); ++ if (!name.equals(TRAMPOLINE)) { ++ throw new IOException("JSClassLoader: bad name " + name); ++ } ++ return defineClass(name, b, 0, b.length, cs); ++ } ++ ++ ++ /* ++ * Returns the contents of the specified URL as an array of bytes. ++ */ ++ private static byte[] getBytes(URL url) throws IOException { ++ URLConnection uc = url.openConnection(); ++ if (uc instanceof java.net.HttpURLConnection) { ++ java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc; ++ int code = huc.getResponseCode(); ++ if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) { ++ throw new IOException("open HTTP connection failed."); ++ } ++ } ++ int len = uc.getContentLength(); ++ InputStream in = new BufferedInputStream(uc.getInputStream()); ++ ++ byte[] b; ++ try { ++ if (len != -1) { ++ // Read exactly len bytes from the input stream ++ b = new byte[len]; ++ while (len > 0) { ++ int n = in.read(b, b.length - len, len); ++ if (n == -1) { ++ throw new IOException("unexpected EOF"); ++ } ++ len -= n; ++ } ++ } else { ++ b = new byte[8192]; ++ int total = 0; ++ while ((len = in.read(b, total, b.length - total)) != -1) { ++ total += len; ++ if (total >= b.length) { ++ byte[] tmp = new byte[total * 2]; ++ System.arraycopy(b, 0, tmp, 0, total); ++ b = tmp; ++ } ++ } ++ // Trim array to correct size, if necessary ++ if (total != b.length) { ++ byte[] tmp = new byte[total]; ++ System.arraycopy(b, 0, tmp, 0, total); ++ b = tmp; ++ } ++ } ++ } finally { ++ in.close(); ++ } ++ return b; ++ } ++ ++ ++ protected PermissionCollection getPermissions(CodeSource codesource) ++ { ++ PermissionCollection perms = super.getPermissions(codesource); ++ perms.add(new AllPermission()); ++ return perms; ++ } ++} diff --git a/java/jdk14/files/patch-javascript_JSInvoke.java b/java/jdk14/files/patch-javascript_JSInvoke.java new file mode 100644 index 000000000000..fc692b9cb9c1 --- /dev/null +++ b/java/jdk14/files/patch-javascript_JSInvoke.java @@ -0,0 +1,26 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSInvoke.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSInvoke.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,21 @@ ++/* ++ * @(#)JSInvoke.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++ ++package sun.plugin.javascript.invoke; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.InvocationTargetException; ++ ++/* ++ * JavaScript to Java invocation trampoline class. ++ */ ++class JSInvoke { ++ private static Object invoke(Method m, Object obj, Object[] params) ++ throws InvocationTargetException, IllegalAccessException { ++ return m.invoke(obj, params); ++ } ++} diff --git a/java/jdk14/files/patch-javascript_ReflectUtil.java b/java/jdk14/files/patch-javascript_ReflectUtil.java new file mode 100644 index 000000000000..827bd0c666ce --- /dev/null +++ b/java/jdk14/files/patch-javascript_ReflectUtil.java @@ -0,0 +1,312 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,307 @@ ++/* ++ * @(#)ReflectUtil.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++package sun.plugin.javascript; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.lang.reflect.InvocationTargetException; ++import java.util.HashMap; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Iterator; ++import sun.plugin.javascript.JSClassLoader; ++ ++public class ReflectUtil { ++ /* ++ * Discover the public methods on public classes ++ * and interfaces accessible to the calling ++ * JavaScript code. ++ */ ++ public static Method[] getJScriptMethods(Class cls) { ++ List m = new ArrayList(); /* the valid methods we find */ ++ ++ /* ++ * Temporary map of method signatures when we decide ++ * that a simple call to target.getMethods() returns ++ * inaccessible methods and we must search for alternative ++ * supermethods that might be accessible. We can toss ++ * this when we're done searching. ++ */ ++ Map sigs = new HashMap(); ++ ++ while (cls != null) { ++ boolean done = getPublicMethods(cls, m, sigs); ++ if (done) { ++ break; ++ } ++ getJScriptInterfaceMethods(cls, m, sigs); ++ cls = cls.getSuperclass(); ++ } ++ return (Method[]) m.toArray(new Method[m.size()]); ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ private static void getJScriptInterfaceMethods(Class cls, List m, Map sigs) { ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length; i++) { ++ Class intf = intfs[i]; ++ boolean done = getPublicMethods(intf, m, sigs); ++ if (!done) { ++ getJScriptInterfaceMethods(intf, m, sigs); ++ } ++ } ++ } ++ ++ /* ++ * ++ * Process the methods in this class or interface ++ */ ++ private static boolean getPublicMethods(Class cls, List m, Map sigs) { ++ Method[] methods = null; ++ try { ++ ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's methods. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return false; ++ } ++ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return false; ++ } ++ ++ methods = cls.getMethods(); ++ } catch (SecurityException se) { ++ return false; ++ } ++ ++ /* ++ * Check for inherited methods with non-public ++ * declaring classes. They might override and hide ++ * methods from their superclasses or ++ * superinterfaces. ++ */ ++ boolean done = true; ++ for (int i=0; i < methods.length; i++) { ++ Class dc = methods[i].getDeclaringClass(); ++ if (!Modifier.isPublic(dc.getModifiers())) { ++ done = false; ++ break; ++ } ++ } ++ ++ /* ++ * Belatedly initialize the signature map if ++ * this is not the first time here. ++ */ ++ if (sigs.isEmpty() && !m.isEmpty()) { ++ initSignatureMap(m, sigs); ++ } ++ ++ if (done) { ++ /* ++ * We're done. Spray all the methods into ++ * the list and then we're out of here. ++ */ ++ for (int i=0; i < methods.length; i++) { ++ addMethod(m, sigs, methods[i]); ++ } ++ } else { ++ /* ++ * Simulate cls.getDeclaredMethods() by ++ * stripping away inherited methods. ++ */ ++ for (int i=0; i < methods.length; i++) { ++ Class dc = methods[i].getDeclaringClass(); ++ if (cls.equals(dc)) { ++ addMethod(m, sigs, methods[i]); ++ } ++ } ++ } ++ return done; ++ } ++ ++ private static void initSignatureMap(List m, Map sigs) { ++ Iterator i = m.iterator(); ++ while (i.hasNext()) { ++ Method entry = (Method) i.next(); ++ sigs.put(getSignature(entry), entry); ++ } ++ } ++ ++ private static void addMethod(List m, Map sigs, Method method) { ++ /* ++ * Avoid work. We ignore the signature matching ++ * until the map is initialized in initSignatureMap. ++ * This has the effect of avoiding the signature ++ * work for the first call of getPublicMethods(). ++ */ ++ if (sigs.isEmpty()) { ++ m.add(method); ++ return; ++ } ++ ++ /* ++ * Avoid adding duplicate accessible methods on ++ * the list. ++ */ ++ String signature = getSignature(method); ++ if (!sigs.containsKey(signature)) { ++ m.add(method); ++ sigs.put(signature, method); ++ } ++ } ++ ++ /* ++ * Return a canonical method signature for the method. ++ * We care only about the simple method name and the ++ * the number, type and order of the parameters. ++ * Exception declarations are not part of a method ++ * signature nor is the return type. ++ */ ++ private static String getSignature(Method method) { ++ StringBuffer sb = new StringBuffer(); ++ ++ sb.append(method.getName()); ++ Class[] params = method.getParameterTypes(); ++ sb.append('('); ++ if (params.length > 0) { ++ sb.append(params[0].getName()); ++ } ++ for (int i=1; i < params.length; i++) { ++ sb.append(','); ++ sb.append(params[i].getName()); ++ } ++ sb.append(')'); ++ ++ return sb.toString(); ++ } ++ ++ /* ++ * Discover the public fields on public classes ++ * and interfaces accessible to the calling ++ * JavaScript code. ++ */ ++ public static Field[] getJScriptFields(Class cls) { ++ List m = new ArrayList(); /* the valid fields we find */ ++ ++ /* ++ * Temporary map of field name when we decide ++ * that a simple call to target.getFields() returns ++ * inaccessible fields and we must search for alternative ++ * supermethods that might be accessible. We can toss ++ * this when we're done searching. ++ */ ++ Map names = new HashMap(); ++ ++ while (cls != null) { ++ boolean done = getPublicFields(cls, m, names); ++ if (done) { ++ break; ++ } ++ getJScriptInterfaceFields(cls, m, names); ++ cls = cls.getSuperclass(); ++ } ++ return (Field[]) m.toArray(new Field[m.size()]); ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ private static void getJScriptInterfaceFields(Class cls, List m, Map names) { ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length; i++) { ++ Class intf = intfs[i]; ++ boolean done = getPublicFields(intf, m, names); ++ if (!done) { ++ getJScriptInterfaceFields(intf, m, names); ++ } ++ } ++ } ++ ++ /* ++ * ++ * Process the fields in this class or interface ++ */ ++ private static boolean getPublicFields(Class cls, List m, Map names) { ++ Field[] fields = null; ++ try { ++ ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's fields. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return false; ++ } ++ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return false; ++ } ++ fields = cls.getFields(); ++ } catch (SecurityException se) { ++ return false; ++ } ++ ++ /* ++ * Check for inherited fields with non-public ++ * declaring classes. They might hide ++ * fields from public classes or interfaces. ++ */ ++ boolean done = true; ++ for (int i=0; i < fields.length; i++) { ++ Class dc = fields[i].getDeclaringClass(); ++ if (!Modifier.isPublic(dc.getModifiers())) { ++ done = false; ++ break; ++ } ++ } ++ if (done) { ++ /* ++ * We're done. Spray all the fields into ++ * the list and then we're out of here. ++ */ ++ for (int i=0; i < fields.length; i++) { ++ addField(m, names, fields[i]); ++ } ++ } else { ++ /* ++ * Simulate cls.getDeclaredFields() by ++ * stripping away inherited fields. ++ */ ++ for (int i=0; i < fields.length; i++) { ++ Class dc = fields[i].getDeclaringClass(); ++ if (cls.equals(dc)) { ++ addField(m, names, fields[i]); ++ } ++ } ++ } ++ return done; ++ } ++ ++ private static void addField(List m, Map names, Field field) { ++ /* ++ * Avoid adding duplicate accessible fields on ++ * the list. ++ */ ++ String name = field.getName(); ++ if (!names.containsKey(name)) { ++ m.add(field); ++ names.put(name, field); ++ } ++ } ++} ++ ++ diff --git a/java/jdk14/files/patch-liveconnect_ReplaceMethod.java b/java/jdk14/files/patch-liveconnect_ReplaceMethod.java new file mode 100644 index 000000000000..829e43452e6c --- /dev/null +++ b/java/jdk14/files/patch-liveconnect_ReplaceMethod.java @@ -0,0 +1,93 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/ReplaceMethod.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/ReplaceMethod.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,88 @@ ++/* ++ * @(#)ReplaceMethod.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++package sun.plugin.liveconnect; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import sun.plugin.javascript.JSClassLoader; ++ ++public class ReplaceMethod { ++ /* ++ * Replace the inaccessible method by a suitable method on public ++ * class/interface accessible to the calling JavaScript code. ++ * Returns null if accessible method is not found. ++ */ ++ static Method getJScriptMethod(Method start) { ++ Class cls = start.getDeclaringClass(); ++ ++ if (Modifier.isPublic(cls.getModifiers())) { ++ return start; ++ } ++ ++ String name = start.getName(); ++ Class[] params = start.getParameterTypes(); ++ ++ Method result = null; ++ while (cls != null && result == null) { ++ result = getPublicMethod(cls, name, params); ++ if (result == null) { ++ result = getJScriptInterfaceMethod(cls, name, params); ++ } ++ cls = cls.getSuperclass(); ++ } ++ return result; ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ static Method getJScriptInterfaceMethod(Class cls, String name, Class[] params) { ++ Method result = null; ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length && result == null; i++) { ++ Class intf = intfs[i]; ++ result = getPublicMethod(intf, name, params); ++ if (result == null) { ++ result = getJScriptInterfaceMethod(intf, name, params); ++ } ++ } ++ return result; ++ } ++ ++ /* ++ * ++ * Process the methods in this class or interface ++ */ ++ static private Method getPublicMethod(Class cls, String name, Class[] params) { ++ try { ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's methods. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return null; ++ } ++ ++ /* ++ * This call will fail if 'cls' is in a restricted ++ * package and we don't have permission to access ++ * it. ++ */ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return null; ++ } ++ return cls.getMethod(name, params); ++ } catch (NoSuchMethodException nsme) { ++ return null; ++ } catch (SecurityException se) { ++ return null; ++ } ++ } ++} ++ ++ diff --git a/java/jdk14/files/patch-liveconnect_SecureInvocation.java b/java/jdk14/files/patch-liveconnect_SecureInvocation.java new file mode 100644 index 000000000000..961414277909 --- /dev/null +++ b/java/jdk14/files/patch-liveconnect_SecureInvocation.java @@ -0,0 +1,351 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/SecureInvocation.java 22 Oct 2003 23:04:21 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/SecureInvocation.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* + * @(#)SecureInvocation.java 1.21 02/08/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,7 +9,8 @@ + + import java.lang.reflect.Constructor; + import java.lang.reflect.Field; +-import java.lang.reflect.Method;
++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; + import java.lang.Thread; + import java.io.FilePermission; + import java.security.AccessControlContext; +@@ -29,7 +30,10 @@ + import java.net.URL; + import java.net.MalformedURLException; + import sun.plugin.util.Trace; +-import sun.plugin.services.PlatformService;
++import sun.plugin.services.PlatformService; ++import sun.plugin.javascript.JSClassLoader; ++import sun.plugin.javascript.ReflectUtil; ++ + + /** + * <P> SecureInvocation is for implementating nsISecureJNI which allows +@@ -98,64 +102,64 @@ + throw e; + } + } +-
+- static class CallMethodThread extends Thread {
+- public CallMethodThread(int handle, Class clazz, Object obj, Method method, Object[] args,
+- String origin, boolean isUniversalBrowserRead,
+- boolean isUniversalJavaPermission) {
+- this.handle = handle;
+- this.clazz = clazz;
+- this.obj = obj;
+- this.method = method;
+- this.args = args;
+- this.origin = origin;
+- this.isUniversalBrowserRead = isUniversalBrowserRead;
+- this.isUniversalJavaPermission = isUniversalJavaPermission;
+- }
+-
+- public void run() {
+- try {
+- result = CallMethod(clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission);
+- }
+- catch(Exception e) {
+- exception = e;
+- }
+- finally {
+- PlatformService.getService().signalEvent(handle);
+- }
+- }
+-
+-
+- public Object getResult() throws Exception {
+- if(exception != null)
+- throw exception;
+- return result;
+- }
+-
+- private Exception exception = null;
+- private Object result = null;
+-
+- private int handle;
+- private Class clazz;
+- private Object obj;
+- private Method method;
+- private Object[] args;
+- private String origin;
+- private boolean isUniversalBrowserRead;
+- private boolean isUniversalJavaPermission;
+-
+- }
+- +- public static Object CallMethod(final int handle, final Class clazz, final Object obj, final Method method, final Object[] args,
+- final String origin, final boolean isUniversalBrowserRead,
+- final boolean isUniversalJavaPermission)
+- throws Exception {
+- CallMethodThread callThread = new CallMethodThread(handle, clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission);
+- callThread.start();
+- PlatformService.getService().waitEvent(handle);
+- return callThread.getResult();
+- }
+-
++ ++ static class CallMethodThread extends Thread { ++ public CallMethodThread(int handle, Class clazz, Object obj, Method method, Object[] args, ++ String origin, boolean isUniversalBrowserRead, ++ boolean isUniversalJavaPermission) { ++ this.handle = handle; ++ this.clazz = clazz; ++ this.obj = obj; ++ this.method = method; ++ this.args = args; ++ this.origin = origin; ++ this.isUniversalBrowserRead = isUniversalBrowserRead; ++ this.isUniversalJavaPermission = isUniversalJavaPermission; ++ } ++ ++ public void run() { ++ try { ++ result = CallMethod(clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission); ++ } ++ catch(Exception e) { ++ exception = e; ++ } ++ finally { ++ PlatformService.getService().signalEvent(handle); ++ } ++ } ++ ++ ++ public Object getResult() throws Exception { ++ if(exception != null) ++ throw exception; ++ return result; ++ } ++ ++ private Exception exception = null; ++ private Object result = null; ++ ++ private int handle; ++ private Class clazz; ++ private Object obj; ++ private Method method; ++ private Object[] args; ++ private String origin; ++ private boolean isUniversalBrowserRead; ++ private boolean isUniversalJavaPermission; ++ ++ } ++ ++ public static Object CallMethod(final int handle, final Class clazz, final Object obj, final Method method, final Object[] args, ++ final String origin, final boolean isUniversalBrowserRead, ++ final boolean isUniversalJavaPermission) ++ throws Exception { ++ CallMethodThread callThread = new CallMethodThread(handle, clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission); ++ callThread.start(); ++ PlatformService.getService().waitEvent(handle); ++ return callThread.getResult(); ++ } ++ + + /** + * <P> Call a method on Java object with security context. +@@ -197,8 +201,8 @@ + AccessControlContext context = new AccessControlContext(domains); + + // Perform the method invocation. +- return AccessController.doPrivileged(new PrivilegedCallMethodAction(method, obj, args), +- context); ++ return AccessController.doPrivileged(new PrivilegedCallMethodAction(method, ++ obj, args), context); + } catch (Exception e) { + Trace.liveConnectPrintException(e); + throw e; +@@ -323,32 +327,6 @@ + } + } + +- +- /** +- * <P> Set up a protection domain according to the origin and +- * the other security related information. +- */ +- private static ProtectionDomain getProtectionDomain(Class clazz, +- String origin, +- boolean byPassOrigin, +- boolean allPermission) +- throws OriginNotAllowedException, MalformedURLException +- { +- boolean trust = false; +- +- // First, check if the call is allowed +- checkLiveConnectCaller(clazz, origin, byPassOrigin); +- +- if (allPermission) +- { +- return getTrustedProtectionDomain(); +- } +- else +- { +- return getDefaultProtectionDomain(origin); +- } +- } +- + /** + * <P> Check if LiveConnect call is allowed at all. + * </P> +@@ -447,7 +425,7 @@ + + // Obtain Java policy + Policy policy = Policy.getPolicy(); +- CodeSource cs = new CodeSource(url, null); ++ CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null); + final PermissionCollection pc = policy.getPermissions(cs); + + if (url == null || url.getProtocol().equals("file")) { +@@ -516,16 +494,19 @@ + + PrivilegedConstructObjectAction(Constructor constructor, Object[] args) + { +- this.constructor = constructor; +- this.args = args; ++ this.constructor = constructor; ++ this.args = args; + +- // Ensure the argument is not null +- if (this.args == null) +- this.args = new Object[0]; ++ // Ensure the argument is not null ++ if (this.args == null) ++ this.args = new Object[0]; + } + + public Object run() throws Exception { +- return constructor.newInstance(args); ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(constructor.getDeclaringClass()); ++ ++ return constructor.newInstance(args); + } + } + +@@ -543,17 +524,54 @@ + + PrivilegedCallMethodAction(Method method, Object obj, Object[] args) + { +- this.method = method; +- this.obj = obj; +- this.args = args; +- +- // Ensure the argument is not null +- if (this.args == null) +- this.args = new Object[0]; ++ this.method = method; ++ ++ this.obj = obj; ++ this.args = args; ++ ++ // Ensure the argument is not null ++ if (this.args == null) ++ this.args = new Object[0]; + } + + public Object run() throws Exception { +- return method.invoke(obj, args); ++ /* ++ * Browser uses reflection to collect methods/fields/constructors ++ * through this method call. Therefore JSClassLoader is not used ++ * in such cases. However it requires filtering to avoid exposing ++ * inaccessible methods/fields/constructors. ++ * ++ * Also, Mozilla ignores abstract methods, therefore those are ++ * replaced by the concrete class methods ++ */ ++ if(obj instanceof Class) { ++ String name = method.getName(); ++ Class cls = (Class)obj; ++ if(name.equals("getMethods")) { ++ Method[] methods = ReflectUtil.getJScriptMethods(cls); ++ for (int i=0; i < methods.length; i++) { ++ Method m = methods[i]; ++ if (Modifier.isAbstract(m.getModifiers())) { ++ Class[] params = m.getParameterTypes(); ++ methods[i] = cls.getMethod(m.getName(), params); ++ } ++ } ++ return methods; ++ }else if (name.equals("getFields")) { ++ return ReflectUtil.getJScriptFields(cls); ++ }else if (name.equals("getConstructors")) { ++ if (!Modifier.isPublic(cls.getModifiers()) || ++ !JSClassLoader.isPackageAccessible(cls)) { ++ return new Constructor[0]; ++ } ++ } ++ } ++ ++ Method actualMethod = ReplaceMethod.getJScriptMethod(method); ++ if(actualMethod != null) ++ return JSClassLoader.invoke(actualMethod, obj, args); ++ else ++ throw new NoSuchMethodException(method.getName()); + } + } + +@@ -564,18 +582,20 @@ + * </P> + */ + class PrivilegedGetFieldAction implements PrivilegedExceptionAction { +- + Field field; + Object obj; + + PrivilegedGetFieldAction(Field field, Object obj) + { +- this.field = field; +- this.obj = obj; ++ this.field = field; ++ this.obj = obj; + } + +- public Object run() throws Exception { +- return field.get(obj); ++ public Object run() throws Exception { ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(field.getDeclaringClass()); ++ ++ return field.get(obj); + } + } + +@@ -593,15 +613,18 @@ + + PrivilegedSetFieldAction(Field field, Object obj, Object val) + { +- this.field = field; +- this.obj = obj; +- this.val = val; ++ this.field = field; ++ this.obj = obj; ++ this.val = val; + } + + public Object run() throws Exception { +- field.set(obj, val); ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(field.getDeclaringClass()); ++ ++ field.set(obj, val); + return null; + } + } +-
+-
++ ++ diff --git a/java/jdk14/files/patch-plugin_DispatchImpl.java b/java/jdk14/files/patch-plugin_DispatchImpl.java new file mode 100644 index 000000000000..abb65a60953e --- /dev/null +++ b/java/jdk14/files/patch-plugin_DispatchImpl.java @@ -0,0 +1,331 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/com/DispatchImpl.java 22 Oct 2003 23:04:20 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/com/DispatchImpl.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* +- * @(#)DispatchImpl.java 1.6 03/01/23 ++ * @(#)DispatchImpl.java 1.16 04/06/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,8 +9,32 @@ + + import sun.plugin.util.Trace; + import sun.plugin.javascript.ocx.JSObject; +-import java.applet.Applet; ++import sun.plugin.liveconnect.JavaScriptProtectionDomain; + import sun.plugin.viewer.context.IExplorerAppletContext; ++import sun.plugin.security.PluginClassLoader; ++import java.applet.Applet; ++import java.net.URL; ++import java.net.MalformedURLException; ++import java.net.InetAddress; ++import java.net.UnknownHostException; ++import java.net.SocketPermission; ++import java.io.FilePermission; ++import java.io.File; ++import java.security.AccessControlContext; ++import java.security.AccessController; ++import java.security.CodeSource; ++import java.security.Policy; ++import java.security.ProtectionDomain; ++import java.security.AllPermission; ++import java.security.Permissions; ++import java.security.Permission; ++import java.security.PermissionCollection; ++import java.security.PrivilegedAction; ++import java.security.PrivilegedExceptionAction; ++import java.security.AccessControlException; ++import java.security.PrivilegedActionException; ++import sun.net.www.ParseUtil; ++import sun.security.util.SecurityConstants; + + /** + * DispatchImpl encapsulates a Java Object and provides Dispatch interface +@@ -22,14 +46,19 @@ + { + JavaClass targetClass = null; + Object targetObj = null; ++ int handle = 0; ++ int wndHandle = 0; ++ AccessControlContext context = null; ++ boolean isBridge = false; + + /* + * Constructor + * @param obj the object to be wrapped + */ +- public DispatchImpl(Object obj) ++ public DispatchImpl(Object obj, int id) + { + targetObj = obj; ++ handle = id; + } + + /** +@@ -40,19 +69,87 @@ + * @param params Arguments. + * @return Java object. + */ +- public Object invoke(int flag, int index, Object []params) ++ public Object invoke(final int flag, final int index, final Object []params) ++ throws Exception ++ { ++ try { ++ //No security constraints in case of ActiveX bridge application ++ if(isBridge) ++ return invokeImpl(flag, index, params); ++ ++ if(context == null) { ++ context = createContext(); ++ } ++ ++ // Invoke the method within the applet sand box security restricitions ++ return AccessController.doPrivileged( ++ new PrivilegedExceptionAction() { ++ public Object run() throws Exception{ ++ return invokeImpl(flag, index, params); ++ } ++ }, context ++ ); ++ }catch(Exception exc) { ++ Throwable cause = exc.getCause(); ++ if(cause == null) { ++ cause = exc; ++ } ++ ++ Trace.liveConnectPrintException(cause); ++ throw new Exception(cause.toString()); ++ } ++ } ++ ++ public AccessControlContext createContext() { ++ try { ++ ProtectionDomain[] domains = new ProtectionDomain[1]; ++ //Obtain the java code origin ++ ProtectionDomain pd = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ return targetObj.getClass().getProtectionDomain(); ++ } ++ }); ++ ++ CodeSource cs = null; ++ URL url = null; ++ if(pd != null) ++ cs = pd.getCodeSource(); ++ if(cs != null) ++ url = cs.getLocation(); ++ ++ domains[0] = getJSProtectionDomain(url, targetObj.getClass()); ++ return new AccessControlContext(domains); ++ }catch(Exception exc) { ++ Trace.liveConnectPrintException(exc); ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Invoke a method according to the method index. ++ * ++ * @param flag Invoke flag ++ * @param index Method index ++ * @param params Arguments. ++ * @return Java object. ++ */ ++ public Object invokeImpl(int flag, int index, Object []params) + throws Exception + { + Object retObj = null; + Dispatcher disp = null; + try { +- convertParams(params); ++ if(params != null) ++ convertParams(params); + disp = targetClass.getDispatcher(flag, index, params); +- return disp.invoke(targetObj, params); +- } +- catch (Throwable e) +- { +- //e.printStackTrace(); ++ if(disp != null) { ++ retObj = disp.invoke(targetObj, params); ++ if(retObj != null) ++ retObj = Utils.convertReturn(disp.getReturnType(), retObj, handle); ++ } ++ return retObj; ++ } catch (Throwable e) { + Throwable cause = e.getCause(); + if(cause == null) { + cause = e; +@@ -82,11 +179,39 @@ + return targetClass; + } + ++ public int getReturnType(int id){ ++ return targetClass.getReturnType(id); ++ } ++ ++ public int getIdForName(final String name) throws Exception{ ++ try { ++ //No security constraints in case of ActiveX bridge application ++ if(isBridge) ++ return getIdForNameImpl(name); ++ ++ if(context == null) { ++ context = createContext(); ++ } ++ ++ // Invoke the method within the applet sand box security restricitions ++ Integer retVal = (Integer)AccessController.doPrivileged( ++ new PrivilegedExceptionAction() { ++ public Object run() throws Exception{ ++ return new Integer(getIdForNameImpl(name)); ++ } ++ }, context ++ ); ++ return retVal.intValue(); ++ }catch(PrivilegedActionException pe) { ++ } ++ ++ return -1; ++ } + + /* + * + */ +- public int getIdForName(String name) throws Exception{ ++ public int getIdForNameImpl(String name) throws Exception{ + int id = -1; + + if(targetClass == null && targetObj != null) { +@@ -103,27 +228,122 @@ + } + + /* +- * ++ * Unwraps the wrapped java object arguments + */ + private void convertParams(Object []params) { + for(int i=0;i<params.length;i++) { + if(params[i] != null && params[i] instanceof DispatchImpl) { + params[i] = ((DispatchImpl)params[i]).getWrappedObject(); + } else if(params[i] != null && params[i] instanceof DispatchClient){ +- JSObject jsObj = new JSObject((DispatchClient)params[i]); +- jsObj.setIExplorerAppletContext((IExplorerAppletContext) ++ JSObject jsObj = null; ++ if (!isBridge) { ++ jsObj = new JSObject((DispatchClient)params[i]); ++ jsObj.setIExplorerAppletContext((IExplorerAppletContext) + ((Applet)targetObj).getAppletContext()); ++ } else { ++ jsObj = new JSObject((DispatchClient)params[i], handle); ++ } + params[i] = jsObj; + } + } + } + ++ /** ++ * Returns a protection domain that represents the default permission ++ * for a given URL. ++ * ++ * @param urlString URL ++ * @return protection domain. ++ */ ++ public static ProtectionDomain getJSProtectionDomain(URL url, Class clazz) ++ throws MalformedURLException { ++ ++ // Obtain default java applet policy ++ Policy policy = (Policy)AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ return Policy.getPolicy(); ++ } ++ }); ++ ++ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null); ++ final PermissionCollection pc = policy.getPermissions(cs); ++ if(url != null) { ++ Permission p; ++ String path = null; ++ try { ++ p = url.openConnection().getPermission(); ++ } catch (java.io.IOException ioe) { ++ p = null; ++ } ++ ++ if (p instanceof FilePermission) { ++ path = p.getName(); ++ } else if ((p == null) && (url.getProtocol().equals("file"))) { ++ path = url.getFile().replace('/', File.separatorChar); ++ path = ParseUtil.decode(path); ++ } else if (p instanceof SocketPermission) { ++ /* ++ Socket permission to connect back to the host ++ */ ++ String host = url.getHost(); ++ pc.add(new SocketPermission(host, ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ } ++ ++ if(path != null && ++ (clazz.getClassLoader() instanceof PluginClassLoader)) { ++ //We need to add an additional permission to read recursively ++ if (path.endsWith(File.separator)) { ++ path += "-"; ++ } else { ++ int endIndex = path.lastIndexOf(File.separatorChar); ++ if (endIndex != -1) ++ path = path.substring(0, endIndex+1) + "-"; ++ } ++ ++ pc.add(new FilePermission(path, SecurityConstants.FILE_READ_ACTION)); ++ ++ /* ++ Socket permission to connect back to the "localhost" ++ */ ++ pc.add(new SocketPermission("localhost", ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ try { ++ String host = InetAddress.getLocalHost().getHostName(); ++ pc.add(new SocketPermission(host, ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ } catch (UnknownHostException uhe) { ++ } ++ return null; ++ } ++ }); ++ } ++ } ++ ++ return new JavaScriptProtectionDomain(pc); ++ } ++ + public String toString() { + if(targetObj != null) { + return targetObj.toString(); + } + return null; + } ++ ++ public int getWindowHandle() { ++ if(wndHandle == 0) { ++ wndHandle = getWindowHandle(handle); ++ } ++ return wndHandle; ++ } ++ ++ protected void setBridge() { ++ isBridge = true; ++ } ++ ++ native int getWindowHandle(int id); + } + + diff --git a/java/jdk14/files/patch-plugin_FileList.gmk b/java/jdk14/files/patch-plugin_FileList.gmk new file mode 100644 index 000000000000..c5fca27bdda9 --- /dev/null +++ b/java/jdk14/files/patch-plugin_FileList.gmk @@ -0,0 +1,22 @@ +$FreeBSD$ + +--- ../../deploy/make/plugin/java/FileList.gmk 7 Nov 2003 12:15:52 -0000 1.2 ++++ ../../deploy/make/plugin/java/FileList.gmk 3 Dec 2004 03:56:58 -0000 1.3 +@@ -86,6 +86,9 @@ + \
+ sun/plugin/javascript/JSObject.java \
+ sun/plugin/javascript/JSContext.java \
++ sun/plugin/javascript/JSClassLoader.java \
++ sun/plugin/javascript/ReflectUtil.java \
++ sun/plugin/javascript/JSInvoke.java \
+ \
+ sun/plugin/javascript/navig/Navigator.java \
+ sun/plugin/javascript/navig/Document.java \
+@@ -125,6 +128,7 @@ + sun/plugin/liveconnect/JavaScriptPermission.java \
+ sun/plugin/liveconnect/SecurityContextHelper.java \
+ sun/plugin/liveconnect/LiveConnect.java \
++ sun/plugin/liveconnect/ReplaceMethod.java \
+ \
+ sun/plugin/extension/ExtensionInstallationImpl.java \
+ sun/plugin/extension/ExtensionInstaller.java \
diff --git a/java/jdk14/files/patch-plugin_MethodDispatcher.java b/java/jdk14/files/patch-plugin_MethodDispatcher.java new file mode 100644 index 000000000000..57e6d22b5a63 --- /dev/null +++ b/java/jdk14/files/patch-plugin_MethodDispatcher.java @@ -0,0 +1,41 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/com/MethodDispatcher.java 22 Oct 2003 23:04:20 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/com/MethodDispatcher.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* +- * @(#)MethodDispatcher.java 1.5 03/01/23 ++ * @(#)MethodDispatcher.java 1.10 04/06/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,6 +9,7 @@ + + import java.lang.reflect.Method; + import sun.plugin.util.Trace; ++import sun.plugin.javascript.JSClassLoader; + + /** + * A <code>MethodDispatcher</code> provides information about, +@@ -47,11 +48,16 @@ + Object retObj = null; + if(method != null && obj != null) { + Trace.msgLiveConnectPrintln("com.method.invoke", new Object[] {method}); ++ Class theClass = obj.getClass(); + Object[] params = TypeConverter.convertObjectArray( + method.getParameterTypes(), args); +- retObj = Utils.convertReturn( method.getReturnType(), +- method.invoke(obj, params )); ++ // check if the class is private and the method is public ++ retObj = JSClassLoader.invoke(method, obj, params); + } + return retObj; ++ } ++ ++ public Class getReturnType() { ++ return method.getReturnType(); + } + } diff --git a/java/jdk15/Makefile b/java/jdk15/Makefile index 6ab93e3cb8e4..169a67f7b96d 100644 --- a/java/jdk15/Makefile +++ b/java/jdk15/Makefile @@ -7,7 +7,7 @@ PORTNAME= jdk PORTVERSION= ${JDK_VERSION}p${JDK_PATCHSET_VERSION} -PORTREVISION= 6 +PORTREVISION= 7 CATEGORIES= java devel MASTER_SITES= # http://www.sun.com/software/java2/download.html # http://www.eyesbeyond.com/freebsddom/java/jdk14.html @@ -99,8 +99,6 @@ MAKE_ENV= ALT_BOOTDIR="${JDK14DIR}" \ .if defined(MINIMAL) MAKE_ENV+= NO_PLUGIN="YES" \ NO_JAVAWS="YES" -.else -FORBIDDEN= Vulnerabilities in the browser plugin .endif ALL_TARGET= all PLIST_SUB+= JDK_VERSION=${JDK_VERSION} diff --git a/java/jdk15/files/patch-javascript_JSClassLoader.java b/java/jdk15/files/patch-javascript_JSClassLoader.java new file mode 100644 index 000000000000..1e3a9ad3080b --- /dev/null +++ b/java/jdk15/files/patch-javascript_JSClassLoader.java @@ -0,0 +1,243 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSClassLoader.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSClassLoader.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,238 @@ ++/* ++ * @(#)JSClassLoader.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++ ++package sun.plugin.javascript; ++ ++import java.security.AllPermission; ++import java.security.AccessController; ++import java.security.PermissionCollection; ++import java.security.SecureClassLoader; ++import java.security.PrivilegedExceptionAction; ++import java.security.CodeSource; ++import java.io.InputStream; ++import java.io.BufferedInputStream; ++import java.io.IOException; ++import java.net.URL; ++import java.net.URLConnection; ++import java.net.HttpURLConnection; ++import java.lang.reflect.Method; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.AccessibleObject; ++import sun.net.www.ParseUtil; ++import sun.security.util.SecurityConstants; ++ ++/* ++ * Create a trampoline class for JavaScript to Java ++ * method invocations. ++ * ++ */ ++public final class JSClassLoader extends SecureClassLoader { ++ private static String JS_PROXY_PKG = "sun.plugin.javascript.invoke."; ++ private static String TRAMPOLINE = JS_PROXY_PKG + "JSInvoke"; ++ private static Method bounce; ++ ++ /* ++ * Bounce through the trampoline. ++ */ ++ public static Object invoke(Method m, Object obj, Object[] params) ++ throws Exception { ++ try { ++ return bounce().invoke(null, new Object[] {m, obj, params}); ++ } catch (InvocationTargetException ie) { ++ Throwable t = ie.getCause(); ++ ++ if (t instanceof InvocationTargetException) { ++ throw (InvocationTargetException)t; ++ } else { ++ throw ie; ++ } ++ } ++ } ++ ++ /** ++ * Check the package access permission by giving a class ++ * ++ * @param clazz: The Class object trying to get access to ++ * ++ */ ++ public static void checkPackageAccess(Class clazz) { ++ String clsname = clazz.getName(); ++ int index = clsname.lastIndexOf("."); ++ if (index != -1) { ++ String pkgname = clsname.substring(0, index); ++ SecurityManager s = System.getSecurityManager(); ++ if (s != null) { ++ s.checkPackageAccess(pkgname); ++ } ++ } ++ } ++ ++ public static boolean isPackageAccessible(Class clazz) { ++ try { ++ checkPackageAccess(clazz); ++ } catch (SecurityException e) { ++ return false; ++ } ++ return true; ++ } ++ ++ ++ private synchronized static Method bounce() throws Exception { ++ if (bounce == null) { ++ bounce = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { ++ public Object run() throws Exception { ++ Class[] types; ++ Class t = getTrampoline(); ++ Method b; ++ ++ types = new Class[] {Method.class, Object.class, Object[].class}; ++ b = t.getDeclaredMethod("invoke", types); ++ ((AccessibleObject)b).setAccessible(true); ++ return b; ++ } ++ }); ++ } ++ return bounce; ++ } ++ ++ private static Class getTrampoline() { ++ try { ++ return Class.forName(TRAMPOLINE, true, new JSClassLoader()); ++ } catch (ClassNotFoundException e) { ++ } ++ return null; ++ } ++ ++ ++ protected synchronized Class loadClass(String name, boolean resolve) ++ throws ClassNotFoundException ++ { ++ SecurityManager s = System.getSecurityManager(); ++ if (s != null) { ++ String cname = name.replace('/', '.'); ++ if (cname.startsWith("[")) { ++ int b = cname.lastIndexOf('[') + 2; ++ if (b > 1 && b < cname.length()) { ++ cname = cname.substring(b); ++ } ++ } ++ int i = cname.lastIndexOf('.'); ++ if (i != -1) { ++ s.checkPackageAccess(cname.substring(0, i)); ++ } ++ } ++ // First, check if the class has already been loaded ++ Class c = findLoadedClass(name); ++ if (c == null) { ++ try { ++ c = findClass(name); ++ } catch (ClassNotFoundException e) { ++ // Fall through ... ++ } ++ if (c == null) { ++ c = getParent().loadClass(name); ++ } ++ } ++ if (resolve) { ++ resolveClass(c); ++ } ++ return c; ++ } ++ ++ ++ protected Class findClass(final String name) ++ throws ClassNotFoundException ++ { ++ if (!name.startsWith(JS_PROXY_PKG)) { ++ throw new ClassNotFoundException(name); ++ } ++ String path = name.replace('.', '/').concat(".class"); ++ URL res = getResource(path); ++ if (res != null) { ++ try { ++ return defineClass(name, res); ++ } catch (IOException e) { ++ throw new ClassNotFoundException(name, e); ++ } ++ } else { ++ throw new ClassNotFoundException(name); ++ } ++ } ++ ++ ++ /* ++ * Define the JavaScript proxy classes ++ */ ++ private Class defineClass(String name, URL url) throws IOException { ++ byte[] b = getBytes(url); ++ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null); ++ if (!name.equals(TRAMPOLINE)) { ++ throw new IOException("JSClassLoader: bad name " + name); ++ } ++ return defineClass(name, b, 0, b.length, cs); ++ } ++ ++ ++ /* ++ * Returns the contents of the specified URL as an array of bytes. ++ */ ++ private static byte[] getBytes(URL url) throws IOException { ++ URLConnection uc = url.openConnection(); ++ if (uc instanceof java.net.HttpURLConnection) { ++ java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc; ++ int code = huc.getResponseCode(); ++ if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) { ++ throw new IOException("open HTTP connection failed."); ++ } ++ } ++ int len = uc.getContentLength(); ++ InputStream in = new BufferedInputStream(uc.getInputStream()); ++ ++ byte[] b; ++ try { ++ if (len != -1) { ++ // Read exactly len bytes from the input stream ++ b = new byte[len]; ++ while (len > 0) { ++ int n = in.read(b, b.length - len, len); ++ if (n == -1) { ++ throw new IOException("unexpected EOF"); ++ } ++ len -= n; ++ } ++ } else { ++ b = new byte[8192]; ++ int total = 0; ++ while ((len = in.read(b, total, b.length - total)) != -1) { ++ total += len; ++ if (total >= b.length) { ++ byte[] tmp = new byte[total * 2]; ++ System.arraycopy(b, 0, tmp, 0, total); ++ b = tmp; ++ } ++ } ++ // Trim array to correct size, if necessary ++ if (total != b.length) { ++ byte[] tmp = new byte[total]; ++ System.arraycopy(b, 0, tmp, 0, total); ++ b = tmp; ++ } ++ } ++ } finally { ++ in.close(); ++ } ++ return b; ++ } ++ ++ ++ protected PermissionCollection getPermissions(CodeSource codesource) ++ { ++ PermissionCollection perms = super.getPermissions(codesource); ++ perms.add(new AllPermission()); ++ return perms; ++ } ++} diff --git a/java/jdk15/files/patch-javascript_JSInvoke.java b/java/jdk15/files/patch-javascript_JSInvoke.java new file mode 100644 index 000000000000..fc692b9cb9c1 --- /dev/null +++ b/java/jdk15/files/patch-javascript_JSInvoke.java @@ -0,0 +1,26 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSInvoke.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSInvoke.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,21 @@ ++/* ++ * @(#)JSInvoke.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++ ++package sun.plugin.javascript.invoke; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.InvocationTargetException; ++ ++/* ++ * JavaScript to Java invocation trampoline class. ++ */ ++class JSInvoke { ++ private static Object invoke(Method m, Object obj, Object[] params) ++ throws InvocationTargetException, IllegalAccessException { ++ return m.invoke(obj, params); ++ } ++} diff --git a/java/jdk15/files/patch-javascript_ReflectUtil.java b/java/jdk15/files/patch-javascript_ReflectUtil.java new file mode 100644 index 000000000000..827bd0c666ce --- /dev/null +++ b/java/jdk15/files/patch-javascript_ReflectUtil.java @@ -0,0 +1,312 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,307 @@ ++/* ++ * @(#)ReflectUtil.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++package sun.plugin.javascript; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.lang.reflect.InvocationTargetException; ++import java.util.HashMap; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Iterator; ++import sun.plugin.javascript.JSClassLoader; ++ ++public class ReflectUtil { ++ /* ++ * Discover the public methods on public classes ++ * and interfaces accessible to the calling ++ * JavaScript code. ++ */ ++ public static Method[] getJScriptMethods(Class cls) { ++ List m = new ArrayList(); /* the valid methods we find */ ++ ++ /* ++ * Temporary map of method signatures when we decide ++ * that a simple call to target.getMethods() returns ++ * inaccessible methods and we must search for alternative ++ * supermethods that might be accessible. We can toss ++ * this when we're done searching. ++ */ ++ Map sigs = new HashMap(); ++ ++ while (cls != null) { ++ boolean done = getPublicMethods(cls, m, sigs); ++ if (done) { ++ break; ++ } ++ getJScriptInterfaceMethods(cls, m, sigs); ++ cls = cls.getSuperclass(); ++ } ++ return (Method[]) m.toArray(new Method[m.size()]); ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ private static void getJScriptInterfaceMethods(Class cls, List m, Map sigs) { ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length; i++) { ++ Class intf = intfs[i]; ++ boolean done = getPublicMethods(intf, m, sigs); ++ if (!done) { ++ getJScriptInterfaceMethods(intf, m, sigs); ++ } ++ } ++ } ++ ++ /* ++ * ++ * Process the methods in this class or interface ++ */ ++ private static boolean getPublicMethods(Class cls, List m, Map sigs) { ++ Method[] methods = null; ++ try { ++ ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's methods. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return false; ++ } ++ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return false; ++ } ++ ++ methods = cls.getMethods(); ++ } catch (SecurityException se) { ++ return false; ++ } ++ ++ /* ++ * Check for inherited methods with non-public ++ * declaring classes. They might override and hide ++ * methods from their superclasses or ++ * superinterfaces. ++ */ ++ boolean done = true; ++ for (int i=0; i < methods.length; i++) { ++ Class dc = methods[i].getDeclaringClass(); ++ if (!Modifier.isPublic(dc.getModifiers())) { ++ done = false; ++ break; ++ } ++ } ++ ++ /* ++ * Belatedly initialize the signature map if ++ * this is not the first time here. ++ */ ++ if (sigs.isEmpty() && !m.isEmpty()) { ++ initSignatureMap(m, sigs); ++ } ++ ++ if (done) { ++ /* ++ * We're done. Spray all the methods into ++ * the list and then we're out of here. ++ */ ++ for (int i=0; i < methods.length; i++) { ++ addMethod(m, sigs, methods[i]); ++ } ++ } else { ++ /* ++ * Simulate cls.getDeclaredMethods() by ++ * stripping away inherited methods. ++ */ ++ for (int i=0; i < methods.length; i++) { ++ Class dc = methods[i].getDeclaringClass(); ++ if (cls.equals(dc)) { ++ addMethod(m, sigs, methods[i]); ++ } ++ } ++ } ++ return done; ++ } ++ ++ private static void initSignatureMap(List m, Map sigs) { ++ Iterator i = m.iterator(); ++ while (i.hasNext()) { ++ Method entry = (Method) i.next(); ++ sigs.put(getSignature(entry), entry); ++ } ++ } ++ ++ private static void addMethod(List m, Map sigs, Method method) { ++ /* ++ * Avoid work. We ignore the signature matching ++ * until the map is initialized in initSignatureMap. ++ * This has the effect of avoiding the signature ++ * work for the first call of getPublicMethods(). ++ */ ++ if (sigs.isEmpty()) { ++ m.add(method); ++ return; ++ } ++ ++ /* ++ * Avoid adding duplicate accessible methods on ++ * the list. ++ */ ++ String signature = getSignature(method); ++ if (!sigs.containsKey(signature)) { ++ m.add(method); ++ sigs.put(signature, method); ++ } ++ } ++ ++ /* ++ * Return a canonical method signature for the method. ++ * We care only about the simple method name and the ++ * the number, type and order of the parameters. ++ * Exception declarations are not part of a method ++ * signature nor is the return type. ++ */ ++ private static String getSignature(Method method) { ++ StringBuffer sb = new StringBuffer(); ++ ++ sb.append(method.getName()); ++ Class[] params = method.getParameterTypes(); ++ sb.append('('); ++ if (params.length > 0) { ++ sb.append(params[0].getName()); ++ } ++ for (int i=1; i < params.length; i++) { ++ sb.append(','); ++ sb.append(params[i].getName()); ++ } ++ sb.append(')'); ++ ++ return sb.toString(); ++ } ++ ++ /* ++ * Discover the public fields on public classes ++ * and interfaces accessible to the calling ++ * JavaScript code. ++ */ ++ public static Field[] getJScriptFields(Class cls) { ++ List m = new ArrayList(); /* the valid fields we find */ ++ ++ /* ++ * Temporary map of field name when we decide ++ * that a simple call to target.getFields() returns ++ * inaccessible fields and we must search for alternative ++ * supermethods that might be accessible. We can toss ++ * this when we're done searching. ++ */ ++ Map names = new HashMap(); ++ ++ while (cls != null) { ++ boolean done = getPublicFields(cls, m, names); ++ if (done) { ++ break; ++ } ++ getJScriptInterfaceFields(cls, m, names); ++ cls = cls.getSuperclass(); ++ } ++ return (Field[]) m.toArray(new Field[m.size()]); ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ private static void getJScriptInterfaceFields(Class cls, List m, Map names) { ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length; i++) { ++ Class intf = intfs[i]; ++ boolean done = getPublicFields(intf, m, names); ++ if (!done) { ++ getJScriptInterfaceFields(intf, m, names); ++ } ++ } ++ } ++ ++ /* ++ * ++ * Process the fields in this class or interface ++ */ ++ private static boolean getPublicFields(Class cls, List m, Map names) { ++ Field[] fields = null; ++ try { ++ ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's fields. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return false; ++ } ++ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return false; ++ } ++ fields = cls.getFields(); ++ } catch (SecurityException se) { ++ return false; ++ } ++ ++ /* ++ * Check for inherited fields with non-public ++ * declaring classes. They might hide ++ * fields from public classes or interfaces. ++ */ ++ boolean done = true; ++ for (int i=0; i < fields.length; i++) { ++ Class dc = fields[i].getDeclaringClass(); ++ if (!Modifier.isPublic(dc.getModifiers())) { ++ done = false; ++ break; ++ } ++ } ++ if (done) { ++ /* ++ * We're done. Spray all the fields into ++ * the list and then we're out of here. ++ */ ++ for (int i=0; i < fields.length; i++) { ++ addField(m, names, fields[i]); ++ } ++ } else { ++ /* ++ * Simulate cls.getDeclaredFields() by ++ * stripping away inherited fields. ++ */ ++ for (int i=0; i < fields.length; i++) { ++ Class dc = fields[i].getDeclaringClass(); ++ if (cls.equals(dc)) { ++ addField(m, names, fields[i]); ++ } ++ } ++ } ++ return done; ++ } ++ ++ private static void addField(List m, Map names, Field field) { ++ /* ++ * Avoid adding duplicate accessible fields on ++ * the list. ++ */ ++ String name = field.getName(); ++ if (!names.containsKey(name)) { ++ m.add(field); ++ names.put(name, field); ++ } ++ } ++} ++ ++ diff --git a/java/jdk15/files/patch-liveconnect_ReplaceMethod.java b/java/jdk15/files/patch-liveconnect_ReplaceMethod.java new file mode 100644 index 000000000000..829e43452e6c --- /dev/null +++ b/java/jdk15/files/patch-liveconnect_ReplaceMethod.java @@ -0,0 +1,93 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/ReplaceMethod.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/ReplaceMethod.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,88 @@ ++/* ++ * @(#)ReplaceMethod.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++package sun.plugin.liveconnect; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import sun.plugin.javascript.JSClassLoader; ++ ++public class ReplaceMethod { ++ /* ++ * Replace the inaccessible method by a suitable method on public ++ * class/interface accessible to the calling JavaScript code. ++ * Returns null if accessible method is not found. ++ */ ++ static Method getJScriptMethod(Method start) { ++ Class cls = start.getDeclaringClass(); ++ ++ if (Modifier.isPublic(cls.getModifiers())) { ++ return start; ++ } ++ ++ String name = start.getName(); ++ Class[] params = start.getParameterTypes(); ++ ++ Method result = null; ++ while (cls != null && result == null) { ++ result = getPublicMethod(cls, name, params); ++ if (result == null) { ++ result = getJScriptInterfaceMethod(cls, name, params); ++ } ++ cls = cls.getSuperclass(); ++ } ++ return result; ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ static Method getJScriptInterfaceMethod(Class cls, String name, Class[] params) { ++ Method result = null; ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length && result == null; i++) { ++ Class intf = intfs[i]; ++ result = getPublicMethod(intf, name, params); ++ if (result == null) { ++ result = getJScriptInterfaceMethod(intf, name, params); ++ } ++ } ++ return result; ++ } ++ ++ /* ++ * ++ * Process the methods in this class or interface ++ */ ++ static private Method getPublicMethod(Class cls, String name, Class[] params) { ++ try { ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's methods. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return null; ++ } ++ ++ /* ++ * This call will fail if 'cls' is in a restricted ++ * package and we don't have permission to access ++ * it. ++ */ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return null; ++ } ++ return cls.getMethod(name, params); ++ } catch (NoSuchMethodException nsme) { ++ return null; ++ } catch (SecurityException se) { ++ return null; ++ } ++ } ++} ++ ++ diff --git a/java/jdk15/files/patch-liveconnect_SecureInvocation.java b/java/jdk15/files/patch-liveconnect_SecureInvocation.java new file mode 100644 index 000000000000..961414277909 --- /dev/null +++ b/java/jdk15/files/patch-liveconnect_SecureInvocation.java @@ -0,0 +1,351 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/SecureInvocation.java 22 Oct 2003 23:04:21 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/SecureInvocation.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* + * @(#)SecureInvocation.java 1.21 02/08/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,7 +9,8 @@ + + import java.lang.reflect.Constructor; + import java.lang.reflect.Field; +-import java.lang.reflect.Method;
++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; + import java.lang.Thread; + import java.io.FilePermission; + import java.security.AccessControlContext; +@@ -29,7 +30,10 @@ + import java.net.URL; + import java.net.MalformedURLException; + import sun.plugin.util.Trace; +-import sun.plugin.services.PlatformService;
++import sun.plugin.services.PlatformService; ++import sun.plugin.javascript.JSClassLoader; ++import sun.plugin.javascript.ReflectUtil; ++ + + /** + * <P> SecureInvocation is for implementating nsISecureJNI which allows +@@ -98,64 +102,64 @@ + throw e; + } + } +-
+- static class CallMethodThread extends Thread {
+- public CallMethodThread(int handle, Class clazz, Object obj, Method method, Object[] args,
+- String origin, boolean isUniversalBrowserRead,
+- boolean isUniversalJavaPermission) {
+- this.handle = handle;
+- this.clazz = clazz;
+- this.obj = obj;
+- this.method = method;
+- this.args = args;
+- this.origin = origin;
+- this.isUniversalBrowserRead = isUniversalBrowserRead;
+- this.isUniversalJavaPermission = isUniversalJavaPermission;
+- }
+-
+- public void run() {
+- try {
+- result = CallMethod(clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission);
+- }
+- catch(Exception e) {
+- exception = e;
+- }
+- finally {
+- PlatformService.getService().signalEvent(handle);
+- }
+- }
+-
+-
+- public Object getResult() throws Exception {
+- if(exception != null)
+- throw exception;
+- return result;
+- }
+-
+- private Exception exception = null;
+- private Object result = null;
+-
+- private int handle;
+- private Class clazz;
+- private Object obj;
+- private Method method;
+- private Object[] args;
+- private String origin;
+- private boolean isUniversalBrowserRead;
+- private boolean isUniversalJavaPermission;
+-
+- }
+- +- public static Object CallMethod(final int handle, final Class clazz, final Object obj, final Method method, final Object[] args,
+- final String origin, final boolean isUniversalBrowserRead,
+- final boolean isUniversalJavaPermission)
+- throws Exception {
+- CallMethodThread callThread = new CallMethodThread(handle, clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission);
+- callThread.start();
+- PlatformService.getService().waitEvent(handle);
+- return callThread.getResult();
+- }
+-
++ ++ static class CallMethodThread extends Thread { ++ public CallMethodThread(int handle, Class clazz, Object obj, Method method, Object[] args, ++ String origin, boolean isUniversalBrowserRead, ++ boolean isUniversalJavaPermission) { ++ this.handle = handle; ++ this.clazz = clazz; ++ this.obj = obj; ++ this.method = method; ++ this.args = args; ++ this.origin = origin; ++ this.isUniversalBrowserRead = isUniversalBrowserRead; ++ this.isUniversalJavaPermission = isUniversalJavaPermission; ++ } ++ ++ public void run() { ++ try { ++ result = CallMethod(clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission); ++ } ++ catch(Exception e) { ++ exception = e; ++ } ++ finally { ++ PlatformService.getService().signalEvent(handle); ++ } ++ } ++ ++ ++ public Object getResult() throws Exception { ++ if(exception != null) ++ throw exception; ++ return result; ++ } ++ ++ private Exception exception = null; ++ private Object result = null; ++ ++ private int handle; ++ private Class clazz; ++ private Object obj; ++ private Method method; ++ private Object[] args; ++ private String origin; ++ private boolean isUniversalBrowserRead; ++ private boolean isUniversalJavaPermission; ++ ++ } ++ ++ public static Object CallMethod(final int handle, final Class clazz, final Object obj, final Method method, final Object[] args, ++ final String origin, final boolean isUniversalBrowserRead, ++ final boolean isUniversalJavaPermission) ++ throws Exception { ++ CallMethodThread callThread = new CallMethodThread(handle, clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission); ++ callThread.start(); ++ PlatformService.getService().waitEvent(handle); ++ return callThread.getResult(); ++ } ++ + + /** + * <P> Call a method on Java object with security context. +@@ -197,8 +201,8 @@ + AccessControlContext context = new AccessControlContext(domains); + + // Perform the method invocation. +- return AccessController.doPrivileged(new PrivilegedCallMethodAction(method, obj, args), +- context); ++ return AccessController.doPrivileged(new PrivilegedCallMethodAction(method, ++ obj, args), context); + } catch (Exception e) { + Trace.liveConnectPrintException(e); + throw e; +@@ -323,32 +327,6 @@ + } + } + +- +- /** +- * <P> Set up a protection domain according to the origin and +- * the other security related information. +- */ +- private static ProtectionDomain getProtectionDomain(Class clazz, +- String origin, +- boolean byPassOrigin, +- boolean allPermission) +- throws OriginNotAllowedException, MalformedURLException +- { +- boolean trust = false; +- +- // First, check if the call is allowed +- checkLiveConnectCaller(clazz, origin, byPassOrigin); +- +- if (allPermission) +- { +- return getTrustedProtectionDomain(); +- } +- else +- { +- return getDefaultProtectionDomain(origin); +- } +- } +- + /** + * <P> Check if LiveConnect call is allowed at all. + * </P> +@@ -447,7 +425,7 @@ + + // Obtain Java policy + Policy policy = Policy.getPolicy(); +- CodeSource cs = new CodeSource(url, null); ++ CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null); + final PermissionCollection pc = policy.getPermissions(cs); + + if (url == null || url.getProtocol().equals("file")) { +@@ -516,16 +494,19 @@ + + PrivilegedConstructObjectAction(Constructor constructor, Object[] args) + { +- this.constructor = constructor; +- this.args = args; ++ this.constructor = constructor; ++ this.args = args; + +- // Ensure the argument is not null +- if (this.args == null) +- this.args = new Object[0]; ++ // Ensure the argument is not null ++ if (this.args == null) ++ this.args = new Object[0]; + } + + public Object run() throws Exception { +- return constructor.newInstance(args); ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(constructor.getDeclaringClass()); ++ ++ return constructor.newInstance(args); + } + } + +@@ -543,17 +524,54 @@ + + PrivilegedCallMethodAction(Method method, Object obj, Object[] args) + { +- this.method = method; +- this.obj = obj; +- this.args = args; +- +- // Ensure the argument is not null +- if (this.args == null) +- this.args = new Object[0]; ++ this.method = method; ++ ++ this.obj = obj; ++ this.args = args; ++ ++ // Ensure the argument is not null ++ if (this.args == null) ++ this.args = new Object[0]; + } + + public Object run() throws Exception { +- return method.invoke(obj, args); ++ /* ++ * Browser uses reflection to collect methods/fields/constructors ++ * through this method call. Therefore JSClassLoader is not used ++ * in such cases. However it requires filtering to avoid exposing ++ * inaccessible methods/fields/constructors. ++ * ++ * Also, Mozilla ignores abstract methods, therefore those are ++ * replaced by the concrete class methods ++ */ ++ if(obj instanceof Class) { ++ String name = method.getName(); ++ Class cls = (Class)obj; ++ if(name.equals("getMethods")) { ++ Method[] methods = ReflectUtil.getJScriptMethods(cls); ++ for (int i=0; i < methods.length; i++) { ++ Method m = methods[i]; ++ if (Modifier.isAbstract(m.getModifiers())) { ++ Class[] params = m.getParameterTypes(); ++ methods[i] = cls.getMethod(m.getName(), params); ++ } ++ } ++ return methods; ++ }else if (name.equals("getFields")) { ++ return ReflectUtil.getJScriptFields(cls); ++ }else if (name.equals("getConstructors")) { ++ if (!Modifier.isPublic(cls.getModifiers()) || ++ !JSClassLoader.isPackageAccessible(cls)) { ++ return new Constructor[0]; ++ } ++ } ++ } ++ ++ Method actualMethod = ReplaceMethod.getJScriptMethod(method); ++ if(actualMethod != null) ++ return JSClassLoader.invoke(actualMethod, obj, args); ++ else ++ throw new NoSuchMethodException(method.getName()); + } + } + +@@ -564,18 +582,20 @@ + * </P> + */ + class PrivilegedGetFieldAction implements PrivilegedExceptionAction { +- + Field field; + Object obj; + + PrivilegedGetFieldAction(Field field, Object obj) + { +- this.field = field; +- this.obj = obj; ++ this.field = field; ++ this.obj = obj; + } + +- public Object run() throws Exception { +- return field.get(obj); ++ public Object run() throws Exception { ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(field.getDeclaringClass()); ++ ++ return field.get(obj); + } + } + +@@ -593,15 +613,18 @@ + + PrivilegedSetFieldAction(Field field, Object obj, Object val) + { +- this.field = field; +- this.obj = obj; +- this.val = val; ++ this.field = field; ++ this.obj = obj; ++ this.val = val; + } + + public Object run() throws Exception { +- field.set(obj, val); ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(field.getDeclaringClass()); ++ ++ field.set(obj, val); + return null; + } + } +-
+-
++ ++ diff --git a/java/jdk15/files/patch-plugin_DispatchImpl.java b/java/jdk15/files/patch-plugin_DispatchImpl.java new file mode 100644 index 000000000000..abb65a60953e --- /dev/null +++ b/java/jdk15/files/patch-plugin_DispatchImpl.java @@ -0,0 +1,331 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/com/DispatchImpl.java 22 Oct 2003 23:04:20 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/com/DispatchImpl.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* +- * @(#)DispatchImpl.java 1.6 03/01/23 ++ * @(#)DispatchImpl.java 1.16 04/06/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,8 +9,32 @@ + + import sun.plugin.util.Trace; + import sun.plugin.javascript.ocx.JSObject; +-import java.applet.Applet; ++import sun.plugin.liveconnect.JavaScriptProtectionDomain; + import sun.plugin.viewer.context.IExplorerAppletContext; ++import sun.plugin.security.PluginClassLoader; ++import java.applet.Applet; ++import java.net.URL; ++import java.net.MalformedURLException; ++import java.net.InetAddress; ++import java.net.UnknownHostException; ++import java.net.SocketPermission; ++import java.io.FilePermission; ++import java.io.File; ++import java.security.AccessControlContext; ++import java.security.AccessController; ++import java.security.CodeSource; ++import java.security.Policy; ++import java.security.ProtectionDomain; ++import java.security.AllPermission; ++import java.security.Permissions; ++import java.security.Permission; ++import java.security.PermissionCollection; ++import java.security.PrivilegedAction; ++import java.security.PrivilegedExceptionAction; ++import java.security.AccessControlException; ++import java.security.PrivilegedActionException; ++import sun.net.www.ParseUtil; ++import sun.security.util.SecurityConstants; + + /** + * DispatchImpl encapsulates a Java Object and provides Dispatch interface +@@ -22,14 +46,19 @@ + { + JavaClass targetClass = null; + Object targetObj = null; ++ int handle = 0; ++ int wndHandle = 0; ++ AccessControlContext context = null; ++ boolean isBridge = false; + + /* + * Constructor + * @param obj the object to be wrapped + */ +- public DispatchImpl(Object obj) ++ public DispatchImpl(Object obj, int id) + { + targetObj = obj; ++ handle = id; + } + + /** +@@ -40,19 +69,87 @@ + * @param params Arguments. + * @return Java object. + */ +- public Object invoke(int flag, int index, Object []params) ++ public Object invoke(final int flag, final int index, final Object []params) ++ throws Exception ++ { ++ try { ++ //No security constraints in case of ActiveX bridge application ++ if(isBridge) ++ return invokeImpl(flag, index, params); ++ ++ if(context == null) { ++ context = createContext(); ++ } ++ ++ // Invoke the method within the applet sand box security restricitions ++ return AccessController.doPrivileged( ++ new PrivilegedExceptionAction() { ++ public Object run() throws Exception{ ++ return invokeImpl(flag, index, params); ++ } ++ }, context ++ ); ++ }catch(Exception exc) { ++ Throwable cause = exc.getCause(); ++ if(cause == null) { ++ cause = exc; ++ } ++ ++ Trace.liveConnectPrintException(cause); ++ throw new Exception(cause.toString()); ++ } ++ } ++ ++ public AccessControlContext createContext() { ++ try { ++ ProtectionDomain[] domains = new ProtectionDomain[1]; ++ //Obtain the java code origin ++ ProtectionDomain pd = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ return targetObj.getClass().getProtectionDomain(); ++ } ++ }); ++ ++ CodeSource cs = null; ++ URL url = null; ++ if(pd != null) ++ cs = pd.getCodeSource(); ++ if(cs != null) ++ url = cs.getLocation(); ++ ++ domains[0] = getJSProtectionDomain(url, targetObj.getClass()); ++ return new AccessControlContext(domains); ++ }catch(Exception exc) { ++ Trace.liveConnectPrintException(exc); ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Invoke a method according to the method index. ++ * ++ * @param flag Invoke flag ++ * @param index Method index ++ * @param params Arguments. ++ * @return Java object. ++ */ ++ public Object invokeImpl(int flag, int index, Object []params) + throws Exception + { + Object retObj = null; + Dispatcher disp = null; + try { +- convertParams(params); ++ if(params != null) ++ convertParams(params); + disp = targetClass.getDispatcher(flag, index, params); +- return disp.invoke(targetObj, params); +- } +- catch (Throwable e) +- { +- //e.printStackTrace(); ++ if(disp != null) { ++ retObj = disp.invoke(targetObj, params); ++ if(retObj != null) ++ retObj = Utils.convertReturn(disp.getReturnType(), retObj, handle); ++ } ++ return retObj; ++ } catch (Throwable e) { + Throwable cause = e.getCause(); + if(cause == null) { + cause = e; +@@ -82,11 +179,39 @@ + return targetClass; + } + ++ public int getReturnType(int id){ ++ return targetClass.getReturnType(id); ++ } ++ ++ public int getIdForName(final String name) throws Exception{ ++ try { ++ //No security constraints in case of ActiveX bridge application ++ if(isBridge) ++ return getIdForNameImpl(name); ++ ++ if(context == null) { ++ context = createContext(); ++ } ++ ++ // Invoke the method within the applet sand box security restricitions ++ Integer retVal = (Integer)AccessController.doPrivileged( ++ new PrivilegedExceptionAction() { ++ public Object run() throws Exception{ ++ return new Integer(getIdForNameImpl(name)); ++ } ++ }, context ++ ); ++ return retVal.intValue(); ++ }catch(PrivilegedActionException pe) { ++ } ++ ++ return -1; ++ } + + /* + * + */ +- public int getIdForName(String name) throws Exception{ ++ public int getIdForNameImpl(String name) throws Exception{ + int id = -1; + + if(targetClass == null && targetObj != null) { +@@ -103,27 +228,122 @@ + } + + /* +- * ++ * Unwraps the wrapped java object arguments + */ + private void convertParams(Object []params) { + for(int i=0;i<params.length;i++) { + if(params[i] != null && params[i] instanceof DispatchImpl) { + params[i] = ((DispatchImpl)params[i]).getWrappedObject(); + } else if(params[i] != null && params[i] instanceof DispatchClient){ +- JSObject jsObj = new JSObject((DispatchClient)params[i]); +- jsObj.setIExplorerAppletContext((IExplorerAppletContext) ++ JSObject jsObj = null; ++ if (!isBridge) { ++ jsObj = new JSObject((DispatchClient)params[i]); ++ jsObj.setIExplorerAppletContext((IExplorerAppletContext) + ((Applet)targetObj).getAppletContext()); ++ } else { ++ jsObj = new JSObject((DispatchClient)params[i], handle); ++ } + params[i] = jsObj; + } + } + } + ++ /** ++ * Returns a protection domain that represents the default permission ++ * for a given URL. ++ * ++ * @param urlString URL ++ * @return protection domain. ++ */ ++ public static ProtectionDomain getJSProtectionDomain(URL url, Class clazz) ++ throws MalformedURLException { ++ ++ // Obtain default java applet policy ++ Policy policy = (Policy)AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ return Policy.getPolicy(); ++ } ++ }); ++ ++ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null); ++ final PermissionCollection pc = policy.getPermissions(cs); ++ if(url != null) { ++ Permission p; ++ String path = null; ++ try { ++ p = url.openConnection().getPermission(); ++ } catch (java.io.IOException ioe) { ++ p = null; ++ } ++ ++ if (p instanceof FilePermission) { ++ path = p.getName(); ++ } else if ((p == null) && (url.getProtocol().equals("file"))) { ++ path = url.getFile().replace('/', File.separatorChar); ++ path = ParseUtil.decode(path); ++ } else if (p instanceof SocketPermission) { ++ /* ++ Socket permission to connect back to the host ++ */ ++ String host = url.getHost(); ++ pc.add(new SocketPermission(host, ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ } ++ ++ if(path != null && ++ (clazz.getClassLoader() instanceof PluginClassLoader)) { ++ //We need to add an additional permission to read recursively ++ if (path.endsWith(File.separator)) { ++ path += "-"; ++ } else { ++ int endIndex = path.lastIndexOf(File.separatorChar); ++ if (endIndex != -1) ++ path = path.substring(0, endIndex+1) + "-"; ++ } ++ ++ pc.add(new FilePermission(path, SecurityConstants.FILE_READ_ACTION)); ++ ++ /* ++ Socket permission to connect back to the "localhost" ++ */ ++ pc.add(new SocketPermission("localhost", ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ try { ++ String host = InetAddress.getLocalHost().getHostName(); ++ pc.add(new SocketPermission(host, ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ } catch (UnknownHostException uhe) { ++ } ++ return null; ++ } ++ }); ++ } ++ } ++ ++ return new JavaScriptProtectionDomain(pc); ++ } ++ + public String toString() { + if(targetObj != null) { + return targetObj.toString(); + } + return null; + } ++ ++ public int getWindowHandle() { ++ if(wndHandle == 0) { ++ wndHandle = getWindowHandle(handle); ++ } ++ return wndHandle; ++ } ++ ++ protected void setBridge() { ++ isBridge = true; ++ } ++ ++ native int getWindowHandle(int id); + } + + diff --git a/java/jdk15/files/patch-plugin_FileList.gmk b/java/jdk15/files/patch-plugin_FileList.gmk new file mode 100644 index 000000000000..c5fca27bdda9 --- /dev/null +++ b/java/jdk15/files/patch-plugin_FileList.gmk @@ -0,0 +1,22 @@ +$FreeBSD$ + +--- ../../deploy/make/plugin/java/FileList.gmk 7 Nov 2003 12:15:52 -0000 1.2 ++++ ../../deploy/make/plugin/java/FileList.gmk 3 Dec 2004 03:56:58 -0000 1.3 +@@ -86,6 +86,9 @@ + \
+ sun/plugin/javascript/JSObject.java \
+ sun/plugin/javascript/JSContext.java \
++ sun/plugin/javascript/JSClassLoader.java \
++ sun/plugin/javascript/ReflectUtil.java \
++ sun/plugin/javascript/JSInvoke.java \
+ \
+ sun/plugin/javascript/navig/Navigator.java \
+ sun/plugin/javascript/navig/Document.java \
+@@ -125,6 +128,7 @@ + sun/plugin/liveconnect/JavaScriptPermission.java \
+ sun/plugin/liveconnect/SecurityContextHelper.java \
+ sun/plugin/liveconnect/LiveConnect.java \
++ sun/plugin/liveconnect/ReplaceMethod.java \
+ \
+ sun/plugin/extension/ExtensionInstallationImpl.java \
+ sun/plugin/extension/ExtensionInstaller.java \
diff --git a/java/jdk15/files/patch-plugin_MethodDispatcher.java b/java/jdk15/files/patch-plugin_MethodDispatcher.java new file mode 100644 index 000000000000..57e6d22b5a63 --- /dev/null +++ b/java/jdk15/files/patch-plugin_MethodDispatcher.java @@ -0,0 +1,41 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/com/MethodDispatcher.java 22 Oct 2003 23:04:20 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/com/MethodDispatcher.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* +- * @(#)MethodDispatcher.java 1.5 03/01/23 ++ * @(#)MethodDispatcher.java 1.10 04/06/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,6 +9,7 @@ + + import java.lang.reflect.Method; + import sun.plugin.util.Trace; ++import sun.plugin.javascript.JSClassLoader; + + /** + * A <code>MethodDispatcher</code> provides information about, +@@ -47,11 +48,16 @@ + Object retObj = null; + if(method != null && obj != null) { + Trace.msgLiveConnectPrintln("com.method.invoke", new Object[] {method}); ++ Class theClass = obj.getClass(); + Object[] params = TypeConverter.convertObjectArray( + method.getParameterTypes(), args); +- retObj = Utils.convertReturn( method.getReturnType(), +- method.invoke(obj, params )); ++ // check if the class is private and the method is public ++ retObj = JSClassLoader.invoke(method, obj, params); + } + return retObj; ++ } ++ ++ public Class getReturnType() { ++ return method.getReturnType(); + } + } diff --git a/java/jdk16/Makefile b/java/jdk16/Makefile index 6ab93e3cb8e4..169a67f7b96d 100644 --- a/java/jdk16/Makefile +++ b/java/jdk16/Makefile @@ -7,7 +7,7 @@ PORTNAME= jdk PORTVERSION= ${JDK_VERSION}p${JDK_PATCHSET_VERSION} -PORTREVISION= 6 +PORTREVISION= 7 CATEGORIES= java devel MASTER_SITES= # http://www.sun.com/software/java2/download.html # http://www.eyesbeyond.com/freebsddom/java/jdk14.html @@ -99,8 +99,6 @@ MAKE_ENV= ALT_BOOTDIR="${JDK14DIR}" \ .if defined(MINIMAL) MAKE_ENV+= NO_PLUGIN="YES" \ NO_JAVAWS="YES" -.else -FORBIDDEN= Vulnerabilities in the browser plugin .endif ALL_TARGET= all PLIST_SUB+= JDK_VERSION=${JDK_VERSION} diff --git a/java/jdk16/files/patch-javascript_JSClassLoader.java b/java/jdk16/files/patch-javascript_JSClassLoader.java new file mode 100644 index 000000000000..1e3a9ad3080b --- /dev/null +++ b/java/jdk16/files/patch-javascript_JSClassLoader.java @@ -0,0 +1,243 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSClassLoader.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSClassLoader.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,238 @@ ++/* ++ * @(#)JSClassLoader.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++ ++package sun.plugin.javascript; ++ ++import java.security.AllPermission; ++import java.security.AccessController; ++import java.security.PermissionCollection; ++import java.security.SecureClassLoader; ++import java.security.PrivilegedExceptionAction; ++import java.security.CodeSource; ++import java.io.InputStream; ++import java.io.BufferedInputStream; ++import java.io.IOException; ++import java.net.URL; ++import java.net.URLConnection; ++import java.net.HttpURLConnection; ++import java.lang.reflect.Method; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.AccessibleObject; ++import sun.net.www.ParseUtil; ++import sun.security.util.SecurityConstants; ++ ++/* ++ * Create a trampoline class for JavaScript to Java ++ * method invocations. ++ * ++ */ ++public final class JSClassLoader extends SecureClassLoader { ++ private static String JS_PROXY_PKG = "sun.plugin.javascript.invoke."; ++ private static String TRAMPOLINE = JS_PROXY_PKG + "JSInvoke"; ++ private static Method bounce; ++ ++ /* ++ * Bounce through the trampoline. ++ */ ++ public static Object invoke(Method m, Object obj, Object[] params) ++ throws Exception { ++ try { ++ return bounce().invoke(null, new Object[] {m, obj, params}); ++ } catch (InvocationTargetException ie) { ++ Throwable t = ie.getCause(); ++ ++ if (t instanceof InvocationTargetException) { ++ throw (InvocationTargetException)t; ++ } else { ++ throw ie; ++ } ++ } ++ } ++ ++ /** ++ * Check the package access permission by giving a class ++ * ++ * @param clazz: The Class object trying to get access to ++ * ++ */ ++ public static void checkPackageAccess(Class clazz) { ++ String clsname = clazz.getName(); ++ int index = clsname.lastIndexOf("."); ++ if (index != -1) { ++ String pkgname = clsname.substring(0, index); ++ SecurityManager s = System.getSecurityManager(); ++ if (s != null) { ++ s.checkPackageAccess(pkgname); ++ } ++ } ++ } ++ ++ public static boolean isPackageAccessible(Class clazz) { ++ try { ++ checkPackageAccess(clazz); ++ } catch (SecurityException e) { ++ return false; ++ } ++ return true; ++ } ++ ++ ++ private synchronized static Method bounce() throws Exception { ++ if (bounce == null) { ++ bounce = (Method) AccessController.doPrivileged(new PrivilegedExceptionAction() { ++ public Object run() throws Exception { ++ Class[] types; ++ Class t = getTrampoline(); ++ Method b; ++ ++ types = new Class[] {Method.class, Object.class, Object[].class}; ++ b = t.getDeclaredMethod("invoke", types); ++ ((AccessibleObject)b).setAccessible(true); ++ return b; ++ } ++ }); ++ } ++ return bounce; ++ } ++ ++ private static Class getTrampoline() { ++ try { ++ return Class.forName(TRAMPOLINE, true, new JSClassLoader()); ++ } catch (ClassNotFoundException e) { ++ } ++ return null; ++ } ++ ++ ++ protected synchronized Class loadClass(String name, boolean resolve) ++ throws ClassNotFoundException ++ { ++ SecurityManager s = System.getSecurityManager(); ++ if (s != null) { ++ String cname = name.replace('/', '.'); ++ if (cname.startsWith("[")) { ++ int b = cname.lastIndexOf('[') + 2; ++ if (b > 1 && b < cname.length()) { ++ cname = cname.substring(b); ++ } ++ } ++ int i = cname.lastIndexOf('.'); ++ if (i != -1) { ++ s.checkPackageAccess(cname.substring(0, i)); ++ } ++ } ++ // First, check if the class has already been loaded ++ Class c = findLoadedClass(name); ++ if (c == null) { ++ try { ++ c = findClass(name); ++ } catch (ClassNotFoundException e) { ++ // Fall through ... ++ } ++ if (c == null) { ++ c = getParent().loadClass(name); ++ } ++ } ++ if (resolve) { ++ resolveClass(c); ++ } ++ return c; ++ } ++ ++ ++ protected Class findClass(final String name) ++ throws ClassNotFoundException ++ { ++ if (!name.startsWith(JS_PROXY_PKG)) { ++ throw new ClassNotFoundException(name); ++ } ++ String path = name.replace('.', '/').concat(".class"); ++ URL res = getResource(path); ++ if (res != null) { ++ try { ++ return defineClass(name, res); ++ } catch (IOException e) { ++ throw new ClassNotFoundException(name, e); ++ } ++ } else { ++ throw new ClassNotFoundException(name); ++ } ++ } ++ ++ ++ /* ++ * Define the JavaScript proxy classes ++ */ ++ private Class defineClass(String name, URL url) throws IOException { ++ byte[] b = getBytes(url); ++ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null); ++ if (!name.equals(TRAMPOLINE)) { ++ throw new IOException("JSClassLoader: bad name " + name); ++ } ++ return defineClass(name, b, 0, b.length, cs); ++ } ++ ++ ++ /* ++ * Returns the contents of the specified URL as an array of bytes. ++ */ ++ private static byte[] getBytes(URL url) throws IOException { ++ URLConnection uc = url.openConnection(); ++ if (uc instanceof java.net.HttpURLConnection) { ++ java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc; ++ int code = huc.getResponseCode(); ++ if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) { ++ throw new IOException("open HTTP connection failed."); ++ } ++ } ++ int len = uc.getContentLength(); ++ InputStream in = new BufferedInputStream(uc.getInputStream()); ++ ++ byte[] b; ++ try { ++ if (len != -1) { ++ // Read exactly len bytes from the input stream ++ b = new byte[len]; ++ while (len > 0) { ++ int n = in.read(b, b.length - len, len); ++ if (n == -1) { ++ throw new IOException("unexpected EOF"); ++ } ++ len -= n; ++ } ++ } else { ++ b = new byte[8192]; ++ int total = 0; ++ while ((len = in.read(b, total, b.length - total)) != -1) { ++ total += len; ++ if (total >= b.length) { ++ byte[] tmp = new byte[total * 2]; ++ System.arraycopy(b, 0, tmp, 0, total); ++ b = tmp; ++ } ++ } ++ // Trim array to correct size, if necessary ++ if (total != b.length) { ++ byte[] tmp = new byte[total]; ++ System.arraycopy(b, 0, tmp, 0, total); ++ b = tmp; ++ } ++ } ++ } finally { ++ in.close(); ++ } ++ return b; ++ } ++ ++ ++ protected PermissionCollection getPermissions(CodeSource codesource) ++ { ++ PermissionCollection perms = super.getPermissions(codesource); ++ perms.add(new AllPermission()); ++ return perms; ++ } ++} diff --git a/java/jdk16/files/patch-javascript_JSInvoke.java b/java/jdk16/files/patch-javascript_JSInvoke.java new file mode 100644 index 000000000000..fc692b9cb9c1 --- /dev/null +++ b/java/jdk16/files/patch-javascript_JSInvoke.java @@ -0,0 +1,26 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSInvoke.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/JSInvoke.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,21 @@ ++/* ++ * @(#)JSInvoke.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++ ++package sun.plugin.javascript.invoke; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.InvocationTargetException; ++ ++/* ++ * JavaScript to Java invocation trampoline class. ++ */ ++class JSInvoke { ++ private static Object invoke(Method m, Object obj, Object[] params) ++ throws InvocationTargetException, IllegalAccessException { ++ return m.invoke(obj, params); ++ } ++} diff --git a/java/jdk16/files/patch-javascript_ReflectUtil.java b/java/jdk16/files/patch-javascript_ReflectUtil.java new file mode 100644 index 000000000000..827bd0c666ce --- /dev/null +++ b/java/jdk16/files/patch-javascript_ReflectUtil.java @@ -0,0 +1,312 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/javascript/ReflectUtil.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,307 @@ ++/* ++ * @(#)ReflectUtil.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++package sun.plugin.javascript; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.lang.reflect.InvocationTargetException; ++import java.util.HashMap; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++import java.util.Iterator; ++import sun.plugin.javascript.JSClassLoader; ++ ++public class ReflectUtil { ++ /* ++ * Discover the public methods on public classes ++ * and interfaces accessible to the calling ++ * JavaScript code. ++ */ ++ public static Method[] getJScriptMethods(Class cls) { ++ List m = new ArrayList(); /* the valid methods we find */ ++ ++ /* ++ * Temporary map of method signatures when we decide ++ * that a simple call to target.getMethods() returns ++ * inaccessible methods and we must search for alternative ++ * supermethods that might be accessible. We can toss ++ * this when we're done searching. ++ */ ++ Map sigs = new HashMap(); ++ ++ while (cls != null) { ++ boolean done = getPublicMethods(cls, m, sigs); ++ if (done) { ++ break; ++ } ++ getJScriptInterfaceMethods(cls, m, sigs); ++ cls = cls.getSuperclass(); ++ } ++ return (Method[]) m.toArray(new Method[m.size()]); ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ private static void getJScriptInterfaceMethods(Class cls, List m, Map sigs) { ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length; i++) { ++ Class intf = intfs[i]; ++ boolean done = getPublicMethods(intf, m, sigs); ++ if (!done) { ++ getJScriptInterfaceMethods(intf, m, sigs); ++ } ++ } ++ } ++ ++ /* ++ * ++ * Process the methods in this class or interface ++ */ ++ private static boolean getPublicMethods(Class cls, List m, Map sigs) { ++ Method[] methods = null; ++ try { ++ ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's methods. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return false; ++ } ++ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return false; ++ } ++ ++ methods = cls.getMethods(); ++ } catch (SecurityException se) { ++ return false; ++ } ++ ++ /* ++ * Check for inherited methods with non-public ++ * declaring classes. They might override and hide ++ * methods from their superclasses or ++ * superinterfaces. ++ */ ++ boolean done = true; ++ for (int i=0; i < methods.length; i++) { ++ Class dc = methods[i].getDeclaringClass(); ++ if (!Modifier.isPublic(dc.getModifiers())) { ++ done = false; ++ break; ++ } ++ } ++ ++ /* ++ * Belatedly initialize the signature map if ++ * this is not the first time here. ++ */ ++ if (sigs.isEmpty() && !m.isEmpty()) { ++ initSignatureMap(m, sigs); ++ } ++ ++ if (done) { ++ /* ++ * We're done. Spray all the methods into ++ * the list and then we're out of here. ++ */ ++ for (int i=0; i < methods.length; i++) { ++ addMethod(m, sigs, methods[i]); ++ } ++ } else { ++ /* ++ * Simulate cls.getDeclaredMethods() by ++ * stripping away inherited methods. ++ */ ++ for (int i=0; i < methods.length; i++) { ++ Class dc = methods[i].getDeclaringClass(); ++ if (cls.equals(dc)) { ++ addMethod(m, sigs, methods[i]); ++ } ++ } ++ } ++ return done; ++ } ++ ++ private static void initSignatureMap(List m, Map sigs) { ++ Iterator i = m.iterator(); ++ while (i.hasNext()) { ++ Method entry = (Method) i.next(); ++ sigs.put(getSignature(entry), entry); ++ } ++ } ++ ++ private static void addMethod(List m, Map sigs, Method method) { ++ /* ++ * Avoid work. We ignore the signature matching ++ * until the map is initialized in initSignatureMap. ++ * This has the effect of avoiding the signature ++ * work for the first call of getPublicMethods(). ++ */ ++ if (sigs.isEmpty()) { ++ m.add(method); ++ return; ++ } ++ ++ /* ++ * Avoid adding duplicate accessible methods on ++ * the list. ++ */ ++ String signature = getSignature(method); ++ if (!sigs.containsKey(signature)) { ++ m.add(method); ++ sigs.put(signature, method); ++ } ++ } ++ ++ /* ++ * Return a canonical method signature for the method. ++ * We care only about the simple method name and the ++ * the number, type and order of the parameters. ++ * Exception declarations are not part of a method ++ * signature nor is the return type. ++ */ ++ private static String getSignature(Method method) { ++ StringBuffer sb = new StringBuffer(); ++ ++ sb.append(method.getName()); ++ Class[] params = method.getParameterTypes(); ++ sb.append('('); ++ if (params.length > 0) { ++ sb.append(params[0].getName()); ++ } ++ for (int i=1; i < params.length; i++) { ++ sb.append(','); ++ sb.append(params[i].getName()); ++ } ++ sb.append(')'); ++ ++ return sb.toString(); ++ } ++ ++ /* ++ * Discover the public fields on public classes ++ * and interfaces accessible to the calling ++ * JavaScript code. ++ */ ++ public static Field[] getJScriptFields(Class cls) { ++ List m = new ArrayList(); /* the valid fields we find */ ++ ++ /* ++ * Temporary map of field name when we decide ++ * that a simple call to target.getFields() returns ++ * inaccessible fields and we must search for alternative ++ * supermethods that might be accessible. We can toss ++ * this when we're done searching. ++ */ ++ Map names = new HashMap(); ++ ++ while (cls != null) { ++ boolean done = getPublicFields(cls, m, names); ++ if (done) { ++ break; ++ } ++ getJScriptInterfaceFields(cls, m, names); ++ cls = cls.getSuperclass(); ++ } ++ return (Field[]) m.toArray(new Field[m.size()]); ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ private static void getJScriptInterfaceFields(Class cls, List m, Map names) { ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length; i++) { ++ Class intf = intfs[i]; ++ boolean done = getPublicFields(intf, m, names); ++ if (!done) { ++ getJScriptInterfaceFields(intf, m, names); ++ } ++ } ++ } ++ ++ /* ++ * ++ * Process the fields in this class or interface ++ */ ++ private static boolean getPublicFields(Class cls, List m, Map names) { ++ Field[] fields = null; ++ try { ++ ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's fields. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return false; ++ } ++ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return false; ++ } ++ fields = cls.getFields(); ++ } catch (SecurityException se) { ++ return false; ++ } ++ ++ /* ++ * Check for inherited fields with non-public ++ * declaring classes. They might hide ++ * fields from public classes or interfaces. ++ */ ++ boolean done = true; ++ for (int i=0; i < fields.length; i++) { ++ Class dc = fields[i].getDeclaringClass(); ++ if (!Modifier.isPublic(dc.getModifiers())) { ++ done = false; ++ break; ++ } ++ } ++ if (done) { ++ /* ++ * We're done. Spray all the fields into ++ * the list and then we're out of here. ++ */ ++ for (int i=0; i < fields.length; i++) { ++ addField(m, names, fields[i]); ++ } ++ } else { ++ /* ++ * Simulate cls.getDeclaredFields() by ++ * stripping away inherited fields. ++ */ ++ for (int i=0; i < fields.length; i++) { ++ Class dc = fields[i].getDeclaringClass(); ++ if (cls.equals(dc)) { ++ addField(m, names, fields[i]); ++ } ++ } ++ } ++ return done; ++ } ++ ++ private static void addField(List m, Map names, Field field) { ++ /* ++ * Avoid adding duplicate accessible fields on ++ * the list. ++ */ ++ String name = field.getName(); ++ if (!names.containsKey(name)) { ++ m.add(field); ++ names.put(name, field); ++ } ++ } ++} ++ ++ diff --git a/java/jdk16/files/patch-liveconnect_ReplaceMethod.java b/java/jdk16/files/patch-liveconnect_ReplaceMethod.java new file mode 100644 index 000000000000..829e43452e6c --- /dev/null +++ b/java/jdk16/files/patch-liveconnect_ReplaceMethod.java @@ -0,0 +1,93 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/ReplaceMethod.java 1 Jan 1970 00:00:00 -0000 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/ReplaceMethod.java 3 Dec 2004 03:56:58 -0000 1.1 +@@ -0,0 +1,88 @@ ++/* ++ * @(#)ReplaceMethod.java 1.1 04/06/20 ++ * ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. ++ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. ++ */ ++package sun.plugin.liveconnect; ++ ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import sun.plugin.javascript.JSClassLoader; ++ ++public class ReplaceMethod { ++ /* ++ * Replace the inaccessible method by a suitable method on public ++ * class/interface accessible to the calling JavaScript code. ++ * Returns null if accessible method is not found. ++ */ ++ static Method getJScriptMethod(Method start) { ++ Class cls = start.getDeclaringClass(); ++ ++ if (Modifier.isPublic(cls.getModifiers())) { ++ return start; ++ } ++ ++ String name = start.getName(); ++ Class[] params = start.getParameterTypes(); ++ ++ Method result = null; ++ while (cls != null && result == null) { ++ result = getPublicMethod(cls, name, params); ++ if (result == null) { ++ result = getJScriptInterfaceMethod(cls, name, params); ++ } ++ cls = cls.getSuperclass(); ++ } ++ return result; ++ } ++ ++ /* ++ * Process the immediate interfaces of this class or interface. ++ */ ++ static Method getJScriptInterfaceMethod(Class cls, String name, Class[] params) { ++ Method result = null; ++ Class[] intfs = cls.getInterfaces(); ++ for (int i=0; i < intfs.length && result == null; i++) { ++ Class intf = intfs[i]; ++ result = getPublicMethod(intf, name, params); ++ if (result == null) { ++ result = getJScriptInterfaceMethod(intf, name, params); ++ } ++ } ++ return result; ++ } ++ ++ /* ++ * ++ * Process the methods in this class or interface ++ */ ++ static private Method getPublicMethod(Class cls, String name, Class[] params) { ++ try { ++ /* ++ * This class or interface is non-public so we ++ * can't use any of it's methods. Go back and ++ * try again with a superclass or superinterface. ++ */ ++ if (!Modifier.isPublic(cls.getModifiers())) { ++ return null; ++ } ++ ++ /* ++ * This call will fail if 'cls' is in a restricted ++ * package and we don't have permission to access ++ * it. ++ */ ++ if (!JSClassLoader.isPackageAccessible(cls)) { ++ return null; ++ } ++ return cls.getMethod(name, params); ++ } catch (NoSuchMethodException nsme) { ++ return null; ++ } catch (SecurityException se) { ++ return null; ++ } ++ } ++} ++ ++ diff --git a/java/jdk16/files/patch-liveconnect_SecureInvocation.java b/java/jdk16/files/patch-liveconnect_SecureInvocation.java new file mode 100644 index 000000000000..961414277909 --- /dev/null +++ b/java/jdk16/files/patch-liveconnect_SecureInvocation.java @@ -0,0 +1,351 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/SecureInvocation.java 22 Oct 2003 23:04:21 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/liveconnect/SecureInvocation.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* + * @(#)SecureInvocation.java 1.21 02/08/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,7 +9,8 @@ + + import java.lang.reflect.Constructor; + import java.lang.reflect.Field; +-import java.lang.reflect.Method;
++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; + import java.lang.Thread; + import java.io.FilePermission; + import java.security.AccessControlContext; +@@ -29,7 +30,10 @@ + import java.net.URL; + import java.net.MalformedURLException; + import sun.plugin.util.Trace; +-import sun.plugin.services.PlatformService;
++import sun.plugin.services.PlatformService; ++import sun.plugin.javascript.JSClassLoader; ++import sun.plugin.javascript.ReflectUtil; ++ + + /** + * <P> SecureInvocation is for implementating nsISecureJNI which allows +@@ -98,64 +102,64 @@ + throw e; + } + } +-
+- static class CallMethodThread extends Thread {
+- public CallMethodThread(int handle, Class clazz, Object obj, Method method, Object[] args,
+- String origin, boolean isUniversalBrowserRead,
+- boolean isUniversalJavaPermission) {
+- this.handle = handle;
+- this.clazz = clazz;
+- this.obj = obj;
+- this.method = method;
+- this.args = args;
+- this.origin = origin;
+- this.isUniversalBrowserRead = isUniversalBrowserRead;
+- this.isUniversalJavaPermission = isUniversalJavaPermission;
+- }
+-
+- public void run() {
+- try {
+- result = CallMethod(clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission);
+- }
+- catch(Exception e) {
+- exception = e;
+- }
+- finally {
+- PlatformService.getService().signalEvent(handle);
+- }
+- }
+-
+-
+- public Object getResult() throws Exception {
+- if(exception != null)
+- throw exception;
+- return result;
+- }
+-
+- private Exception exception = null;
+- private Object result = null;
+-
+- private int handle;
+- private Class clazz;
+- private Object obj;
+- private Method method;
+- private Object[] args;
+- private String origin;
+- private boolean isUniversalBrowserRead;
+- private boolean isUniversalJavaPermission;
+-
+- }
+- +- public static Object CallMethod(final int handle, final Class clazz, final Object obj, final Method method, final Object[] args,
+- final String origin, final boolean isUniversalBrowserRead,
+- final boolean isUniversalJavaPermission)
+- throws Exception {
+- CallMethodThread callThread = new CallMethodThread(handle, clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission);
+- callThread.start();
+- PlatformService.getService().waitEvent(handle);
+- return callThread.getResult();
+- }
+-
++ ++ static class CallMethodThread extends Thread { ++ public CallMethodThread(int handle, Class clazz, Object obj, Method method, Object[] args, ++ String origin, boolean isUniversalBrowserRead, ++ boolean isUniversalJavaPermission) { ++ this.handle = handle; ++ this.clazz = clazz; ++ this.obj = obj; ++ this.method = method; ++ this.args = args; ++ this.origin = origin; ++ this.isUniversalBrowserRead = isUniversalBrowserRead; ++ this.isUniversalJavaPermission = isUniversalJavaPermission; ++ } ++ ++ public void run() { ++ try { ++ result = CallMethod(clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission); ++ } ++ catch(Exception e) { ++ exception = e; ++ } ++ finally { ++ PlatformService.getService().signalEvent(handle); ++ } ++ } ++ ++ ++ public Object getResult() throws Exception { ++ if(exception != null) ++ throw exception; ++ return result; ++ } ++ ++ private Exception exception = null; ++ private Object result = null; ++ ++ private int handle; ++ private Class clazz; ++ private Object obj; ++ private Method method; ++ private Object[] args; ++ private String origin; ++ private boolean isUniversalBrowserRead; ++ private boolean isUniversalJavaPermission; ++ ++ } ++ ++ public static Object CallMethod(final int handle, final Class clazz, final Object obj, final Method method, final Object[] args, ++ final String origin, final boolean isUniversalBrowserRead, ++ final boolean isUniversalJavaPermission) ++ throws Exception { ++ CallMethodThread callThread = new CallMethodThread(handle, clazz, obj, method, args, origin, isUniversalBrowserRead, isUniversalJavaPermission); ++ callThread.start(); ++ PlatformService.getService().waitEvent(handle); ++ return callThread.getResult(); ++ } ++ + + /** + * <P> Call a method on Java object with security context. +@@ -197,8 +201,8 @@ + AccessControlContext context = new AccessControlContext(domains); + + // Perform the method invocation. +- return AccessController.doPrivileged(new PrivilegedCallMethodAction(method, obj, args), +- context); ++ return AccessController.doPrivileged(new PrivilegedCallMethodAction(method, ++ obj, args), context); + } catch (Exception e) { + Trace.liveConnectPrintException(e); + throw e; +@@ -323,32 +327,6 @@ + } + } + +- +- /** +- * <P> Set up a protection domain according to the origin and +- * the other security related information. +- */ +- private static ProtectionDomain getProtectionDomain(Class clazz, +- String origin, +- boolean byPassOrigin, +- boolean allPermission) +- throws OriginNotAllowedException, MalformedURLException +- { +- boolean trust = false; +- +- // First, check if the call is allowed +- checkLiveConnectCaller(clazz, origin, byPassOrigin); +- +- if (allPermission) +- { +- return getTrustedProtectionDomain(); +- } +- else +- { +- return getDefaultProtectionDomain(origin); +- } +- } +- + /** + * <P> Check if LiveConnect call is allowed at all. + * </P> +@@ -447,7 +425,7 @@ + + // Obtain Java policy + Policy policy = Policy.getPolicy(); +- CodeSource cs = new CodeSource(url, null); ++ CodeSource cs = new CodeSource(url, (java.security.cert.Certificate[])null); + final PermissionCollection pc = policy.getPermissions(cs); + + if (url == null || url.getProtocol().equals("file")) { +@@ -516,16 +494,19 @@ + + PrivilegedConstructObjectAction(Constructor constructor, Object[] args) + { +- this.constructor = constructor; +- this.args = args; ++ this.constructor = constructor; ++ this.args = args; + +- // Ensure the argument is not null +- if (this.args == null) +- this.args = new Object[0]; ++ // Ensure the argument is not null ++ if (this.args == null) ++ this.args = new Object[0]; + } + + public Object run() throws Exception { +- return constructor.newInstance(args); ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(constructor.getDeclaringClass()); ++ ++ return constructor.newInstance(args); + } + } + +@@ -543,17 +524,54 @@ + + PrivilegedCallMethodAction(Method method, Object obj, Object[] args) + { +- this.method = method; +- this.obj = obj; +- this.args = args; +- +- // Ensure the argument is not null +- if (this.args == null) +- this.args = new Object[0]; ++ this.method = method; ++ ++ this.obj = obj; ++ this.args = args; ++ ++ // Ensure the argument is not null ++ if (this.args == null) ++ this.args = new Object[0]; + } + + public Object run() throws Exception { +- return method.invoke(obj, args); ++ /* ++ * Browser uses reflection to collect methods/fields/constructors ++ * through this method call. Therefore JSClassLoader is not used ++ * in such cases. However it requires filtering to avoid exposing ++ * inaccessible methods/fields/constructors. ++ * ++ * Also, Mozilla ignores abstract methods, therefore those are ++ * replaced by the concrete class methods ++ */ ++ if(obj instanceof Class) { ++ String name = method.getName(); ++ Class cls = (Class)obj; ++ if(name.equals("getMethods")) { ++ Method[] methods = ReflectUtil.getJScriptMethods(cls); ++ for (int i=0; i < methods.length; i++) { ++ Method m = methods[i]; ++ if (Modifier.isAbstract(m.getModifiers())) { ++ Class[] params = m.getParameterTypes(); ++ methods[i] = cls.getMethod(m.getName(), params); ++ } ++ } ++ return methods; ++ }else if (name.equals("getFields")) { ++ return ReflectUtil.getJScriptFields(cls); ++ }else if (name.equals("getConstructors")) { ++ if (!Modifier.isPublic(cls.getModifiers()) || ++ !JSClassLoader.isPackageAccessible(cls)) { ++ return new Constructor[0]; ++ } ++ } ++ } ++ ++ Method actualMethod = ReplaceMethod.getJScriptMethod(method); ++ if(actualMethod != null) ++ return JSClassLoader.invoke(actualMethod, obj, args); ++ else ++ throw new NoSuchMethodException(method.getName()); + } + } + +@@ -564,18 +582,20 @@ + * </P> + */ + class PrivilegedGetFieldAction implements PrivilegedExceptionAction { +- + Field field; + Object obj; + + PrivilegedGetFieldAction(Field field, Object obj) + { +- this.field = field; +- this.obj = obj; ++ this.field = field; ++ this.obj = obj; + } + +- public Object run() throws Exception { +- return field.get(obj); ++ public Object run() throws Exception { ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(field.getDeclaringClass()); ++ ++ return field.get(obj); + } + } + +@@ -593,15 +613,18 @@ + + PrivilegedSetFieldAction(Field field, Object obj, Object val) + { +- this.field = field; +- this.obj = obj; +- this.val = val; ++ this.field = field; ++ this.obj = obj; ++ this.val = val; + } + + public Object run() throws Exception { +- field.set(obj, val); ++ /* Check whether the caller has package access permission */ ++ JSClassLoader.checkPackageAccess(field.getDeclaringClass()); ++ ++ field.set(obj, val); + return null; + } + } +-
+-
++ ++ diff --git a/java/jdk16/files/patch-plugin_DispatchImpl.java b/java/jdk16/files/patch-plugin_DispatchImpl.java new file mode 100644 index 000000000000..abb65a60953e --- /dev/null +++ b/java/jdk16/files/patch-plugin_DispatchImpl.java @@ -0,0 +1,331 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/com/DispatchImpl.java 22 Oct 2003 23:04:20 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/com/DispatchImpl.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* +- * @(#)DispatchImpl.java 1.6 03/01/23 ++ * @(#)DispatchImpl.java 1.16 04/06/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,8 +9,32 @@ + + import sun.plugin.util.Trace; + import sun.plugin.javascript.ocx.JSObject; +-import java.applet.Applet; ++import sun.plugin.liveconnect.JavaScriptProtectionDomain; + import sun.plugin.viewer.context.IExplorerAppletContext; ++import sun.plugin.security.PluginClassLoader; ++import java.applet.Applet; ++import java.net.URL; ++import java.net.MalformedURLException; ++import java.net.InetAddress; ++import java.net.UnknownHostException; ++import java.net.SocketPermission; ++import java.io.FilePermission; ++import java.io.File; ++import java.security.AccessControlContext; ++import java.security.AccessController; ++import java.security.CodeSource; ++import java.security.Policy; ++import java.security.ProtectionDomain; ++import java.security.AllPermission; ++import java.security.Permissions; ++import java.security.Permission; ++import java.security.PermissionCollection; ++import java.security.PrivilegedAction; ++import java.security.PrivilegedExceptionAction; ++import java.security.AccessControlException; ++import java.security.PrivilegedActionException; ++import sun.net.www.ParseUtil; ++import sun.security.util.SecurityConstants; + + /** + * DispatchImpl encapsulates a Java Object and provides Dispatch interface +@@ -22,14 +46,19 @@ + { + JavaClass targetClass = null; + Object targetObj = null; ++ int handle = 0; ++ int wndHandle = 0; ++ AccessControlContext context = null; ++ boolean isBridge = false; + + /* + * Constructor + * @param obj the object to be wrapped + */ +- public DispatchImpl(Object obj) ++ public DispatchImpl(Object obj, int id) + { + targetObj = obj; ++ handle = id; + } + + /** +@@ -40,19 +69,87 @@ + * @param params Arguments. + * @return Java object. + */ +- public Object invoke(int flag, int index, Object []params) ++ public Object invoke(final int flag, final int index, final Object []params) ++ throws Exception ++ { ++ try { ++ //No security constraints in case of ActiveX bridge application ++ if(isBridge) ++ return invokeImpl(flag, index, params); ++ ++ if(context == null) { ++ context = createContext(); ++ } ++ ++ // Invoke the method within the applet sand box security restricitions ++ return AccessController.doPrivileged( ++ new PrivilegedExceptionAction() { ++ public Object run() throws Exception{ ++ return invokeImpl(flag, index, params); ++ } ++ }, context ++ ); ++ }catch(Exception exc) { ++ Throwable cause = exc.getCause(); ++ if(cause == null) { ++ cause = exc; ++ } ++ ++ Trace.liveConnectPrintException(cause); ++ throw new Exception(cause.toString()); ++ } ++ } ++ ++ public AccessControlContext createContext() { ++ try { ++ ProtectionDomain[] domains = new ProtectionDomain[1]; ++ //Obtain the java code origin ++ ProtectionDomain pd = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ return targetObj.getClass().getProtectionDomain(); ++ } ++ }); ++ ++ CodeSource cs = null; ++ URL url = null; ++ if(pd != null) ++ cs = pd.getCodeSource(); ++ if(cs != null) ++ url = cs.getLocation(); ++ ++ domains[0] = getJSProtectionDomain(url, targetObj.getClass()); ++ return new AccessControlContext(domains); ++ }catch(Exception exc) { ++ Trace.liveConnectPrintException(exc); ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Invoke a method according to the method index. ++ * ++ * @param flag Invoke flag ++ * @param index Method index ++ * @param params Arguments. ++ * @return Java object. ++ */ ++ public Object invokeImpl(int flag, int index, Object []params) + throws Exception + { + Object retObj = null; + Dispatcher disp = null; + try { +- convertParams(params); ++ if(params != null) ++ convertParams(params); + disp = targetClass.getDispatcher(flag, index, params); +- return disp.invoke(targetObj, params); +- } +- catch (Throwable e) +- { +- //e.printStackTrace(); ++ if(disp != null) { ++ retObj = disp.invoke(targetObj, params); ++ if(retObj != null) ++ retObj = Utils.convertReturn(disp.getReturnType(), retObj, handle); ++ } ++ return retObj; ++ } catch (Throwable e) { + Throwable cause = e.getCause(); + if(cause == null) { + cause = e; +@@ -82,11 +179,39 @@ + return targetClass; + } + ++ public int getReturnType(int id){ ++ return targetClass.getReturnType(id); ++ } ++ ++ public int getIdForName(final String name) throws Exception{ ++ try { ++ //No security constraints in case of ActiveX bridge application ++ if(isBridge) ++ return getIdForNameImpl(name); ++ ++ if(context == null) { ++ context = createContext(); ++ } ++ ++ // Invoke the method within the applet sand box security restricitions ++ Integer retVal = (Integer)AccessController.doPrivileged( ++ new PrivilegedExceptionAction() { ++ public Object run() throws Exception{ ++ return new Integer(getIdForNameImpl(name)); ++ } ++ }, context ++ ); ++ return retVal.intValue(); ++ }catch(PrivilegedActionException pe) { ++ } ++ ++ return -1; ++ } + + /* + * + */ +- public int getIdForName(String name) throws Exception{ ++ public int getIdForNameImpl(String name) throws Exception{ + int id = -1; + + if(targetClass == null && targetObj != null) { +@@ -103,27 +228,122 @@ + } + + /* +- * ++ * Unwraps the wrapped java object arguments + */ + private void convertParams(Object []params) { + for(int i=0;i<params.length;i++) { + if(params[i] != null && params[i] instanceof DispatchImpl) { + params[i] = ((DispatchImpl)params[i]).getWrappedObject(); + } else if(params[i] != null && params[i] instanceof DispatchClient){ +- JSObject jsObj = new JSObject((DispatchClient)params[i]); +- jsObj.setIExplorerAppletContext((IExplorerAppletContext) ++ JSObject jsObj = null; ++ if (!isBridge) { ++ jsObj = new JSObject((DispatchClient)params[i]); ++ jsObj.setIExplorerAppletContext((IExplorerAppletContext) + ((Applet)targetObj).getAppletContext()); ++ } else { ++ jsObj = new JSObject((DispatchClient)params[i], handle); ++ } + params[i] = jsObj; + } + } + } + ++ /** ++ * Returns a protection domain that represents the default permission ++ * for a given URL. ++ * ++ * @param urlString URL ++ * @return protection domain. ++ */ ++ public static ProtectionDomain getJSProtectionDomain(URL url, Class clazz) ++ throws MalformedURLException { ++ ++ // Obtain default java applet policy ++ Policy policy = (Policy)AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ return Policy.getPolicy(); ++ } ++ }); ++ ++ CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null); ++ final PermissionCollection pc = policy.getPermissions(cs); ++ if(url != null) { ++ Permission p; ++ String path = null; ++ try { ++ p = url.openConnection().getPermission(); ++ } catch (java.io.IOException ioe) { ++ p = null; ++ } ++ ++ if (p instanceof FilePermission) { ++ path = p.getName(); ++ } else if ((p == null) && (url.getProtocol().equals("file"))) { ++ path = url.getFile().replace('/', File.separatorChar); ++ path = ParseUtil.decode(path); ++ } else if (p instanceof SocketPermission) { ++ /* ++ Socket permission to connect back to the host ++ */ ++ String host = url.getHost(); ++ pc.add(new SocketPermission(host, ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ } ++ ++ if(path != null && ++ (clazz.getClassLoader() instanceof PluginClassLoader)) { ++ //We need to add an additional permission to read recursively ++ if (path.endsWith(File.separator)) { ++ path += "-"; ++ } else { ++ int endIndex = path.lastIndexOf(File.separatorChar); ++ if (endIndex != -1) ++ path = path.substring(0, endIndex+1) + "-"; ++ } ++ ++ pc.add(new FilePermission(path, SecurityConstants.FILE_READ_ACTION)); ++ ++ /* ++ Socket permission to connect back to the "localhost" ++ */ ++ pc.add(new SocketPermission("localhost", ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ AccessController.doPrivileged(new PrivilegedAction() { ++ public Object run() { ++ try { ++ String host = InetAddress.getLocalHost().getHostName(); ++ pc.add(new SocketPermission(host, ++ SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); ++ } catch (UnknownHostException uhe) { ++ } ++ return null; ++ } ++ }); ++ } ++ } ++ ++ return new JavaScriptProtectionDomain(pc); ++ } ++ + public String toString() { + if(targetObj != null) { + return targetObj.toString(); + } + return null; + } ++ ++ public int getWindowHandle() { ++ if(wndHandle == 0) { ++ wndHandle = getWindowHandle(handle); ++ } ++ return wndHandle; ++ } ++ ++ protected void setBridge() { ++ isBridge = true; ++ } ++ ++ native int getWindowHandle(int id); + } + + diff --git a/java/jdk16/files/patch-plugin_FileList.gmk b/java/jdk16/files/patch-plugin_FileList.gmk new file mode 100644 index 000000000000..c5fca27bdda9 --- /dev/null +++ b/java/jdk16/files/patch-plugin_FileList.gmk @@ -0,0 +1,22 @@ +$FreeBSD$ + +--- ../../deploy/make/plugin/java/FileList.gmk 7 Nov 2003 12:15:52 -0000 1.2 ++++ ../../deploy/make/plugin/java/FileList.gmk 3 Dec 2004 03:56:58 -0000 1.3 +@@ -86,6 +86,9 @@ + \
+ sun/plugin/javascript/JSObject.java \
+ sun/plugin/javascript/JSContext.java \
++ sun/plugin/javascript/JSClassLoader.java \
++ sun/plugin/javascript/ReflectUtil.java \
++ sun/plugin/javascript/JSInvoke.java \
+ \
+ sun/plugin/javascript/navig/Navigator.java \
+ sun/plugin/javascript/navig/Document.java \
+@@ -125,6 +128,7 @@ + sun/plugin/liveconnect/JavaScriptPermission.java \
+ sun/plugin/liveconnect/SecurityContextHelper.java \
+ sun/plugin/liveconnect/LiveConnect.java \
++ sun/plugin/liveconnect/ReplaceMethod.java \
+ \
+ sun/plugin/extension/ExtensionInstallationImpl.java \
+ sun/plugin/extension/ExtensionInstaller.java \
diff --git a/java/jdk16/files/patch-plugin_MethodDispatcher.java b/java/jdk16/files/patch-plugin_MethodDispatcher.java new file mode 100644 index 000000000000..57e6d22b5a63 --- /dev/null +++ b/java/jdk16/files/patch-plugin_MethodDispatcher.java @@ -0,0 +1,41 @@ +$FreeBSD$ + +--- ../../deploy/src/plugin/src/share/classes/sun/plugin/com/MethodDispatcher.java 22 Oct 2003 23:04:20 -0000 1.1 ++++ ../../deploy/src/plugin/src/share/classes/sun/plugin/com/MethodDispatcher.java 3 Dec 2004 03:56:58 -0000 1.2 +@@ -1,7 +1,7 @@ + /* +- * @(#)MethodDispatcher.java 1.5 03/01/23 ++ * @(#)MethodDispatcher.java 1.10 04/06/20 + * +- * Copyright 2003 Sun Microsystems, Inc. All rights reserved. ++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +@@ -9,6 +9,7 @@ + + import java.lang.reflect.Method; + import sun.plugin.util.Trace; ++import sun.plugin.javascript.JSClassLoader; + + /** + * A <code>MethodDispatcher</code> provides information about, +@@ -47,11 +48,16 @@ + Object retObj = null; + if(method != null && obj != null) { + Trace.msgLiveConnectPrintln("com.method.invoke", new Object[] {method}); ++ Class theClass = obj.getClass(); + Object[] params = TypeConverter.convertObjectArray( + method.getParameterTypes(), args); +- retObj = Utils.convertReturn( method.getReturnType(), +- method.invoke(obj, params )); ++ // check if the class is private and the method is public ++ retObj = JSClassLoader.invoke(method, obj, params); + } + return retObj; ++ } ++ ++ public Class getReturnType() { ++ return method.getReturnType(); + } + } |