aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorglewis <glewis@FreeBSD.org>2004-12-04 03:53:44 +0800
committerglewis <glewis@FreeBSD.org>2004-12-04 03:53:44 +0800
commit85df37779480465b148f128b0d8a3bd92b332a6e (patch)
treecd5431c249a49d6c40819feeb0abb16d7b742b07 /java
parent3164f2f687feb34021d95eae8265174f740c2670 (diff)
downloadfreebsd-ports-gnome-85df37779480465b148f128b0d8a3bd92b332a6e.tar.gz
freebsd-ports-gnome-85df37779480465b148f128b0d8a3bd92b332a6e.tar.zst
freebsd-ports-gnome-85df37779480465b148f128b0d8a3bd92b332a6e.zip
. Backport parts of the 1.5 plugin to address plugin vulnerabilities.
. Bump PORTVERSION. Submitted by: Kurt Miller <truk@optonline.net>
Diffstat (limited to 'java')
-rw-r--r--java/jdk14/Makefile4
-rw-r--r--java/jdk14/files/patch-javascript_JSClassLoader.java243
-rw-r--r--java/jdk14/files/patch-javascript_JSInvoke.java26
-rw-r--r--java/jdk14/files/patch-javascript_ReflectUtil.java312
-rw-r--r--java/jdk14/files/patch-liveconnect_ReplaceMethod.java93
-rw-r--r--java/jdk14/files/patch-liveconnect_SecureInvocation.java351
-rw-r--r--java/jdk14/files/patch-plugin_DispatchImpl.java331
-rw-r--r--java/jdk14/files/patch-plugin_FileList.gmk22
-rw-r--r--java/jdk14/files/patch-plugin_MethodDispatcher.java41
-rw-r--r--java/jdk15/Makefile4
-rw-r--r--java/jdk15/files/patch-javascript_JSClassLoader.java243
-rw-r--r--java/jdk15/files/patch-javascript_JSInvoke.java26
-rw-r--r--java/jdk15/files/patch-javascript_ReflectUtil.java312
-rw-r--r--java/jdk15/files/patch-liveconnect_ReplaceMethod.java93
-rw-r--r--java/jdk15/files/patch-liveconnect_SecureInvocation.java351
-rw-r--r--java/jdk15/files/patch-plugin_DispatchImpl.java331
-rw-r--r--java/jdk15/files/patch-plugin_FileList.gmk22
-rw-r--r--java/jdk15/files/patch-plugin_MethodDispatcher.java41
-rw-r--r--java/jdk16/Makefile4
-rw-r--r--java/jdk16/files/patch-javascript_JSClassLoader.java243
-rw-r--r--java/jdk16/files/patch-javascript_JSInvoke.java26
-rw-r--r--java/jdk16/files/patch-javascript_ReflectUtil.java312
-rw-r--r--java/jdk16/files/patch-liveconnect_ReplaceMethod.java93
-rw-r--r--java/jdk16/files/patch-liveconnect_SecureInvocation.java351
-rw-r--r--java/jdk16/files/patch-plugin_DispatchImpl.java331
-rw-r--r--java/jdk16/files/patch-plugin_FileList.gmk22
-rw-r--r--java/jdk16/files/patch-plugin_MethodDispatcher.java41
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();
+ }
+ }