8290368: Introduce LDAP and RMI protocol-specific object factory filters to JNDI implementation
Reviewed-by: dfuchs, rriggs, jpai
This commit is contained in:
parent
21aeb9e794
commit
d37ce4cdd1
@ -1376,17 +1376,18 @@ jdk.io.permissionsUseCanonicalPath=false
|
||||
jdk.tls.alpnCharset=ISO_8859_1
|
||||
|
||||
#
|
||||
# JNDI Object Factories Filter
|
||||
# Global 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.
|
||||
# with the same format as jdk.serialFilter. Limit patterns specified in the filter property
|
||||
# are unused.
|
||||
#
|
||||
# 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.
|
||||
# Each class name pattern is matched against the factory class name to allow or disallow its
|
||||
# instantiation. The access to a factory class is allowed if the filter returns
|
||||
# ALLOWED.
|
||||
#
|
||||
# Note: This property is currently used by the JDK Reference implementation.
|
||||
# It is not guaranteed to be examined and used by other implementations.
|
||||
@ -1398,6 +1399,58 @@ jdk.tls.alpnCharset=ISO_8859_1
|
||||
# instance to recreate the referenced object.
|
||||
#jdk.jndi.object.factoriesFilter=*
|
||||
|
||||
#
|
||||
# Protocol Specific JNDI/LDAP Object Factories Filter
|
||||
#
|
||||
# This filter is used by the JNDI/LDAP provider implementation in the JDK to further control the
|
||||
# set of object factory classes which will be allowed to instantiate objects from object
|
||||
# references bound to LDAP contexts. 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. Limit patterns specified in the filter property
|
||||
# are unused.
|
||||
#
|
||||
# Each class name pattern is matched against the factory class name to allow or disallow its
|
||||
# instantiation. The access to a factory class is allowed only when it is not rejected by this filter
|
||||
# or by the global filter defined by "jdk.jndi.object.factoriesFilter", and at least one of these
|
||||
# two filters returns ALLOWED.
|
||||
#
|
||||
# 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.ldap.object.factoriesFilter is also specified, it supersedes
|
||||
# the security property value defined here. The default value of the property is
|
||||
# "java.naming/com.sun.jndi.ldap.**;!*".
|
||||
#
|
||||
# The default pattern value allows any object factory class defined in the java.naming module
|
||||
# to be specified by the reference instance, but rejects any other.
|
||||
#jdk.jndi.ldap.object.factoriesFilter=java.naming/com.sun.jndi.ldap.**;!*
|
||||
|
||||
#
|
||||
# Protocol Specific JNDI/RMI Object Factories Filter
|
||||
#
|
||||
# This filter is used by the JNDI/RMI provider implementation in the JDK to further control the
|
||||
# set of object factory classes which will be allowed to instantiate objects from object
|
||||
# references bound to RMI names. 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. Limit patterns specified in the filter property
|
||||
# are unused.
|
||||
#
|
||||
# Each class name pattern is matched against the factory class name to allow or disallow its
|
||||
# instantiation. The access to a factory class is allowed only when it is not rejected by this filter
|
||||
# or by the global filter defined by "jdk.jndi.object.factoriesFilter", and at least one of these
|
||||
# two filters returns ALLOWED.
|
||||
#
|
||||
# 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.rmi.object.factoriesFilter is also specified, it supersedes
|
||||
# the security property value defined here. The default value of the property is
|
||||
# "jdk.naming.rmi/com.sun.jndi.rmi.**;!*".
|
||||
#
|
||||
# The default pattern value allows any object factory class defined in the jdk.naming.rmi module
|
||||
# to be specified by the reference instance, but rejects any other.
|
||||
#jdk.jndi.rmi.object.factoriesFilter=jdk.naming.rmi/com.sun.jndi.rmi.**;!*
|
||||
|
||||
#
|
||||
# Policy for non-forwardable service ticket in a S4U2proxy request
|
||||
#
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -33,9 +33,10 @@ import java.util.Vector;
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import javax.naming.ldap.Control;
|
||||
import javax.naming.spi.*;
|
||||
|
||||
import com.sun.jndi.toolkit.ctx.Continuation;
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
|
||||
final class LdapBindingEnumeration
|
||||
extends AbstractLdapNamingEnumeration<Binding> {
|
||||
@ -76,8 +77,8 @@ final class LdapBindingEnumeration
|
||||
cn.add(atom);
|
||||
|
||||
try {
|
||||
obj = DirectoryManager.getObjectInstance(obj, cn, homeCtx,
|
||||
homeCtx.envprops, attrs);
|
||||
obj = NamingManagerHelper.getDirObjectInstance(obj, cn, homeCtx,
|
||||
homeCtx.envprops, attrs, ObjectFactoriesFilter::checkLdapFilter);
|
||||
|
||||
} catch (NamingException e) {
|
||||
throw e;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -27,7 +27,6 @@ package com.sun.jndi.ldap;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import javax.naming.spi.*;
|
||||
import javax.naming.event.*;
|
||||
import javax.naming.ldap.*;
|
||||
import javax.naming.ldap.LdapName;
|
||||
@ -54,6 +53,8 @@ import com.sun.jndi.toolkit.ctx.*;
|
||||
import com.sun.jndi.toolkit.dir.HierMemDirCtx;
|
||||
import com.sun.jndi.toolkit.dir.SearchFilter;
|
||||
import com.sun.jndi.ldap.ext.StartTlsResponseImpl;
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
|
||||
/**
|
||||
* The LDAP context implementation.
|
||||
@ -1111,8 +1112,8 @@ public final class LdapCtx extends ComponentDirContext
|
||||
}
|
||||
|
||||
try {
|
||||
return DirectoryManager.getObjectInstance(obj, name,
|
||||
this, envprops, attrs);
|
||||
return NamingManagerHelper.getDirObjectInstance(obj, name, this,
|
||||
envprops, attrs, ObjectFactoriesFilter::checkLdapFilter);
|
||||
|
||||
} catch (NamingException e) {
|
||||
throw cont.fillInException(e);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -27,12 +27,13 @@ package com.sun.jndi.ldap;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import javax.naming.spi.*;
|
||||
import javax.naming.ldap.*;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.StringTokenizer;
|
||||
import com.sun.jndi.toolkit.dir.SearchFilter;
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
|
||||
/**
|
||||
* A context for handling referrals.
|
||||
@ -116,8 +117,8 @@ final class LdapReferralContext implements DirContext, LdapContext {
|
||||
|
||||
Object obj;
|
||||
try {
|
||||
obj = NamingManager.getObjectInstance(ref, null, null, env);
|
||||
|
||||
obj = NamingManagerHelper.getObjectInstance(ref, null, null,
|
||||
env, ObjectFactoriesFilter::checkLdapFilter);
|
||||
} catch (NamingException e) {
|
||||
|
||||
if (handleReferrals == LdapClient.LDAP_REF_THROW) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -32,11 +32,12 @@ import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Vector;
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import javax.naming.spi.*;
|
||||
import javax.naming.ldap.*;
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
import com.sun.jndi.toolkit.ctx.Continuation;
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
|
||||
final class LdapSearchEnumeration
|
||||
extends AbstractLdapNamingEnumeration<SearchResult> {
|
||||
@ -134,9 +135,9 @@ final class LdapSearchEnumeration
|
||||
// Call getObjectInstance before removing unrequested attributes
|
||||
try {
|
||||
// rcn is either relative to homeCtx or a fully qualified DN
|
||||
obj = DirectoryManager.getObjectInstance(
|
||||
obj = NamingManagerHelper.getDirObjectInstance(
|
||||
obj, rcn, (relative ? homeCtx : null),
|
||||
homeCtx.envprops, attrs);
|
||||
homeCtx.envprops, attrs, ObjectFactoriesFilter::checkLdapFilter);
|
||||
} catch (NamingException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.RefAddr;
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.Referenceable;
|
||||
import javax.naming.StringRefAddr;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.spi.DirObjectFactory;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
import javax.naming.spi.ObjectFactoryBuilder;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class NamingManagerHelper {
|
||||
|
||||
public static Object getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment,
|
||||
Predicate<Class<?>> factoryFilter) throws Exception {
|
||||
ObjectFactory factory;
|
||||
|
||||
// Use builder if installed
|
||||
ObjectFactoryBuilder builder = getObjectFactoryBuilder();
|
||||
if (builder != null) {
|
||||
// builder must return non-null factory
|
||||
factory = builder.createObjectFactory(refInfo, environment);
|
||||
return factory.getObjectInstance(refInfo, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
|
||||
// Use reference if possible
|
||||
Reference ref = null;
|
||||
if (refInfo instanceof Reference) {
|
||||
ref = (Reference) refInfo;
|
||||
} else if (refInfo instanceof Referenceable) {
|
||||
ref = ((Referenceable)(refInfo)).getReference();
|
||||
}
|
||||
|
||||
Object answer;
|
||||
|
||||
if (ref != null) {
|
||||
String f = ref.getFactoryClassName();
|
||||
if (f != null) {
|
||||
// if reference identifies a factory, use exclusively
|
||||
|
||||
factory = getObjectFactoryFromReference(ref, f, factoryFilter);
|
||||
if (factory != null) {
|
||||
return factory.getObjectInstance(ref, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
// No factory found, so return original refInfo.
|
||||
// That could happen if:
|
||||
// - a factory class is not in a class path and reference does
|
||||
// not contain a URL for it
|
||||
// - a factory class is available but object factory filters
|
||||
// disallow its usage
|
||||
return refInfo;
|
||||
|
||||
} else {
|
||||
// if reference has no factory, check for addresses
|
||||
// containing URLs
|
||||
|
||||
answer = processURLAddrs(ref, name, nameCtx, environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try using any specified factories
|
||||
answer =
|
||||
createObjectFromFactories(refInfo, name, nameCtx, environment);
|
||||
return (answer != null) ? answer : refInfo;
|
||||
}
|
||||
|
||||
|
||||
public static Object getDirObjectInstance(Object refInfo, Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment, Attributes attrs,
|
||||
Predicate<Class<?>> factoryFilter) throws Exception {
|
||||
ObjectFactory factory;
|
||||
|
||||
ObjectFactoryBuilder builder = getObjectFactoryBuilder();
|
||||
if (builder != null) {
|
||||
// builder must return non-null factory
|
||||
factory = builder.createObjectFactory(refInfo, environment);
|
||||
if (factory instanceof DirObjectFactory) {
|
||||
return ((DirObjectFactory)factory).getObjectInstance(
|
||||
refInfo, name, nameCtx, environment, attrs);
|
||||
} else {
|
||||
return factory.getObjectInstance(refInfo, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
}
|
||||
|
||||
// use reference if possible
|
||||
Reference ref = null;
|
||||
if (refInfo instanceof Reference) {
|
||||
ref = (Reference) refInfo;
|
||||
} else if (refInfo instanceof Referenceable) {
|
||||
ref = ((Referenceable)(refInfo)).getReference();
|
||||
}
|
||||
|
||||
Object answer;
|
||||
|
||||
if (ref != null) {
|
||||
String f = ref.getFactoryClassName();
|
||||
if (f != null) {
|
||||
// if reference identifies a factory, use exclusively
|
||||
|
||||
factory = getObjectFactoryFromReference(ref, f, factoryFilter);
|
||||
if (factory instanceof DirObjectFactory) {
|
||||
return ((DirObjectFactory)factory).getObjectInstance(
|
||||
ref, name, nameCtx, environment, attrs);
|
||||
} else if (factory != null) {
|
||||
return factory.getObjectInstance(ref, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
// No factory found, so return original refInfo.
|
||||
// That could happen if:
|
||||
// - a factory class is not in a class path and reference does
|
||||
// not contain a URL for it
|
||||
// - a factory class is available but object factory filters
|
||||
// disallow its usage
|
||||
return refInfo;
|
||||
|
||||
} else {
|
||||
// if reference has no factory, check for addresses
|
||||
// containing URLs
|
||||
// ignore name & attrs params; not used in URL factory
|
||||
// RMI references from '
|
||||
answer = processURLAddrs(ref, name, nameCtx, environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try using any specified factories
|
||||
answer = createObjectFromFactories(refInfo, name, nameCtx,
|
||||
environment, attrs);
|
||||
return (answer != null) ? answer : refInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ObjectFactory for the object identified by a reference,
|
||||
* using the reference's factory class name and factory codebase
|
||||
* to load in the factory's class.
|
||||
* @param ref The non-null reference to use.
|
||||
* @param factoryName The non-null class name of the factory.
|
||||
* @return The object factory for the object identified by ref; null
|
||||
* if unable to load the factory.
|
||||
*/
|
||||
static ObjectFactory getObjectFactoryFromReference(
|
||||
Reference ref, String factoryName, Predicate<Class<?>> filter)
|
||||
throws IllegalAccessException,
|
||||
InstantiationException,
|
||||
MalformedURLException {
|
||||
Class<?> clas = null;
|
||||
|
||||
// Try to use current class loader
|
||||
try {
|
||||
clas = helper.loadClassWithoutInit(factoryName);
|
||||
// Validate factory's class with the objects factory serial filter
|
||||
if (!filter.test(clas)) {
|
||||
return null;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
// ignore and continue
|
||||
// e.printStackTrace();
|
||||
}
|
||||
// All other exceptions are passed up.
|
||||
|
||||
// Not in class path; try to use codebase
|
||||
String codebase;
|
||||
if (clas == null &&
|
||||
(codebase = ref.getFactoryClassLocation()) != null) {
|
||||
try {
|
||||
clas = helper.loadClass(factoryName, codebase);
|
||||
// Validate factory's class with the objects factory serial filter
|
||||
if (clas == null || !filter.test(clas)) {
|
||||
return null;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Class.newInstance
|
||||
ObjectFactory result = (clas != null) ? (ObjectFactory) clas.newInstance() : null;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object using the factories specified in the
|
||||
* {@code Context.OBJECT_FACTORIES} property of the environment
|
||||
* or of the provider resource file associated with {@code nameCtx}.
|
||||
*
|
||||
* @return factory created; null if cannot create
|
||||
*/
|
||||
private static Object createObjectFromFactories(Object obj, Name name,
|
||||
Context nameCtx, Hashtable<?,?> environment, Attributes attrs)
|
||||
throws Exception {
|
||||
|
||||
FactoryEnumeration factories = ResourceManager.getFactories(
|
||||
Context.OBJECT_FACTORIES, environment, nameCtx);
|
||||
|
||||
if (factories == null)
|
||||
return null;
|
||||
|
||||
ObjectFactory factory;
|
||||
Object answer = null;
|
||||
// Try each factory until one succeeds
|
||||
while (answer == null && factories.hasMore()) {
|
||||
factory = (ObjectFactory)factories.next();
|
||||
if (factory instanceof DirObjectFactory) {
|
||||
answer = ((DirObjectFactory)factory).
|
||||
getObjectInstance(obj, name, nameCtx, environment, attrs);
|
||||
} else {
|
||||
answer =
|
||||
factory.getObjectInstance(obj, name, nameCtx, environment);
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ref has no factory. For each address of type "URL", try its URL
|
||||
* context factory. Returns null if unsuccessful in creating and
|
||||
* invoking a factory.
|
||||
*/
|
||||
static Object processURLAddrs(Reference ref, Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment)
|
||||
throws NamingException {
|
||||
|
||||
for (int i = 0; i < ref.size(); i++) {
|
||||
RefAddr addr = ref.get(i);
|
||||
if (addr instanceof StringRefAddr &&
|
||||
addr.getType().equalsIgnoreCase("URL")) {
|
||||
|
||||
String url = (String)addr.getContent();
|
||||
Object answer = processURL(url, name, nameCtx, environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object processURL(Object refInfo, Name name,
|
||||
Context nameCtx, Hashtable<?,?> environment)
|
||||
throws NamingException {
|
||||
Object answer;
|
||||
|
||||
// If refInfo is a URL string, try to use its URL context factory
|
||||
// If no context found, continue to try object factories.
|
||||
if (refInfo instanceof String) {
|
||||
String url = (String)refInfo;
|
||||
String scheme = getURLScheme(url);
|
||||
if (scheme != null) {
|
||||
answer = getURLObject(scheme, refInfo, name, nameCtx,
|
||||
environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If refInfo is an array of URL strings,
|
||||
// try to find a context factory for any one of its URLs.
|
||||
// If no context found, continue to try object factories.
|
||||
if (refInfo instanceof String[]) {
|
||||
String[] urls = (String[])refInfo;
|
||||
for (int i = 0; i <urls.length; i++) {
|
||||
String scheme = getURLScheme(urls[i]);
|
||||
if (scheme != null) {
|
||||
answer = getURLObject(scheme, refInfo, name, nameCtx,
|
||||
environment);
|
||||
if (answer != null)
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getURLScheme(String str) {
|
||||
int colon_posn = str.indexOf(':');
|
||||
int slash_posn = str.indexOf('/');
|
||||
|
||||
if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
|
||||
return str.substring(0, colon_posn);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object for the given URL scheme id using
|
||||
* the supplied urlInfo.
|
||||
* <p>
|
||||
* If urlInfo is null, the result is a context for resolving URLs
|
||||
* with the scheme id 'scheme'.
|
||||
* If urlInfo is a URL, the result is a context named by the URL.
|
||||
* Names passed to this context is assumed to be relative to this
|
||||
* context (i.e. not a URL). For example, if urlInfo is
|
||||
* "ldap://ldap.wiz.com/o=Wiz,c=us", the resulting context will
|
||||
* be that pointed to by "o=Wiz,c=us" on the server 'ldap.wiz.com'.
|
||||
* Subsequent names that can be passed to this context will be
|
||||
* LDAP names relative to this context (e.g. cn="Barbs Jensen").
|
||||
* If urlInfo is an array of URLs, the URLs are assumed
|
||||
* to be equivalent in terms of the context to which they refer.
|
||||
* The resulting context is like that of the single URL case.
|
||||
* If urlInfo is of any other type, that is handled by the
|
||||
* context factory for the URL scheme.
|
||||
* @param scheme the URL scheme id for the context
|
||||
* @param urlInfo information used to create the context
|
||||
* @param name name of this object relative to {@code nameCtx}
|
||||
* @param nameCtx Context whose provider resource file will be searched
|
||||
* for package prefix values (or null if none)
|
||||
* @param environment Environment properties for creating the context
|
||||
* @see javax.naming.InitialContext
|
||||
*/
|
||||
private static Object getURLObject(String scheme, Object urlInfo,
|
||||
Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment)
|
||||
throws NamingException {
|
||||
|
||||
// e.g. "ftpURLContextFactory"
|
||||
ObjectFactory factory = (ObjectFactory)ResourceManager.getFactory(
|
||||
Context.URL_PKG_PREFIXES, environment, nameCtx,
|
||||
"." + scheme + "." + scheme + "URLContextFactory", DEFAULT_PKG_PREFIX);
|
||||
|
||||
if (factory == null)
|
||||
return null;
|
||||
|
||||
// Found object factory
|
||||
try {
|
||||
return factory.getObjectInstance(urlInfo, name, nameCtx, environment);
|
||||
} catch (NamingException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
NamingException ne = new NamingException();
|
||||
ne.setRootCause(e);
|
||||
throw ne;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object using the factories specified in the
|
||||
* {@code Context.OBJECT_FACTORIES} property of the environment
|
||||
* or of the provider resource file associated with {@code nameCtx}.
|
||||
*
|
||||
* @return factory created; null if cannot create
|
||||
*/
|
||||
private static Object createObjectFromFactories(Object obj, Name name,
|
||||
Context nameCtx, Hashtable<?,?> environment) throws Exception {
|
||||
|
||||
FactoryEnumeration factories = ResourceManager.getFactories(
|
||||
Context.OBJECT_FACTORIES, environment, nameCtx);
|
||||
|
||||
if (factories == null)
|
||||
return null;
|
||||
|
||||
// Try each factory until one succeeds
|
||||
ObjectFactory factory;
|
||||
Object answer = null;
|
||||
while (answer == null && factories.hasMore()) {
|
||||
factory = (ObjectFactory)factories.next();
|
||||
answer = factory.getObjectInstance(obj, name, nameCtx, environment);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
public static synchronized void setObjectFactoryBuilder(
|
||||
ObjectFactoryBuilder builder) throws NamingException {
|
||||
if (object_factory_builder != null)
|
||||
throw new IllegalStateException("ObjectFactoryBuilder already set");
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkSetFactory();
|
||||
}
|
||||
object_factory_builder = builder;
|
||||
}
|
||||
|
||||
public static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {
|
||||
return object_factory_builder;
|
||||
}
|
||||
|
||||
private static final String DEFAULT_PKG_PREFIX = "com.sun.jndi.url";
|
||||
static final VersionHelper helper = VersionHelper.getVersionHelper();
|
||||
|
||||
private static ObjectFactoryBuilder object_factory_builder = null;
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2022, 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
|
||||
@ -50,19 +50,58 @@ 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
|
||||
* If the filter result is {@linkplain Status#ALLOWED ALLOWED}, the filter will
|
||||
* allow the instantiation of objects factory class.
|
||||
*
|
||||
* @param factoryClass objects factory class
|
||||
* @param serialClass objects factory class
|
||||
* @return true - if the factory is allowed to be instantiated; false - otherwise
|
||||
*/
|
||||
public static boolean canInstantiateObjectsFactory(Class<?> factoryClass) {
|
||||
return checkInput(() -> factoryClass);
|
||||
public static boolean checkGlobalFilter(Class<?> serialClass) {
|
||||
return checkInput(GLOBAL_FILTER, () -> serialClass);
|
||||
}
|
||||
|
||||
private static boolean checkInput(FactoryInfo factoryInfo) {
|
||||
Status result = GLOBAL.checkInput(factoryInfo);
|
||||
return result != Status.REJECTED;
|
||||
/**
|
||||
* Checks if the factory filters allow the given factory class for LDAP.
|
||||
* This method combines the global and LDAP specific filter results to determine
|
||||
* if the given factory class is allowed.
|
||||
* The given factory class is rejected if any of these two filters reject
|
||||
* it, or if none of them allow it.
|
||||
*
|
||||
* @param serialClass objects factory class
|
||||
* @return true - if the factory is allowed to be instantiated; false - otherwise
|
||||
*/
|
||||
public static boolean checkLdapFilter(Class<?> serialClass) {
|
||||
return checkInput(LDAP_FILTER, () -> serialClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the factory filters allow the given factory class for RMI.
|
||||
* This method combines the global and RMI specific filter results to determine
|
||||
* if the given factory class is allowed.
|
||||
* The given factory class is rejected if any of these two filters reject
|
||||
* it, or if none of them allow it.
|
||||
*
|
||||
* @param serialClass objects factory class
|
||||
* @return true - if the factory is allowed to be instantiated; false - otherwise
|
||||
*/
|
||||
public static boolean checkRmiFilter(Class<?> serialClass) {
|
||||
return checkInput(RMI_FILTER, () -> serialClass);
|
||||
}
|
||||
|
||||
private static boolean checkInput(ConfiguredFilter filter, FactoryInfo serialClass) {
|
||||
var globalFilter = GLOBAL_FILTER.filter();
|
||||
var specificFilter = filter.filter();
|
||||
Status globalResult = globalFilter.checkInput(serialClass);
|
||||
|
||||
// Check if a specific filter is the global one
|
||||
if (filter == GLOBAL_FILTER) {
|
||||
return globalResult == Status.ALLOWED;
|
||||
}
|
||||
return switch (globalResult) {
|
||||
case ALLOWED -> specificFilter.checkInput(serialClass) != Status.REJECTED;
|
||||
case REJECTED -> false;
|
||||
case UNDECIDED -> specificFilter.checkInput(serialClass) == Status.ALLOWED;
|
||||
};
|
||||
}
|
||||
|
||||
// FilterInfo to check if objects factory class is allowed by the system-wide
|
||||
@ -97,18 +136,91 @@ public final class ObjectFactoriesFilter {
|
||||
}
|
||||
|
||||
// System property name that contains the patterns to filter object factory names
|
||||
private static final String FACTORIES_FILTER_PROPNAME = "jdk.jndi.object.factoriesFilter";
|
||||
private static final String GLOBAL_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 property name that contains the patterns to filter LDAP object factory
|
||||
// names
|
||||
private static final String LDAP_FACTORIES_FILTER_PROPNAME =
|
||||
"jdk.jndi.ldap.object.factoriesFilter";
|
||||
|
||||
// System wide object factories filter constructed from the system property
|
||||
private static final ObjectInputFilter GLOBAL =
|
||||
ObjectInputFilter.Config.createFilter(getFilterPropertyValue());
|
||||
// System property name that contains the patterns to filter RMI object factory
|
||||
// names
|
||||
private static final String RMI_FACTORIES_FILTER_PROPNAME =
|
||||
"jdk.jndi.rmi.object.factoriesFilter";
|
||||
|
||||
// Default system property value that allows the load of any object factory
|
||||
// classes
|
||||
private static final String DEFAULT_GLOBAL_SP_VALUE = "*";
|
||||
|
||||
// Default system property value that allows the load of any object factory
|
||||
// class provided by the JDK LDAP provider implementation
|
||||
private static final String DEFAULT_LDAP_SP_VALUE =
|
||||
"java.naming/com.sun.jndi.ldap.**;!*";
|
||||
|
||||
// Default system property value that allows the load of any object factory
|
||||
// class provided by the JDK RMI provider implementation
|
||||
private static final String DEFAULT_RMI_SP_VALUE =
|
||||
"jdk.naming.rmi/com.sun.jndi.rmi.**;!*";
|
||||
|
||||
// A system-wide global object factories filter constructed from the system
|
||||
// property
|
||||
private static final ConfiguredFilter GLOBAL_FILTER =
|
||||
initializeFilter(GLOBAL_FACTORIES_FILTER_PROPNAME, DEFAULT_GLOBAL_SP_VALUE);
|
||||
|
||||
// A system-wide LDAP specific object factories filter constructed from the system
|
||||
// property
|
||||
private static final ConfiguredFilter LDAP_FILTER =
|
||||
initializeFilter(LDAP_FACTORIES_FILTER_PROPNAME, DEFAULT_LDAP_SP_VALUE);
|
||||
|
||||
// A system-wide RMI specific object factories filter constructed from the system
|
||||
// property
|
||||
private static final ConfiguredFilter RMI_FILTER =
|
||||
initializeFilter(RMI_FACTORIES_FILTER_PROPNAME, DEFAULT_RMI_SP_VALUE);
|
||||
|
||||
// Record for storing a factory filter configuration
|
||||
private interface ConfiguredFilter {
|
||||
ObjectInputFilter filter();
|
||||
}
|
||||
|
||||
// Record to store an object input filter constructed from a valid filter
|
||||
// pattern string
|
||||
private record ValidFilter(ObjectInputFilter filter)
|
||||
implements ConfiguredFilter {
|
||||
}
|
||||
|
||||
// Record to store parsing results for a filter with
|
||||
// illegal or malformed pattern string
|
||||
private record InvalidFilter(String filterPropertyName,
|
||||
IllegalArgumentException error)
|
||||
implements ConfiguredFilter {
|
||||
|
||||
@Override
|
||||
public ObjectInputFilter filter() {
|
||||
// Report a filter property name and an error message
|
||||
throw new IllegalArgumentException(filterPropertyName +
|
||||
": " + error.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Read filter pattern value from a system/security property
|
||||
// and create a filter record from it (valid or invalid).
|
||||
private static ConfiguredFilter initializeFilter(String filterPropertyName,
|
||||
String filterDefaultValue) {
|
||||
try {
|
||||
var filter = ObjectInputFilter.Config.createFilter(
|
||||
getFilterPropertyValue(filterPropertyName,
|
||||
filterDefaultValue));
|
||||
return new ValidFilter(filter);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return new InvalidFilter(filterPropertyName, iae);
|
||||
}
|
||||
}
|
||||
|
||||
// Get security or system property value
|
||||
private static String getFilterPropertyValue() {
|
||||
String propVal = SecurityProperties.privilegedGetOverridable(FACTORIES_FILTER_PROPNAME);
|
||||
return propVal != null ? propVal : DEFAULT_SP_VALUE;
|
||||
private static String getFilterPropertyValue(String propertyName,
|
||||
String defaultValue) {
|
||||
String propVal = SecurityProperties.privilegedGetOverridable(propertyName);
|
||||
return propVal != null ? propVal : defaultValue;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -29,13 +29,13 @@ import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.Referenceable;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.CannotProceedException;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.Attributes;
|
||||
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
import com.sun.naming.internal.ResourceManager;
|
||||
import com.sun.naming.internal.FactoryEnumeration;
|
||||
|
||||
@ -154,92 +154,8 @@ public class DirectoryManager extends NamingManager {
|
||||
getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment, Attributes attrs)
|
||||
throws Exception {
|
||||
|
||||
ObjectFactory factory;
|
||||
|
||||
ObjectFactoryBuilder builder = getObjectFactoryBuilder();
|
||||
if (builder != null) {
|
||||
// builder must return non-null factory
|
||||
factory = builder.createObjectFactory(refInfo, environment);
|
||||
if (factory instanceof DirObjectFactory) {
|
||||
return ((DirObjectFactory)factory).getObjectInstance(
|
||||
refInfo, name, nameCtx, environment, attrs);
|
||||
} else {
|
||||
return factory.getObjectInstance(refInfo, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
}
|
||||
|
||||
// use reference if possible
|
||||
Reference ref = null;
|
||||
if (refInfo instanceof Reference) {
|
||||
ref = (Reference) refInfo;
|
||||
} else if (refInfo instanceof Referenceable) {
|
||||
ref = ((Referenceable)(refInfo)).getReference();
|
||||
}
|
||||
|
||||
Object answer;
|
||||
|
||||
if (ref != null) {
|
||||
String f = ref.getFactoryClassName();
|
||||
if (f != null) {
|
||||
// if reference identifies a factory, use exclusively
|
||||
|
||||
factory = getObjectFactoryFromReference(ref, f);
|
||||
if (factory instanceof DirObjectFactory) {
|
||||
return ((DirObjectFactory)factory).getObjectInstance(
|
||||
ref, name, nameCtx, environment, attrs);
|
||||
} else if (factory != null) {
|
||||
return factory.getObjectInstance(ref, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
// No factory found, so return original refInfo.
|
||||
// Will reach this point if factory class is not in
|
||||
// class path and reference does not contain a URL for it
|
||||
return refInfo;
|
||||
|
||||
} else {
|
||||
// if reference has no factory, check for addresses
|
||||
// containing URLs
|
||||
// ignore name & attrs params; not used in URL factory
|
||||
|
||||
answer = processURLAddrs(ref, name, nameCtx, environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try using any specified factories
|
||||
answer = createObjectFromFactories(refInfo, name, nameCtx,
|
||||
environment, attrs);
|
||||
return (answer != null) ? answer : refInfo;
|
||||
}
|
||||
|
||||
private static Object createObjectFromFactories(Object obj, Name name,
|
||||
Context nameCtx, Hashtable<?,?> environment, Attributes attrs)
|
||||
throws Exception {
|
||||
|
||||
FactoryEnumeration factories = ResourceManager.getFactories(
|
||||
Context.OBJECT_FACTORIES, environment, nameCtx);
|
||||
|
||||
if (factories == null)
|
||||
return null;
|
||||
|
||||
ObjectFactory factory;
|
||||
Object answer = null;
|
||||
// Try each factory until one succeeds
|
||||
while (answer == null && factories.hasMore()) {
|
||||
factory = (ObjectFactory)factories.next();
|
||||
if (factory instanceof DirObjectFactory) {
|
||||
answer = ((DirObjectFactory)factory).
|
||||
getObjectInstance(obj, name, nameCtx, environment, attrs);
|
||||
} else {
|
||||
answer =
|
||||
factory.getObjectInstance(obj, name, nameCtx, environment);
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
return NamingManagerHelper.getDirObjectInstance(refInfo, name, nameCtx,
|
||||
environment, attrs, ObjectFactoriesFilter::checkGlobalFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -25,13 +25,13 @@
|
||||
|
||||
package javax.naming.spi;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
|
||||
import javax.naming.*;
|
||||
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
import com.sun.naming.internal.VersionHelper;
|
||||
import com.sun.naming.internal.ResourceManager;
|
||||
@ -78,11 +78,6 @@ public class NamingManager {
|
||||
|
||||
// --------- object factory stuff
|
||||
|
||||
/**
|
||||
* Package-private; used by DirectoryManager and NamingManager.
|
||||
*/
|
||||
private static ObjectFactoryBuilder object_factory_builder = null;
|
||||
|
||||
private static final ClassLoaderValue<InitialContextFactory> FACTORIES_CACHE =
|
||||
new ClassLoaderValue<>();
|
||||
|
||||
@ -111,110 +106,16 @@ public class NamingManager {
|
||||
* @see ObjectFactoryBuilder
|
||||
* @see java.lang.SecurityManager#checkSetFactory
|
||||
*/
|
||||
public static synchronized void setObjectFactoryBuilder(
|
||||
public static void setObjectFactoryBuilder(
|
||||
ObjectFactoryBuilder builder) throws NamingException {
|
||||
if (object_factory_builder != null)
|
||||
throw new IllegalStateException("ObjectFactoryBuilder already set");
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkSetFactory();
|
||||
}
|
||||
object_factory_builder = builder;
|
||||
NamingManagerHelper.setObjectFactoryBuilder(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for accessing object factory builder.
|
||||
*/
|
||||
static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {
|
||||
return object_factory_builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the ObjectFactory for the object identified by a reference,
|
||||
* using the reference's factory class name and factory codebase
|
||||
* to load in the factory's class.
|
||||
* @param ref The non-null reference to use.
|
||||
* @param factoryName The non-null class name of the factory.
|
||||
* @return The object factory for the object identified by ref; null
|
||||
* if unable to load the factory.
|
||||
*/
|
||||
static ObjectFactory getObjectFactoryFromReference(
|
||||
Reference ref, String factoryName)
|
||||
throws IllegalAccessException,
|
||||
InstantiationException,
|
||||
MalformedURLException {
|
||||
Class<?> clas = null;
|
||||
|
||||
// Try to use current class loader
|
||||
try {
|
||||
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();
|
||||
}
|
||||
// All other exceptions are passed up.
|
||||
|
||||
// Not in class path; try to use codebase
|
||||
String codebase;
|
||||
if (clas == null &&
|
||||
(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) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Class.newInstance
|
||||
ObjectFactory result = (clas != null) ? (ObjectFactory) clas.newInstance() : null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an object using the factories specified in the
|
||||
* {@code Context.OBJECT_FACTORIES} property of the environment
|
||||
* or of the provider resource file associated with {@code nameCtx}.
|
||||
*
|
||||
* @return factory created; null if cannot create
|
||||
*/
|
||||
private static Object createObjectFromFactories(Object obj, Name name,
|
||||
Context nameCtx, Hashtable<?,?> environment) throws Exception {
|
||||
|
||||
FactoryEnumeration factories = ResourceManager.getFactories(
|
||||
Context.OBJECT_FACTORIES, environment, nameCtx);
|
||||
|
||||
if (factories == null)
|
||||
return null;
|
||||
|
||||
// Try each factory until one succeeds
|
||||
ObjectFactory factory;
|
||||
Object answer = null;
|
||||
while (answer == null && factories.hasMore()) {
|
||||
factory = (ObjectFactory)factories.next();
|
||||
answer = factory.getObjectInstance(obj, name, nameCtx, environment);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private static String getURLScheme(String str) {
|
||||
int colon_posn = str.indexOf(':');
|
||||
int slash_posn = str.indexOf('/');
|
||||
|
||||
if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
|
||||
return str.substring(0, colon_posn);
|
||||
return null;
|
||||
static ObjectFactoryBuilder getObjectFactoryBuilder() {
|
||||
return NamingManagerHelper.getObjectFactoryBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -308,124 +209,11 @@ public class NamingManager {
|
||||
public static Object
|
||||
getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment)
|
||||
throws Exception
|
||||
{
|
||||
|
||||
ObjectFactory factory;
|
||||
|
||||
// Use builder if installed
|
||||
ObjectFactoryBuilder builder = getObjectFactoryBuilder();
|
||||
if (builder != null) {
|
||||
// builder must return non-null factory
|
||||
factory = builder.createObjectFactory(refInfo, environment);
|
||||
return factory.getObjectInstance(refInfo, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
|
||||
// Use reference if possible
|
||||
Reference ref = null;
|
||||
if (refInfo instanceof Reference) {
|
||||
ref = (Reference) refInfo;
|
||||
} else if (refInfo instanceof Referenceable) {
|
||||
ref = ((Referenceable)(refInfo)).getReference();
|
||||
}
|
||||
|
||||
Object answer;
|
||||
|
||||
if (ref != null) {
|
||||
String f = ref.getFactoryClassName();
|
||||
if (f != null) {
|
||||
// if reference identifies a factory, use exclusively
|
||||
|
||||
factory = getObjectFactoryFromReference(ref, f);
|
||||
if (factory != null) {
|
||||
return factory.getObjectInstance(ref, name, nameCtx,
|
||||
environment);
|
||||
}
|
||||
// No factory found, so return original refInfo.
|
||||
// Will reach this point if factory class is not in
|
||||
// class path and reference does not contain a URL for it
|
||||
return refInfo;
|
||||
|
||||
} else {
|
||||
// if reference has no factory, check for addresses
|
||||
// containing URLs
|
||||
|
||||
answer = processURLAddrs(ref, name, nameCtx, environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// try using any specified factories
|
||||
answer =
|
||||
createObjectFromFactories(refInfo, name, nameCtx, environment);
|
||||
return (answer != null) ? answer : refInfo;
|
||||
throws Exception {
|
||||
return NamingManagerHelper.getObjectInstance(refInfo, name, nameCtx,
|
||||
environment, ObjectFactoriesFilter::checkGlobalFilter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ref has no factory. For each address of type "URL", try its URL
|
||||
* context factory. Returns null if unsuccessful in creating and
|
||||
* invoking a factory.
|
||||
*/
|
||||
static Object processURLAddrs(Reference ref, Name name, Context nameCtx,
|
||||
Hashtable<?,?> environment)
|
||||
throws NamingException {
|
||||
|
||||
for (int i = 0; i < ref.size(); i++) {
|
||||
RefAddr addr = ref.get(i);
|
||||
if (addr instanceof StringRefAddr &&
|
||||
addr.getType().equalsIgnoreCase("URL")) {
|
||||
|
||||
String url = (String)addr.getContent();
|
||||
Object answer = processURL(url, name, nameCtx, environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Object processURL(Object refInfo, Name name,
|
||||
Context nameCtx, Hashtable<?,?> environment)
|
||||
throws NamingException {
|
||||
Object answer;
|
||||
|
||||
// If refInfo is a URL string, try to use its URL context factory
|
||||
// If no context found, continue to try object factories.
|
||||
if (refInfo instanceof String) {
|
||||
String url = (String)refInfo;
|
||||
String scheme = getURLScheme(url);
|
||||
if (scheme != null) {
|
||||
answer = getURLObject(scheme, refInfo, name, nameCtx,
|
||||
environment);
|
||||
if (answer != null) {
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If refInfo is an array of URL strings,
|
||||
// try to find a context factory for any one of its URLs.
|
||||
// If no context found, continue to try object factories.
|
||||
if (refInfo instanceof String[]) {
|
||||
String[] urls = (String[])refInfo;
|
||||
for (int i = 0; i <urls.length; i++) {
|
||||
String scheme = getURLScheme(urls[i]);
|
||||
if (scheme != null) {
|
||||
answer = getURLObject(scheme, refInfo, name, nameCtx,
|
||||
environment);
|
||||
if (answer != null)
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a context identified by {@code obj}, using the specified
|
||||
* environment.
|
||||
|
@ -96,13 +96,31 @@
|
||||
* 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
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}.
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}. Limit patterns
|
||||
* specified in the filter property are unused.
|
||||
* This property can also be specified as a {@linkplain java.security.Security security property}.
|
||||
* This property is also supported by the <a href="{@docRoot}/jdk.naming.rmi/module-summary.html">default JNDI
|
||||
* RMI Provider</a>.
|
||||
* <br>The default value allows any object factory class specified by the reference
|
||||
* instance to recreate the referenced object.
|
||||
* </li>
|
||||
* <li>{@systemProperty jdk.jndi.ldap.object.factoriesFilter}:
|
||||
* <br>The value of this system property defines a filter used by
|
||||
* the JDK LDAP provider implementation to further restrict the set of object factory classes which will
|
||||
* be allowed to instantiate objects from object references returned by LDAP systems.
|
||||
* The factory class named by the {@linkplain javax.naming.Reference reference instance} first will be
|
||||
* matched against this specific filter and then against the global filter. The factory class is rejected
|
||||
* if any of these two filters reject it, or if none of them allow it.
|
||||
* The filter property supports pattern-based filter syntax with the same format as
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}. Limit patterns
|
||||
* specified in the filter property are unused.
|
||||
* <br>The default value allows any object factory class provided by the JDK LDAP provider
|
||||
* implementation.
|
||||
* <br>This system property will be used to filter LDAP specific object factories only if
|
||||
* global {@link javax.naming.spi.ObjectFactoryBuilder} is {@linkplain
|
||||
* javax.naming.spi.NamingManager#setObjectFactoryBuilder(javax.naming.spi.ObjectFactoryBuilder)
|
||||
* not set}.
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>Other providers may define additional properties in their module description:
|
||||
* <ul>
|
||||
@ -133,6 +151,8 @@ module java.naming {
|
||||
exports com.sun.jndi.toolkit.url to
|
||||
jdk.naming.dns,
|
||||
jdk.naming.rmi;
|
||||
exports com.sun.naming.internal to
|
||||
jdk.naming.rmi;
|
||||
|
||||
uses javax.naming.ldap.StartTlsResponse;
|
||||
uses javax.naming.spi.InitialContextFactory;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2022, 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
|
||||
@ -26,6 +26,9 @@
|
||||
package com.sun.jndi.rmi.registry;
|
||||
|
||||
|
||||
import com.sun.naming.internal.NamingManagerHelper;
|
||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Properties;
|
||||
import java.rmi.*;
|
||||
@ -498,8 +501,8 @@ public class RegistryContext implements Context, Referenceable {
|
||||
"The object factory is untrusted. Set the system property" +
|
||||
" 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
|
||||
}
|
||||
return NamingManager.getObjectInstance(obj, name, this,
|
||||
environment);
|
||||
return NamingManagerHelper.getObjectInstance(obj, name, this,
|
||||
environment, ObjectFactoriesFilter::checkRmiFilter);
|
||||
} catch (NamingException e) {
|
||||
throw e;
|
||||
} catch (RemoteException e) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2022, 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
|
||||
@ -36,13 +36,27 @@
|
||||
* 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
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}.
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}. Limit patterns
|
||||
* specified in the filter property are unused.
|
||||
* This property can also be specified as a {@linkplain java.security.Security security property}.
|
||||
* This property is also supported by the <a href="{@docRoot}/java.naming/module-summary.html">default
|
||||
* LDAP Naming Service Provider</a>.
|
||||
* <br>The default value allows any object factory class specified by the reference
|
||||
* instance to recreate the referenced object.
|
||||
* </li>
|
||||
* <li>{@systemProperty jdk.jndi.rmi.object.factoriesFilter}:
|
||||
* <br>The value of this system property defines a filter used by
|
||||
* the JDK RMI provider implementation to further restrict the set of object factory classes which will
|
||||
* be allowed to instantiate objects from object references returned by RMI systems.
|
||||
* The factory class named by the {@linkplain javax.naming.Reference reference instance} first will be
|
||||
* matched against this specific filter and then against the global filter. The factory class is rejected
|
||||
* if any of these two filters reject it, or if none of them allow it.
|
||||
* The filter property supports pattern-based filter syntax with the same format as
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter(String) jdk.serialFilter}. Limit patterns
|
||||
* specified in the filter property are unused.
|
||||
* <br>The default value allows any object factory class provided by the JDK RMI provider
|
||||
* implementation.
|
||||
* </li>
|
||||
* </ul>
|
||||
* @provides javax.naming.spi.InitialContextFactory
|
||||
* @moduleGraph
|
||||
|
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.net.URIBuilder;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290368
|
||||
* @summary Checks if LDAP specific objects factory filter system and security
|
||||
* properties can be used to restrict usage of object factories during
|
||||
* LDAP lookup operations.
|
||||
* @modules java.naming/com.sun.jndi.ldap
|
||||
* @library /test/lib ../../lib /javax/naming/module/src/test/test/
|
||||
* @build LDAPServer LDAPTestUtils TestFactory
|
||||
*
|
||||
* @run main/othervm LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=*
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.**;!*
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.test.**;!*
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.test.*;!*
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.test.Test*;!*
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=!com.test.**
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=!com.test.TestFactory;com.**
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=!com.test.TestFactory;com.test.*
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=!com.test.Test*
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.*;!*
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.test.TestFactor;!*
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=com.test.TestFactoryy;!*
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/disallowLdapFilter.props
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/disallowLdapFilter.props
|
||||
* -Djdk.jndi.ldap.object.factoriesFilter=com.test.TestFactory
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/allowLdapFilter.props
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/allowLdapFilter.props
|
||||
* -Djdk.jndi.rmi.object.factoriesFilter=!com.test.TestFactory
|
||||
* LdapFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/allowLdapFilter.props
|
||||
* -Djdk.jndi.ldap.object.factoriesFilter=!com.test.TestFactory
|
||||
* LdapFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=.*
|
||||
* LdapFactoriesFilterTest false false
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=*
|
||||
* -Djdk.jndi.object.factoriesFilter=.*
|
||||
* LdapFactoriesFilterTest false false
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.ldap.object.factoriesFilter=*
|
||||
* -Djdk.jndi.object.factoriesFilter=*
|
||||
* -Djdk.jndi.rmi.object.factoriesFilter=.*
|
||||
* LdapFactoriesFilterTest true true
|
||||
*/
|
||||
|
||||
public class LdapFactoriesFilterTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
boolean testFactoryAllowed = Boolean.parseBoolean(args[0]);
|
||||
boolean ldapAndGlobalFiltersValid =
|
||||
Boolean.parseBoolean(args[1]);
|
||||
|
||||
// Create unbound server socket
|
||||
ServerSocket serverSocket = new ServerSocket();
|
||||
try (serverSocket) {
|
||||
// Bind it to the loopback address
|
||||
SocketAddress sockAddr = new InetSocketAddress(
|
||||
InetAddress.getLoopbackAddress(), 0);
|
||||
serverSocket.bind(sockAddr);
|
||||
|
||||
// Construct the provider URL for LDAPTestUtils
|
||||
String providerURL = URIBuilder.newBuilder()
|
||||
.scheme("ldap")
|
||||
.loopback()
|
||||
.port(serverSocket.getLocalPort())
|
||||
.buildUnchecked().toString();
|
||||
|
||||
// Create and initialize test environment variables
|
||||
Hashtable<Object, Object> env;
|
||||
env = LDAPTestUtils.initEnv(serverSocket, providerURL,
|
||||
LdapFactoriesFilterTest.class.getName(), args, false);
|
||||
DirContext ctx = new InitialDirContext(env);
|
||||
Exception observedException = null;
|
||||
Object lookupRes = null;
|
||||
|
||||
// Lookup bound reference
|
||||
try {
|
||||
lookupRes = ctx.lookup("Example");
|
||||
System.err.println("Lookup results: " + lookupRes.getClass().getCanonicalName());
|
||||
} catch (Exception ex) {
|
||||
observedException = ex;
|
||||
}
|
||||
|
||||
// Check lookup operation results
|
||||
if (testFactoryAllowed) {
|
||||
// NamingException with RuntimeException cause is expected here
|
||||
if (observedException instanceof NamingException namingException) {
|
||||
System.err.println("Observed NamingException: " + observedException);
|
||||
Throwable cause = namingException.getCause();
|
||||
System.err.println("NamingException cause: " + cause);
|
||||
// We expect RuntimeException from factory for cases when LDAP factory
|
||||
// filter allows the test factory
|
||||
if (cause instanceof RuntimeException rte) {
|
||||
String rteMessage = rte.getMessage();
|
||||
System.err.println("RuntimeException message: " + rteMessage);
|
||||
if (!com.test.TestFactory.RUNTIME_EXCEPTION_MESSAGE.equals(rteMessage)) {
|
||||
throw new AssertionError(
|
||||
"Unexpected RuntimeException message observed");
|
||||
}
|
||||
} else {
|
||||
throw new AssertionError(
|
||||
"RuntimeException is expected to be thrown" +
|
||||
" by the test object factory");
|
||||
}
|
||||
} else {
|
||||
throw new AssertionError(
|
||||
"NamingException was not thrown as expected");
|
||||
}
|
||||
} else if (!ldapAndGlobalFiltersValid) {
|
||||
// If LDAP or GLOBAL factories filter are not properly formatted we're expecting to
|
||||
// get NamingException with IllegalArgumentException set as a cause that contains
|
||||
// formatting error message.
|
||||
// If RMI filter is not properly formatted we're not expecting IAE here since
|
||||
// this test only performing LDAP lookups
|
||||
if (observedException instanceof NamingException ne) {
|
||||
if (ne.getCause() instanceof IllegalArgumentException iae) {
|
||||
// All tests with malformed filters contain wildcards with
|
||||
// package name missing, therefore the message is expected
|
||||
// to start with "package missing in:"
|
||||
System.err.println("Found expected exception: " + iae);
|
||||
} else {
|
||||
throw new AssertionError("IllegalArgumentException" +
|
||||
" is expected for malformed filter values");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Object factory is not allowed by the factories filter
|
||||
// we expect reference here
|
||||
if (lookupRes instanceof Reference ref) {
|
||||
System.err.println("Lookup result is a reference: " +
|
||||
ref.getFactoryClassLocation() + " " + ref.getFactoryClassName());
|
||||
} else {
|
||||
new AssertionError("Reference was not returned as a lookup result");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
#
|
||||
# Copyright (c) 2022, 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# Capture file for LdapFactoriesFilterTest.java
|
||||
#
|
||||
# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
|
||||
# running the LdapFactoriesFilterTest application program against a real
|
||||
# LDAP server and setting the JNDI/LDAP environment property:
|
||||
# com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# LDAP BindRequest
|
||||
0000: 30 0C 02 01 01 60 07 02 01 03 04 00 80 00 0....`........
|
||||
|
||||
# LDAP BindResponse
|
||||
0000: 30 0C 02 01 01 61 07 0A 01 00 04 00 04 00 0....a........
|
||||
|
||||
# LDAP SearchRequest
|
||||
0000: 30 49 02 01 02 63 27 04 07 45 78 61 6D 70 6C 65 0I...c'..Example
|
||||
0010: 0A 01 00 0A 01 03 02 01 00 02 01 00 01 01 00 87 ................
|
||||
0020: 0B 6F 62 6A 65 63 74 43 6C 61 73 73 30 00 A0 1B .objectClass0...
|
||||
0030: 30 19 04 17 32 2E 31 36 2E 38 34 30 2E 31 2E 31 0...2.16.840.1.1
|
||||
0040: 31 33 37 33 30 2E 33 2E 34 2E 32 13730.3.4.2
|
||||
|
||||
# LDAP SearchResultEntry
|
||||
0000: 30 75 02 01 02 64 70 04 07 45 78 61 6D 70 6C 65 0u...dp..Example
|
||||
0010: 30 65 30 16 04 0D 6A 61 76 61 43 6C 61 73 73 4E 0e0...javaClassN
|
||||
0020: 61 6D 65 31 05 04 03 66 6F 6F 30 24 04 0B 6F 62 ame1...foo0$..ob
|
||||
0030: 6A 65 63 74 43 6C 61 73 73 31 15 04 13 6A 61 76 jectClass1...jav
|
||||
0040: 61 4E 61 6D 69 6E 67 52 65 66 65 72 65 6E 63 65 aNamingReference
|
||||
0050: 30 25 04 0B 6A 61 76 61 46 61 63 74 6F 72 79 31 0%..javaFactory1
|
||||
0060: 16 04 14 63 6F 6D 2E 74 65 73 74 2E 54 65 73 74 ...com.test.Test
|
||||
0070: 46 61 63 74 6F 72 79 Factory
|
||||
|
||||
# LDAP SearchResultDone
|
||||
0000: 30 0C 02 01 02 65 07 0A 01 00 04 00 04 00 0....e........
|
40
test/jdk/com/sun/jndi/ldap/objects/factory/TestFactory.java
Normal file
40
test/jdk/com/sun/jndi/ldap/objects/factory/TestFactory.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*
|
||||
* 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.test;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class TestFactory implements ObjectFactory {
|
||||
public static final String RUNTIME_EXCEPTION_MESSAGE =
|
||||
"Test object factory is called to instantiate factory";
|
||||
|
||||
@Override
|
||||
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
|
||||
System.err.println("obj:" + obj);
|
||||
throw new RuntimeException(RUNTIME_EXCEPTION_MESSAGE);
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
jdk.jndi.ldap.object.factoriesFilter=com.test.TestFactory;!*
|
@ -0,0 +1 @@
|
||||
jdk.jndi.ldap.object.factoriesFilter=!com.test.TestFactory
|
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.Reference;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8290368
|
||||
* @summary Checks if RMI specific objects factory filter system and security
|
||||
* properties can be used to restrict usage of object factories during
|
||||
* RMI lookup operations.
|
||||
* @modules java.rmi/sun.rmi.registry
|
||||
* java.rmi/sun.rmi.server
|
||||
* java.rmi/sun.rmi.transport
|
||||
* java.rmi/sun.rmi.transport.tcp
|
||||
* @library ../../../../../../java/rmi/testlibrary
|
||||
* @build TestLibrary
|
||||
* @compile TestFactory.java
|
||||
*
|
||||
* @run main/othervm RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=*
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.**;!*
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.test.**;!*
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.test.*;!*
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.test.Test*;!*
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=!com.test.**
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=!com.test.TestFactory;com.**
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=!com.test.TestFactory;com.test.*
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=!com.test.Test*
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.*;!*
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.test.TestFactor;!*
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=com.test.TestFactoryy;!*
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/disallowRmiFilter.props
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/disallowRmiFilter.props
|
||||
* -Djdk.jndi.rmi.object.factoriesFilter=com.test.TestFactory
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/allowRmiFilter.props
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/allowRmiFilter.props
|
||||
* -Djdk.jndi.ldap.object.factoriesFilter=!com.test.TestFactory
|
||||
* RmiFactoriesFilterTest true true
|
||||
*
|
||||
* @run main/othervm -Djava.security.properties=${test.src}/allowRmiFilter.props
|
||||
* -Djdk.jndi.rmi.object.factoriesFilter=!com.test.TestFactory
|
||||
* RmiFactoriesFilterTest false true
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=.*
|
||||
* RmiFactoriesFilterTest false false
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=*
|
||||
* -Djdk.jndi.object.factoriesFilter=.*
|
||||
* RmiFactoriesFilterTest false false
|
||||
*
|
||||
* @run main/othervm -Djdk.jndi.rmi.object.factoriesFilter=*
|
||||
* -Djdk.jndi.object.factoriesFilter=*
|
||||
* -Djdk.jndi.ldap.object.factoriesFilter=.*
|
||||
* RmiFactoriesFilterTest true true
|
||||
*/
|
||||
|
||||
public class RmiFactoriesFilterTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
boolean classExpectedToLoad = Boolean.parseBoolean(args[0]);
|
||||
boolean rmiAndGlobalFiltersValid =
|
||||
Boolean.parseBoolean(args[1]);
|
||||
int registryPort;
|
||||
try {
|
||||
Registry registry = TestLibrary.createRegistryOnEphemeralPort();
|
||||
registryPort = TestLibrary.getRegistryPort(registry);
|
||||
System.out.println("Registry port: " + registryPort);
|
||||
} catch (RemoteException re) {
|
||||
throw new RuntimeException("Failed to create registry", re);
|
||||
}
|
||||
|
||||
Context context = getInitialContext(registryPort);
|
||||
// Bind the Reference object
|
||||
Reference ref = new Reference("TestObject", "com.test.TestFactory",
|
||||
null);
|
||||
context.bind("objectTest", ref);
|
||||
|
||||
loadUsingFactoryFromTCCL(registryPort, classExpectedToLoad, rmiAndGlobalFiltersValid);
|
||||
if (!rmiAndGlobalFiltersValid) {
|
||||
// Check that IAE is set as NamingException cause for malformed RMI or GLOBAL
|
||||
// filter values when lookup is called for the second time
|
||||
loadUsingFactoryFromTCCL(registryPort, classExpectedToLoad, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static Context getInitialContext(int port) throws NamingException {
|
||||
Hashtable<String, String> env = new Hashtable<>();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY,
|
||||
"com.sun.jndi.rmi.registry.RegistryContextFactory");
|
||||
env.put(Context.PROVIDER_URL, "rmi://127.0.0.1:" + port);
|
||||
return new InitialContext(env);
|
||||
}
|
||||
|
||||
private static void loadUsingFactoryFromTCCL(int registryPort,
|
||||
boolean classExpectedToLoad,
|
||||
boolean rmiAndGlobalFiltersValid) {
|
||||
|
||||
|
||||
try {
|
||||
Context context = getInitialContext(registryPort);
|
||||
Object object = context.lookup("objectTest");
|
||||
System.out.println("Number of getObjectInstance calls:" +
|
||||
com.test.TestFactory.getNumberOfGetInstanceCalls());
|
||||
System.out.println("Loaded class type:" + object.getClass().getCanonicalName());
|
||||
System.out.println("Loaded class: " + object);
|
||||
if (classExpectedToLoad) {
|
||||
if (!"TestObject".equals(object)) {
|
||||
throw new AssertionError("Class was expected to get loaded by the factory");
|
||||
}
|
||||
} else {
|
||||
if ("TestObject".equals(object)) {
|
||||
throw new AssertionError("Class was unexpectedly loaded by the factory");
|
||||
}
|
||||
}
|
||||
} catch (NamingException ne) {
|
||||
// Only expecting NamingException for cases when RMI or GLOBAL filters are malformed
|
||||
if (rmiAndGlobalFiltersValid) {
|
||||
throw new AssertionError("Unexpected NamingException observed", ne);
|
||||
}
|
||||
if (ne.getCause() instanceof IllegalArgumentException iae) {
|
||||
// All tests with malformed filters contain wildcards with
|
||||
// package name missing, therefore the message is expected
|
||||
// to start with "package missing in:"
|
||||
System.err.println("Found expected exception: " + iae);
|
||||
} else {
|
||||
throw new AssertionError("IllegalArgument exception" +
|
||||
" is expected for malformed filter values");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
test/jdk/com/sun/jndi/rmi/registry/objects/TestFactory.java
Normal file
77
test/jdk/com/sun/jndi/rmi/registry/objects/TestFactory.java
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*
|
||||
* 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.test;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class TestFactory implements ObjectFactory {
|
||||
|
||||
/**
|
||||
* Get the number of {@code TestFactory.getObjectInstance} calls
|
||||
*
|
||||
* @return the number of calls
|
||||
*/
|
||||
public static int getNumberOfGetInstanceCalls() {
|
||||
return timesGetInstanceCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param obj The possibly null object containing location or reference
|
||||
* information that can be used in creating an object.
|
||||
* @param name The name of this object relative to {@code nameCtx},
|
||||
* or null if no name is specified.
|
||||
* @param nameCtx The context relative to which the {@code name}
|
||||
* parameter is specified, or null if {@code name} is
|
||||
* relative to the default initial context.
|
||||
* @param environment The possibly null environment that is used in
|
||||
* creating the object.
|
||||
* @return If specified object is a {@code Reference} returns a {@code String} with a class
|
||||
* name specified in the reference, otherwise returns {@code "TestObj"}
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
|
||||
timesGetInstanceCalled++;
|
||||
String loadedObject;
|
||||
if (obj instanceof Reference) {
|
||||
Reference r = (Reference) obj;
|
||||
System.err.println("TestFactory: loading javax.naming.Reference:");
|
||||
System.err.println("\tFactory location=" + r.getFactoryClassLocation());
|
||||
System.err.println("\tFactory class name=" + r.getFactoryClassName());
|
||||
System.err.println("\tClass name=" + r.getClassName());
|
||||
loadedObject = r.getClassName();
|
||||
} else {
|
||||
System.err.println("TestFactory: loading " + obj.getClass().getName());
|
||||
loadedObject = "TestObj";
|
||||
}
|
||||
return loadedObject;
|
||||
}
|
||||
|
||||
private static volatile int timesGetInstanceCalled;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
jdk.jndi.rmi.object.factoriesFilter=com.test.TestFactory;!*
|
@ -0,0 +1 @@
|
||||
jdk.jndi.rmi.object.factoriesFilter=!com.test.TestFactory;*
|
@ -98,7 +98,8 @@ public class RunBasic {
|
||||
runTest("person", "test.StorePerson",
|
||||
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
||||
runTest("fruit", "test.StoreFruit",
|
||||
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
||||
"-Dcom.sun.jndi.ldap.object.trustSerialData=true",
|
||||
"-Djdk.jndi.ldap.object.factoriesFilter=org.example.fruit.FruitFactory");
|
||||
runTest("hello", "test.StoreRemote",
|
||||
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
||||
runTest("foo", "test.ConnectWithFoo");
|
||||
|
Loading…
x
Reference in New Issue
Block a user