# HG changeset patch # User mbalao # Date 1617771334 -3600 # Node ID f396f4a7ee5dc6621abd4c89b2c9cdb1b1096ca9 # Parent a7ef81ab119be3eba29743380402d46e38cae589 8244473: Contextualize registration for JNDI Reviewed-by: bae, andrew diff -r a7ef81ab119b -r f396f4a7ee5d src/share/classes/com/sun/jndi/ldap/Obj.java --- a/src/share/classes/com/sun/jndi/ldap/Obj.java Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/classes/com/sun/jndi/ldap/Obj.java Wed Apr 07 05:55:34 2021 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -235,6 +235,9 @@ String[] codebases = getCodebases(attrs.get(JAVA_ATTRIBUTES[CODEBASE])); try { if ((attr = attrs.get(JAVA_ATTRIBUTES[SERIALIZED_DATA])) != null) { + if (!VersionHelper12.isSerialDataAllowed()) { + throw new NamingException("Object deserialization is not allowed"); + } ClassLoader cl = helper.getURLClassLoader(codebases); return deserializeObject((byte[])attr.get(), cl); } else if ((attr = attrs.get(JAVA_ATTRIBUTES[REMOTE_LOC])) != null) { diff -r a7ef81ab119b -r f396f4a7ee5d src/share/classes/com/sun/jndi/ldap/VersionHelper12.java --- a/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java Wed Apr 07 05:55:34 2021 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,19 +39,48 @@ private static final String TRUST_URL_CODEBASE_PROPERTY = "com.sun.jndi.ldap.object.trustURLCodebase"; + // System property to control whether classes are allowed to be loaded from + // 'javaSerializedData' attribute + private static final String TRUST_SERIAL_DATA_PROPERTY = + "com.sun.jndi.ldap.object.trustSerialData"; + + /** + * Determines whether objects may be deserialized from the content of + * 'javaSerializedData' attribute. + */ + private static final boolean trustSerialData; + // Determine whether classes may be loaded from an arbitrary URL code base. - private static final String trustURLCodebase = - AccessController.doPrivileged( - new PrivilegedAction() { - public String run() { - return System.getProperty(TRUST_URL_CODEBASE_PROPERTY, - "false"); - } - } - ); + private static final boolean trustURLCodebase; + + static { + String trust = getPrivilegedProperty(TRUST_URL_CODEBASE_PROPERTY, "false"); + trustURLCodebase = "true".equalsIgnoreCase(trust); + String trustSDString = getPrivilegedProperty(TRUST_SERIAL_DATA_PROPERTY, "true"); + trustSerialData = "true".equalsIgnoreCase(trustSDString); + } + + private static String getPrivilegedProperty(String propertyName, String defaultVal) { + PrivilegedAction action = () -> System.getProperty(propertyName, defaultVal); + if (System.getSecurityManager() == null) { + return action.run(); + } else { + return AccessController.doPrivileged(action); + } + } VersionHelper12() {} // Disallow external from creating one of these. + /** + * Returns true if deserialization of objects from 'javaSerializedData' + * LDAP attribute is allowed. + * + * @return true if deserialization is allowed; false - otherwise + */ + public static boolean isSerialDataAllowed() { + return trustSerialData; + } + ClassLoader getURLClassLoader(String[] url) throws MalformedURLException { ClassLoader parent = getContextClassLoader(); @@ -60,7 +89,7 @@ * the system property com.sun.jndi.ldap.object.trustURLCodebase * has been set to "true". */ - if (url != null && "true".equalsIgnoreCase(trustURLCodebase)) { + if (url != null && trustURLCodebase) { return URLClassLoader.newInstance(getUrlArray(url), parent); } else { return parent; diff -r a7ef81ab119b -r f396f4a7ee5d src/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/naming/internal/ObjectFactoriesFilter.java Wed Apr 07 05:55:34 2021 +0100 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.naming.internal; + +import javax.naming.Reference; + +import sun.misc.ObjectInputFilter; +import sun.misc.ObjectInputFilter.FilterInfo; +import sun.misc.ObjectInputFilter.Status; + +import sun.security.util.SecurityProperties; + +/** + * This class implements the filter that validates object factories classes instantiated + * during {@link Reference} lookups. + * There is one system-wide filter instance per VM that can be set via + * the {@code "jdk.jndi.object.factoriesFilter"} system property value, or via + * setting the property in the security properties file. The system property value supersedes + * the security property value. If none of the properties are specified the default + * "*" value is used. + * The filter is implemented as {@link ObjectInputFilter} with capabilities limited to the + * validation of a factory's class types only ({@linkplain FilterInfo#serialClass()}). + * Array length, number of object references, depth, and stream size filtering capabilities are + * not supported by the filter. + */ +public final class ObjectFactoriesFilter { + + /** + * Checks if serial filter configured with {@code "jdk.jndi.object.factoriesFilter"} + * system property value allows instantiation of the specified objects factory class. + * If the filter result is not {@linkplain Status#REJECTED REJECTED}, the filter will + * allow the instantiation of objects factory class. + * + * @param factoryClass objects factory class + * @return true - if the factory is allowed to be instantiated; false - otherwise + */ + public static boolean canInstantiateObjectsFactory(Class factoryClass) { + return checkInput(() -> factoryClass); + } + + private static boolean checkInput(FactoryInfo factoryInfo) { + Status result = GLOBAL.checkInput(factoryInfo); + return result != Status.REJECTED; + } + + // FilterInfo to check if objects factory class is allowed by the system-wide + // filter. Array length, number of object references, depth, and stream size + // capabilities are ignored. + @FunctionalInterface + private interface FactoryInfo extends FilterInfo { + @Override + default long arrayLength() { + return -1; + } + + @Override + default long depth() { + return 1; + } + + @Override + default long references() { + return 0; + } + + @Override + default long streamBytes() { + return 0; + } + } + + // Prevent instantiation of the factories filter class + private ObjectFactoriesFilter() { + throw new InternalError("Not instantiable"); + } + + // System property name that contains the patterns to filter object factory names + private static final String FACTORIES_FILTER_PROPNAME = "jdk.jndi.object.factoriesFilter"; + + // Default system property value that allows the load of any object factory classes + private static final String DEFAULT_SP_VALUE = "*"; + + // System wide object factories filter constructed from the system property + private static final ObjectInputFilter GLOBAL = + ObjectInputFilter.Config.createFilter(getFilterPropertyValue()); + + // Get security or system property value + private static String getFilterPropertyValue() { + String propVal = SecurityProperties.privilegedGetOverridable(FACTORIES_FILTER_PROPNAME); + return propVal != null ? propVal : DEFAULT_SP_VALUE; + } +} diff -r a7ef81ab119b -r f396f4a7ee5d src/share/classes/com/sun/naming/internal/VersionHelper.java --- a/src/share/classes/com/sun/naming/internal/VersionHelper.java Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/classes/com/sun/naming/internal/VersionHelper.java Wed Apr 07 05:55:34 2021 +0100 @@ -77,6 +77,9 @@ return helper; } + public abstract Class loadClassWithoutInit(String className) + throws ClassNotFoundException; + public abstract Class loadClass(String className) throws ClassNotFoundException; diff -r a7ef81ab119b -r f396f4a7ee5d src/share/classes/com/sun/naming/internal/VersionHelper12.java --- a/src/share/classes/com/sun/naming/internal/VersionHelper12.java Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/classes/com/sun/naming/internal/VersionHelper12.java Wed Apr 07 05:55:34 2021 +0100 @@ -61,6 +61,10 @@ return loadClass(className, getContextClassLoader()); } + public Class loadClassWithoutInit(String className) throws ClassNotFoundException { + return loadClass(className, false, getContextClassLoader()); + } + /** * Determines whether classes may be loaded from an arbitrary URL code base. */ @@ -86,10 +90,15 @@ * This internal method is used with Thread Context Class Loader (TCCL), * please don't expose this method as public. */ + Class loadClass(String className, boolean initialize, ClassLoader cl) + throws ClassNotFoundException { + Class cls = Class.forName(className, initialize, cl); + return cls; + } + Class loadClass(String className, ClassLoader cl) throws ClassNotFoundException { - Class cls = Class.forName(className, true, cl); - return cls; + return loadClass(className, true, cl); } /** diff -r a7ef81ab119b -r f396f4a7ee5d src/share/classes/javax/naming/spi/NamingManager.java --- a/src/share/classes/javax/naming/spi/NamingManager.java Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/classes/javax/naming/spi/NamingManager.java Wed Apr 07 05:55:34 2021 +0100 @@ -31,6 +31,8 @@ import java.net.MalformedURLException; import javax.naming.*; + +import com.sun.naming.internal.ObjectFactoriesFilter; import com.sun.naming.internal.VersionHelper; import com.sun.naming.internal.ResourceManager; import com.sun.naming.internal.FactoryEnumeration; @@ -143,7 +145,11 @@ // Try to use current class loader try { - clas = helper.loadClass(factoryName); + clas = helper.loadClassWithoutInit(factoryName); + // Validate factory's class with the objects factory serial filter + if (!ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) { + return null; + } } catch (ClassNotFoundException e) { // ignore and continue // e.printStackTrace(); @@ -156,6 +162,11 @@ (codebase = ref.getFactoryClassLocation()) != null) { try { clas = helper.loadClass(factoryName, codebase); + // Validate factory's class with the objects factory serial filter + if (clas == null || + !ObjectFactoriesFilter.canInstantiateObjectsFactory(clas)) { + return null; + } } catch (ClassNotFoundException e) { } } diff -r a7ef81ab119b -r f396f4a7ee5d src/share/lib/security/java.security-aix --- a/src/share/lib/security/java.security-aix Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/lib/security/java.security-aix Wed Apr 07 05:55:34 2021 +0100 @@ -1191,3 +1191,26 @@ # System value prevails. The default value of the property is "false". # #jdk.security.allowNonCaAnchor=true + +# +# JNDI Object Factories Filter +# +# This filter is used by the JNDI runtime to control the set of object factory classes +# which will be allowed to instantiate objects from object references returned by +# naming/directory systems. The factory class named by the reference instance will be +# matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. +# +# Each pattern is matched against the factory class name to allow or disallow it's +# instantiation. The access to a factory class is allowed unless the filter returns +# REJECTED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is "*". +# +# The default pattern value allows any object factory class specified by the reference +# instance to recreate the referenced object. +#jdk.jndi.object.factoriesFilter=* \ No newline at end of file diff -r a7ef81ab119b -r f396f4a7ee5d src/share/lib/security/java.security-linux --- a/src/share/lib/security/java.security-linux Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/lib/security/java.security-linux Wed Apr 07 05:55:34 2021 +0100 @@ -1197,3 +1197,26 @@ # System value prevails. The default value of the property is "false". # #jdk.security.allowNonCaAnchor=true + +# +# JNDI Object Factories Filter +# +# This filter is used by the JNDI runtime to control the set of object factory classes +# which will be allowed to instantiate objects from object references returned by +# naming/directory systems. The factory class named by the reference instance will be +# matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. +# +# Each pattern is matched against the factory class name to allow or disallow it's +# instantiation. The access to a factory class is allowed unless the filter returns +# REJECTED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is "*". +# +# The default pattern value allows any object factory class specified by the reference +# instance to recreate the referenced object. +#jdk.jndi.object.factoriesFilter=* \ No newline at end of file diff -r a7ef81ab119b -r f396f4a7ee5d src/share/lib/security/java.security-macosx --- a/src/share/lib/security/java.security-macosx Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/lib/security/java.security-macosx Wed Apr 07 05:55:34 2021 +0100 @@ -1195,3 +1195,26 @@ # System value prevails. The default value of the property is "false". # #jdk.security.allowNonCaAnchor=true + +# +# JNDI Object Factories Filter +# +# This filter is used by the JNDI runtime to control the set of object factory classes +# which will be allowed to instantiate objects from object references returned by +# naming/directory systems. The factory class named by the reference instance will be +# matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. +# +# Each pattern is matched against the factory class name to allow or disallow it's +# instantiation. The access to a factory class is allowed unless the filter returns +# REJECTED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is "*". +# +# The default pattern value allows any object factory class specified by the reference +# instance to recreate the referenced object. +#jdk.jndi.object.factoriesFilter=* \ No newline at end of file diff -r a7ef81ab119b -r f396f4a7ee5d src/share/lib/security/java.security-solaris --- a/src/share/lib/security/java.security-solaris Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/lib/security/java.security-solaris Wed Apr 07 05:55:34 2021 +0100 @@ -1193,3 +1193,26 @@ # System value prevails. The default value of the property is "false". # #jdk.security.allowNonCaAnchor=true + +# +# JNDI Object Factories Filter +# +# This filter is used by the JNDI runtime to control the set of object factory classes +# which will be allowed to instantiate objects from object references returned by +# naming/directory systems. The factory class named by the reference instance will be +# matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. +# +# Each pattern is matched against the factory class name to allow or disallow it's +# instantiation. The access to a factory class is allowed unless the filter returns +# REJECTED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is "*". +# +# The default pattern value allows any object factory class specified by the reference +# instance to recreate the referenced object. +#jdk.jndi.object.factoriesFilter=* \ No newline at end of file diff -r a7ef81ab119b -r f396f4a7ee5d src/share/lib/security/java.security-windows --- a/src/share/lib/security/java.security-windows Sat Mar 27 19:01:26 2021 +0000 +++ b/src/share/lib/security/java.security-windows Wed Apr 07 05:55:34 2021 +0100 @@ -1195,3 +1195,26 @@ # System value prevails. The default value of the property is "false". # #jdk.security.allowNonCaAnchor=true + +# +# JNDI Object Factories Filter +# +# This filter is used by the JNDI runtime to control the set of object factory classes +# which will be allowed to instantiate objects from object references returned by +# naming/directory systems. The factory class named by the reference instance will be +# matched against this filter. The filter property supports pattern-based filter syntax +# with the same format as jdk.serialFilter. +# +# Each pattern is matched against the factory class name to allow or disallow it's +# instantiation. The access to a factory class is allowed unless the filter returns +# REJECTED. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +# If the system property jdk.jndi.object.factoriesFilter is also specified, it supersedes +# the security property value defined here. The default value of the property is "*". +# +# The default pattern value allows any object factory class specified by the reference +# instance to recreate the referenced object. +#jdk.jndi.object.factoriesFilter=* \ No newline at end of file