8025758: Enhance Naming management
authorxuelei
Wed, 16 Oct 2013 18:19:11 -0700
changeset 22329 4cd45450d07c
parent 22328 5a7d30033602
child 22330 cafb826672bd
8025758: Enhance Naming management Summary: Enforce package access control with current context. Also reviewed by Alexander Fomin <alexander.fomin@oracle.com> Reviewed-by: weijun, ahgross
jdk/src/share/classes/com/sun/naming/internal/FactoryEnumeration.java
jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java
--- a/jdk/src/share/classes/com/sun/naming/internal/FactoryEnumeration.java	Wed Oct 16 13:26:05 2013 +0400
+++ b/jdk/src/share/classes/com/sun/naming/internal/FactoryEnumeration.java	Wed Oct 16 18:19:11 2013 -0700
@@ -56,9 +56,12 @@
      * references so as not to prevent GC of the class loader.  Each
      * weak reference is tagged with the factory's class name so the
      * class can be reloaded if the reference is cleared.
-
+     *
      * @param factories A non-null list
      * @param loader    The class loader of the list's contents
+     *
+     * This internal method is used with Thread Context Class Loader (TCCL),
+     * please don't expose this method as public.
      */
     FactoryEnumeration(List<NamedWeakReference<Object>> factories,
                        ClassLoader loader) {
@@ -79,7 +82,9 @@
 
             try {
                 if (answer == null) {   // reload class if weak ref cleared
-                    answer = Class.forName(className, true, loader);
+                    Class<?> cls = Class.forName(className, true, loader);
+                    VersionHelper12.checkPackageAccess(cls);
+                    answer = cls;
                 }
                 // Instantiate Class to get factory
                 answer = ((Class) answer).newInstance();
--- a/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java	Wed Oct 16 13:26:05 2013 +0400
+++ b/jdk/src/share/classes/com/sun/naming/internal/VersionHelper12.java	Wed Oct 16 18:19:11 2013 -0700
@@ -39,6 +39,7 @@
 import java.util.Properties;
 
 import javax.naming.*;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * VersionHelper was used by JNDI to accommodate differences between
@@ -53,21 +54,39 @@
 
 final class VersionHelper12 extends VersionHelper {
 
-    private boolean getSystemPropsFailed = false;
+    // workaround to disable additional package access control with
+    // Thread Context Class Loader (TCCL).
+    private final static boolean noPackageAccessWithTCCL = "true".equals(
+        AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return System.getProperty(
+                        "com.sun.naming.untieAccessContextWithTCCL");
+                }
+            }
+        ));
 
-    VersionHelper12() {} // Disallow external from creating one of these.
+    // Disallow external from creating one of these.
+    VersionHelper12() {
+    }
 
     public Class<?> loadClass(String className) throws ClassNotFoundException {
-        ClassLoader cl = getContextClassLoader();
-        return Class.forName(className, true, cl);
+        return loadClass(className, getContextClassLoader());
     }
 
     /**
-      * Package private.
-      */
+     * Package private.
+     *
+     * This internal method is used with Thread Context Class Loader (TCCL),
+     * please don't expose this method as public.
+     */
     Class<?> loadClass(String className, ClassLoader cl)
         throws ClassNotFoundException {
-        return Class.forName(className, true, cl);
+        Class<?> cls = Class.forName(className, true, cl);
+        if (!noPackageAccessWithTCCL) {
+            checkPackageAccess(cls);
+        }
+        return cls;
     }
 
     /**
@@ -75,13 +94,42 @@
      * @param codebase A non-null, space-separated list of URL strings.
      */
     public Class<?> loadClass(String className, String codebase)
-        throws ClassNotFoundException, MalformedURLException {
-        ClassLoader cl;
+            throws ClassNotFoundException, MalformedURLException {
 
         ClassLoader parent = getContextClassLoader();
-        cl = URLClassLoader.newInstance(getUrlArray(codebase), parent);
+        ClassLoader cl =
+                 URLClassLoader.newInstance(getUrlArray(codebase), parent);
+
+        return loadClass(className, cl);
+    }
 
-        return Class.forName(className, true, cl);
+    /**
+     * check package access of a class that is loaded with Thread Context
+     * Class Loader (TCCL).
+     *
+     * Similar to java.lang.ClassLoader.checkPackageAccess()
+     */
+    static void checkPackageAccess(Class<?> cls) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (ReflectUtil.isNonPublicProxyClass(cls)) {
+                for (Class<?> intf: cls.getInterfaces()) {
+                    checkPackageAccess(intf);
+                }
+                return;
+            }
+
+            final String name = cls.getName();
+            final int i = name.lastIndexOf('.');
+            if (i != -1) {
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    public Void run() {
+                        sm.checkPackageAccess(name.substring(0, i));
+                        return null;
+                    }
+                }, AccessController.getContext());
+            }
+        }
     }
 
     String getJndiProperty(final int i) {
@@ -99,16 +147,12 @@
     }
 
     String[] getJndiProperties() {
-        if (getSystemPropsFailed) {
-            return null;        // after one failure, don't bother trying again
-        }
         Properties sysProps = AccessController.doPrivileged(
             new PrivilegedAction<Properties>() {
                 public Properties run() {
                     try {
                         return System.getProperties();
                     } catch (SecurityException e) {
-                        getSystemPropsFailed = true;
                         return null;
                     }
                 }
@@ -173,7 +217,17 @@
         return new InputStreamEnumeration(urls);
     }
 
+    /**
+     * Package private.
+     *
+     * This internal method makes use of Thread Context Class Loader (TCCL),
+     * please don't expose this method as public.
+     *
+     * Please take care of package access control on the current context
+     * whenever using TCCL.
+     */
     ClassLoader getContextClassLoader() {
+
         return AccessController.doPrivileged(
             new PrivilegedAction<ClassLoader>() {
                 public ClassLoader run() {
@@ -183,7 +237,6 @@
         );
     }
 
-
     /**
      * Given an enumeration of URLs, an instance of this class represents
      * an enumeration of their InputStreams.  Each operation on the URL