mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
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
22 changed files with 1263 additions and 355 deletions
|
@ -1376,17 +1376,18 @@ jdk.io.permissionsUseCanonicalPath=false
|
||||||
jdk.tls.alpnCharset=ISO_8859_1
|
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
|
# 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
|
# 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
|
# 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
|
# 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
|
# 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 unless the filter returns
|
# instantiation. The access to a factory class is allowed if the filter returns
|
||||||
# REJECTED.
|
# ALLOWED.
|
||||||
#
|
#
|
||||||
# Note: This property is currently used by the JDK Reference implementation.
|
# Note: This property is currently used by the JDK Reference implementation.
|
||||||
# It is not guaranteed to be examined and used by other implementations.
|
# 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.
|
# instance to recreate the referenced object.
|
||||||
#jdk.jndi.object.factoriesFilter=*
|
#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
|
# 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.*;
|
||||||
import javax.naming.directory.*;
|
import javax.naming.directory.*;
|
||||||
import javax.naming.ldap.Control;
|
import javax.naming.ldap.Control;
|
||||||
import javax.naming.spi.*;
|
|
||||||
|
|
||||||
import com.sun.jndi.toolkit.ctx.Continuation;
|
import com.sun.jndi.toolkit.ctx.Continuation;
|
||||||
|
import com.sun.naming.internal.NamingManagerHelper;
|
||||||
|
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||||
|
|
||||||
final class LdapBindingEnumeration
|
final class LdapBindingEnumeration
|
||||||
extends AbstractLdapNamingEnumeration<Binding> {
|
extends AbstractLdapNamingEnumeration<Binding> {
|
||||||
|
@ -76,8 +77,8 @@ final class LdapBindingEnumeration
|
||||||
cn.add(atom);
|
cn.add(atom);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
obj = DirectoryManager.getObjectInstance(obj, cn, homeCtx,
|
obj = NamingManagerHelper.getDirObjectInstance(obj, cn, homeCtx,
|
||||||
homeCtx.envprops, attrs);
|
homeCtx.envprops, attrs, ObjectFactoriesFilter::checkLdapFilter);
|
||||||
|
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.*;
|
||||||
import javax.naming.directory.*;
|
import javax.naming.directory.*;
|
||||||
import javax.naming.spi.*;
|
|
||||||
import javax.naming.event.*;
|
import javax.naming.event.*;
|
||||||
import javax.naming.ldap.*;
|
import javax.naming.ldap.*;
|
||||||
import javax.naming.ldap.LdapName;
|
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.HierMemDirCtx;
|
||||||
import com.sun.jndi.toolkit.dir.SearchFilter;
|
import com.sun.jndi.toolkit.dir.SearchFilter;
|
||||||
import com.sun.jndi.ldap.ext.StartTlsResponseImpl;
|
import com.sun.jndi.ldap.ext.StartTlsResponseImpl;
|
||||||
|
import com.sun.naming.internal.NamingManagerHelper;
|
||||||
|
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The LDAP context implementation.
|
* The LDAP context implementation.
|
||||||
|
@ -1111,8 +1112,8 @@ public final class LdapCtx extends ComponentDirContext
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return DirectoryManager.getObjectInstance(obj, name,
|
return NamingManagerHelper.getDirObjectInstance(obj, name, this,
|
||||||
this, envprops, attrs);
|
envprops, attrs, ObjectFactoriesFilter::checkLdapFilter);
|
||||||
|
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw cont.fillInException(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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.*;
|
||||||
import javax.naming.directory.*;
|
import javax.naming.directory.*;
|
||||||
import javax.naming.spi.*;
|
|
||||||
import javax.naming.ldap.*;
|
import javax.naming.ldap.*;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import com.sun.jndi.toolkit.dir.SearchFilter;
|
import com.sun.jndi.toolkit.dir.SearchFilter;
|
||||||
|
import com.sun.naming.internal.NamingManagerHelper;
|
||||||
|
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A context for handling referrals.
|
* A context for handling referrals.
|
||||||
|
@ -116,8 +117,8 @@ final class LdapReferralContext implements DirContext, LdapContext {
|
||||||
|
|
||||||
Object obj;
|
Object obj;
|
||||||
try {
|
try {
|
||||||
obj = NamingManager.getObjectInstance(ref, null, null, env);
|
obj = NamingManagerHelper.getObjectInstance(ref, null, null,
|
||||||
|
env, ObjectFactoriesFilter::checkLdapFilter);
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
|
|
||||||
if (handleReferrals == LdapClient.LDAP_REF_THROW) {
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 java.util.Vector;
|
||||||
import javax.naming.*;
|
import javax.naming.*;
|
||||||
import javax.naming.directory.*;
|
import javax.naming.directory.*;
|
||||||
import javax.naming.spi.*;
|
|
||||||
import javax.naming.ldap.*;
|
import javax.naming.ldap.*;
|
||||||
import javax.naming.ldap.LdapName;
|
import javax.naming.ldap.LdapName;
|
||||||
|
|
||||||
import com.sun.jndi.toolkit.ctx.Continuation;
|
import com.sun.jndi.toolkit.ctx.Continuation;
|
||||||
|
import com.sun.naming.internal.NamingManagerHelper;
|
||||||
|
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||||
|
|
||||||
final class LdapSearchEnumeration
|
final class LdapSearchEnumeration
|
||||||
extends AbstractLdapNamingEnumeration<SearchResult> {
|
extends AbstractLdapNamingEnumeration<SearchResult> {
|
||||||
|
@ -134,9 +135,9 @@ final class LdapSearchEnumeration
|
||||||
// Call getObjectInstance before removing unrequested attributes
|
// Call getObjectInstance before removing unrequested attributes
|
||||||
try {
|
try {
|
||||||
// rcn is either relative to homeCtx or a fully qualified DN
|
// rcn is either relative to homeCtx or a fully qualified DN
|
||||||
obj = DirectoryManager.getObjectInstance(
|
obj = NamingManagerHelper.getDirObjectInstance(
|
||||||
obj, rcn, (relative ? homeCtx : null),
|
obj, rcn, (relative ? homeCtx : null),
|
||||||
homeCtx.envprops, attrs);
|
homeCtx.envprops, attrs, ObjectFactoriesFilter::checkLdapFilter);
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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"}
|
* Checks if serial filter configured with {@code "jdk.jndi.object.factoriesFilter"}
|
||||||
* system property value allows instantiation of the specified objects factory class.
|
* 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.
|
* 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
|
* @return true - if the factory is allowed to be instantiated; false - otherwise
|
||||||
*/
|
*/
|
||||||
public static boolean canInstantiateObjectsFactory(Class<?> factoryClass) {
|
public static boolean checkGlobalFilter(Class<?> serialClass) {
|
||||||
return checkInput(() -> factoryClass);
|
return checkInput(GLOBAL_FILTER, () -> serialClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkInput(FactoryInfo factoryInfo) {
|
/**
|
||||||
Status result = GLOBAL.checkInput(factoryInfo);
|
* Checks if the factory filters allow the given factory class for LDAP.
|
||||||
return result != Status.REJECTED;
|
* 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
|
// 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
|
// 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
|
// System property name that contains the patterns to filter LDAP object factory
|
||||||
private static final String DEFAULT_SP_VALUE = "*";
|
// names
|
||||||
|
private static final String LDAP_FACTORIES_FILTER_PROPNAME =
|
||||||
|
"jdk.jndi.ldap.object.factoriesFilter";
|
||||||
|
|
||||||
// System wide object factories filter constructed from the system property
|
// System property name that contains the patterns to filter RMI object factory
|
||||||
private static final ObjectInputFilter GLOBAL =
|
// names
|
||||||
ObjectInputFilter.Config.createFilter(getFilterPropertyValue());
|
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
|
// Get security or system property value
|
||||||
private static String getFilterPropertyValue() {
|
private static String getFilterPropertyValue(String propertyName,
|
||||||
String propVal = SecurityProperties.privilegedGetOverridable(FACTORIES_FILTER_PROPNAME);
|
String defaultValue) {
|
||||||
return propVal != null ? propVal : DEFAULT_SP_VALUE;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Context;
|
||||||
import javax.naming.Name;
|
import javax.naming.Name;
|
||||||
import javax.naming.Reference;
|
|
||||||
import javax.naming.Referenceable;
|
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.naming.CannotProceedException;
|
import javax.naming.CannotProceedException;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
import javax.naming.directory.Attributes;
|
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.ResourceManager;
|
||||||
import com.sun.naming.internal.FactoryEnumeration;
|
import com.sun.naming.internal.FactoryEnumeration;
|
||||||
|
|
||||||
|
@ -154,92 +154,8 @@ public class DirectoryManager extends NamingManager {
|
||||||
getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
||||||
Hashtable<?,?> environment, Attributes attrs)
|
Hashtable<?,?> environment, Attributes attrs)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
return NamingManagerHelper.getDirObjectInstance(refInfo, name, nameCtx,
|
||||||
ObjectFactory factory;
|
environment, attrs, ObjectFactoriesFilter::checkGlobalFilter);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,13 +25,13 @@
|
||||||
|
|
||||||
package javax.naming.spi;
|
package javax.naming.spi;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.naming.*;
|
import javax.naming.*;
|
||||||
|
|
||||||
|
import com.sun.naming.internal.NamingManagerHelper;
|
||||||
import com.sun.naming.internal.ObjectFactoriesFilter;
|
import com.sun.naming.internal.ObjectFactoriesFilter;
|
||||||
import com.sun.naming.internal.VersionHelper;
|
import com.sun.naming.internal.VersionHelper;
|
||||||
import com.sun.naming.internal.ResourceManager;
|
import com.sun.naming.internal.ResourceManager;
|
||||||
|
@ -78,11 +78,6 @@ public class NamingManager {
|
||||||
|
|
||||||
// --------- object factory stuff
|
// --------- object factory stuff
|
||||||
|
|
||||||
/**
|
|
||||||
* Package-private; used by DirectoryManager and NamingManager.
|
|
||||||
*/
|
|
||||||
private static ObjectFactoryBuilder object_factory_builder = null;
|
|
||||||
|
|
||||||
private static final ClassLoaderValue<InitialContextFactory> FACTORIES_CACHE =
|
private static final ClassLoaderValue<InitialContextFactory> FACTORIES_CACHE =
|
||||||
new ClassLoaderValue<>();
|
new ClassLoaderValue<>();
|
||||||
|
|
||||||
|
@ -111,110 +106,16 @@ public class NamingManager {
|
||||||
* @see ObjectFactoryBuilder
|
* @see ObjectFactoryBuilder
|
||||||
* @see java.lang.SecurityManager#checkSetFactory
|
* @see java.lang.SecurityManager#checkSetFactory
|
||||||
*/
|
*/
|
||||||
public static synchronized void setObjectFactoryBuilder(
|
public static void setObjectFactoryBuilder(
|
||||||
ObjectFactoryBuilder builder) throws NamingException {
|
ObjectFactoryBuilder builder) throws NamingException {
|
||||||
if (object_factory_builder != null)
|
NamingManagerHelper.setObjectFactoryBuilder(builder);
|
||||||
throw new IllegalStateException("ObjectFactoryBuilder already set");
|
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
SecurityManager security = System.getSecurityManager();
|
|
||||||
if (security != null) {
|
|
||||||
security.checkSetFactory();
|
|
||||||
}
|
|
||||||
object_factory_builder = builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for accessing object factory builder.
|
* Used for accessing object factory builder.
|
||||||
*/
|
*/
|
||||||
static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {
|
static ObjectFactoryBuilder getObjectFactoryBuilder() {
|
||||||
return object_factory_builder;
|
return NamingManagerHelper.getObjectFactoryBuilder();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -308,124 +209,11 @@ public class NamingManager {
|
||||||
public static Object
|
public static Object
|
||||||
getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
getObjectInstance(Object refInfo, Name name, Context nameCtx,
|
||||||
Hashtable<?,?> environment)
|
Hashtable<?,?> environment)
|
||||||
throws Exception
|
throws Exception {
|
||||||
{
|
return NamingManagerHelper.getObjectInstance(refInfo, name, nameCtx,
|
||||||
|
environment, ObjectFactoriesFilter::checkGlobalFilter);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
* Retrieves a context identified by {@code obj}, using the specified
|
||||||
* environment.
|
* environment.
|
||||||
|
|
|
@ -96,13 +96,31 @@
|
||||||
* be allowed to instantiate objects from object references returned by naming/directory systems.
|
* 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 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
|
* 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 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
|
* This property is also supported by the <a href="{@docRoot}/jdk.naming.rmi/module-summary.html">default JNDI
|
||||||
* RMI Provider</a>.
|
* RMI Provider</a>.
|
||||||
* <br>The default value allows any object factory class specified by the reference
|
* <br>The default value allows any object factory class specified by the reference
|
||||||
* instance to recreate the referenced object.
|
* instance to recreate the referenced object.
|
||||||
* </li>
|
* </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>
|
* </ul>
|
||||||
* <p>Other providers may define additional properties in their module description:
|
* <p>Other providers may define additional properties in their module description:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -133,6 +151,8 @@ module java.naming {
|
||||||
exports com.sun.jndi.toolkit.url to
|
exports com.sun.jndi.toolkit.url to
|
||||||
jdk.naming.dns,
|
jdk.naming.dns,
|
||||||
jdk.naming.rmi;
|
jdk.naming.rmi;
|
||||||
|
exports com.sun.naming.internal to
|
||||||
|
jdk.naming.rmi;
|
||||||
|
|
||||||
uses javax.naming.ldap.StartTlsResponse;
|
uses javax.naming.ldap.StartTlsResponse;
|
||||||
uses javax.naming.spi.InitialContextFactory;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,9 @@
|
||||||
package com.sun.jndi.rmi.registry;
|
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.Hashtable;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.rmi.*;
|
import java.rmi.*;
|
||||||
|
@ -498,8 +501,8 @@ public class RegistryContext implements Context, Referenceable {
|
||||||
"The object factory is untrusted. Set the system property" +
|
"The object factory is untrusted. Set the system property" +
|
||||||
" 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
|
" 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
|
||||||
}
|
}
|
||||||
return NamingManager.getObjectInstance(obj, name, this,
|
return NamingManagerHelper.getObjectInstance(obj, name, this,
|
||||||
environment);
|
environment, ObjectFactoriesFilter::checkRmiFilter);
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (RemoteException 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.
|
* 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 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
|
* 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 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
|
* This property is also supported by the <a href="{@docRoot}/java.naming/module-summary.html">default
|
||||||
* LDAP Naming Service Provider</a>.
|
* LDAP Naming Service Provider</a>.
|
||||||
* <br>The default value allows any object factory class specified by the reference
|
* <br>The default value allows any object factory class specified by the reference
|
||||||
* instance to recreate the referenced object.
|
* instance to recreate the referenced object.
|
||||||
* </li>
|
* </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>
|
* </ul>
|
||||||
* @provides javax.naming.spi.InitialContextFactory
|
* @provides javax.naming.spi.InitialContextFactory
|
||||||
* @moduleGraph
|
* @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",
|
runTest("person", "test.StorePerson",
|
||||||
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
||||||
runTest("fruit", "test.StoreFruit",
|
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",
|
runTest("hello", "test.StoreRemote",
|
||||||
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
"-Dcom.sun.jndi.ldap.object.trustSerialData=true");
|
||||||
runTest("foo", "test.ConnectWithFoo");
|
runTest("foo", "test.ConnectWithFoo");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue