mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8187556: Backout of a fix reintroduced a dependency that had since been removed
Reviewed-by: duke
This commit is contained in:
parent
8d9060c1a6
commit
65db4f42d0
13 changed files with 755 additions and 254 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
package com.sun.jmx.remote.internal.rmi;
|
||||
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
|
@ -51,7 +52,8 @@ public interface RMIExporter {
|
|||
public Remote exportObject(Remote obj,
|
||||
int port,
|
||||
RMIClientSocketFactory csf,
|
||||
RMIServerSocketFactory ssf)
|
||||
RMIServerSocketFactory ssf,
|
||||
ObjectInputFilter filter)
|
||||
throws RemoteException;
|
||||
|
||||
public boolean unexportObject(Remote obj, boolean force)
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.sun.jmx.remote.util.EnvHelp;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.rmi.server.RMIClientSocketFactory;
|
||||
|
@ -101,19 +102,59 @@ public class RMIConnectorServer extends JMXConnectorServer {
|
|||
"jmx.remote.rmi.server.socket.factory";
|
||||
|
||||
/**
|
||||
* Name of the attribute that specifies a list of class names acceptable
|
||||
* as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
|
||||
* Name of the attribute that specifies an
|
||||
* {@link ObjectInputFilter} pattern string to filter classes acceptable
|
||||
* for {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
|
||||
* remote method call.
|
||||
* <p>
|
||||
* This list of classes should correspond to the transitive closure of the
|
||||
* credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
|
||||
* associated with the {@linkplain RMIServer} implementation.
|
||||
* The filter pattern must be in same format as used in
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter}
|
||||
* <p>
|
||||
* If the attribute is not set, or is null, then any class is
|
||||
* deemed acceptable.
|
||||
* This list of classes allowed by filter should correspond to the
|
||||
* transitive closure of the credentials class (or classes) used by the
|
||||
* installed {@linkplain JMXAuthenticator} associated with the
|
||||
* {@linkplain RMIServer} implementation.
|
||||
* If the attribute is not set then any class is deemed acceptable.
|
||||
* @see ObjectInputFilter
|
||||
*/
|
||||
public static final String CREDENTIAL_TYPES =
|
||||
"jmx.remote.rmi.server.credential.types";
|
||||
public static final String CREDENTIALS_FILTER_PATTERN =
|
||||
"jmx.remote.rmi.server.credentials.filter.pattern";
|
||||
|
||||
/**
|
||||
* This attribute defines a pattern from which to create a
|
||||
* {@link java.io.ObjectInputFilter} that will be used when deserializing
|
||||
* objects sent to the {@code JMXConnectorServer} by any client.
|
||||
* <p>
|
||||
* The filter will be called for any class found in the serialized
|
||||
* stream sent to server by client, including all JMX defined classes
|
||||
* (such as {@link javax.management.ObjectName}), all method parameters,
|
||||
* and, if present in the stream, all classes transitively referred by
|
||||
* the serial form of any deserialized object.
|
||||
* The pattern must be in same format as used in
|
||||
* {@link java.io.ObjectInputFilter.Config#createFilter}.
|
||||
* It may define a white list of permitted classes, a black list of
|
||||
* rejected classes, a maximum depth for the deserialized objects,
|
||||
* etc.
|
||||
* <p>
|
||||
* To be functional, the filter should allow at least all the
|
||||
* concrete types in the transitive closure of all objects that
|
||||
* might get serialized when serializing all JMX classes referred
|
||||
* as parameters in the {@link
|
||||
* javax.management.remote.rmi.RMIConnection} interface,
|
||||
* plus all classes that a {@link javax.management.remote.rmi.RMIConnector client}
|
||||
* might need to transmit wrapped in {@linkplain java.rmi.MarshalledObject
|
||||
* marshalled objects} in order to interoperate with the MBeans registered
|
||||
* in the {@code MBeanServer}. That would potentially include all the
|
||||
* concrete {@linkplain javax.management.openmbean JMX OpenTypes} and the
|
||||
* classes they use in their serial form.
|
||||
* <p>
|
||||
* Care must be taken when defining such a filter, as defining
|
||||
* a white list too restrictive or a too wide a black list may
|
||||
* prevent legitimate clients from interoperating with the
|
||||
* {@code JMXConnectorServer}.
|
||||
*/
|
||||
public static final String SERIAL_FILTER_PATTERN =
|
||||
"jmx.remote.rmi.server.serial.filter.pattern";
|
||||
|
||||
/**
|
||||
* <p>Makes an <code>RMIConnectorServer</code>.
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
package javax.management.remote.rmi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
|
@ -39,15 +40,13 @@ import javax.security.auth.Subject;
|
|||
|
||||
import com.sun.jmx.remote.internal.rmi.RMIExporter;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
import sun.rmi.server.DeserializationChecker;
|
||||
import sun.rmi.server.UnicastServerRef;
|
||||
import sun.rmi.server.UnicastServerRef2;
|
||||
import sun.rmi.transport.LiveRef;
|
||||
|
||||
/**
|
||||
* <p>An {@link RMIServer} object that is exported through JRMP and that
|
||||
|
@ -60,8 +59,6 @@ import sun.rmi.server.UnicastServerRef2;
|
|||
*/
|
||||
public class RMIJRMPServerImpl extends RMIServerImpl {
|
||||
|
||||
private final ExportedWrapper exportedWrapper;
|
||||
|
||||
/**
|
||||
* <p>Creates a new {@link RMIServer} object that will be exported
|
||||
* on the given port using the given socket factories.</p>
|
||||
|
@ -100,33 +97,48 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
|||
this.ssf = ssf;
|
||||
this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
|
||||
|
||||
// This attribute was represented by RMIConnectorServer.CREDENTIALS_TYPES.
|
||||
// This attribute is superceded by
|
||||
// RMIConnectorServer.CREDENTIALS_FILTER_PATTERN.
|
||||
// Retaining this for backward compatibility.
|
||||
String[] credentialsTypes
|
||||
= (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
|
||||
List<String> types = null;
|
||||
if (credentialsTypes != null) {
|
||||
types = new ArrayList<>();
|
||||
for (String type : credentialsTypes) {
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("A credential type is null.");
|
||||
}
|
||||
ReflectUtil.checkPackageAccess(type);
|
||||
types.add(type);
|
||||
}
|
||||
= (String[]) this.env.get("jmx.remote.rmi.server.credential.types");
|
||||
|
||||
String credentialsFilter
|
||||
= (String) this.env.get(RMIConnectorServer.CREDENTIALS_FILTER_PATTERN);
|
||||
|
||||
// It is impossible for both attributes to be specified
|
||||
if(credentialsTypes != null && credentialsFilter != null)
|
||||
throw new IllegalArgumentException("Cannot specify both \""
|
||||
+ "jmx.remote.rmi.server.credential.types" + "\" and \""
|
||||
+ RMIConnectorServer.CREDENTIALS_FILTER_PATTERN + "\"");
|
||||
else if(credentialsFilter != null){
|
||||
cFilter = ObjectInputFilter.Config.createFilter(credentialsFilter);
|
||||
allowedTypes = null;
|
||||
}
|
||||
exportedWrapper = types != null ?
|
||||
new ExportedWrapper(this, types) :
|
||||
null;
|
||||
else if (credentialsTypes != null) {
|
||||
allowedTypes = Arrays.stream(credentialsTypes).filter(
|
||||
s -> s!= null).collect(Collectors.toSet());
|
||||
allowedTypes.stream().forEach(ReflectUtil::checkPackageAccess);
|
||||
cFilter = this::newClientCheckInput;
|
||||
} else {
|
||||
allowedTypes = null;
|
||||
cFilter = null;
|
||||
}
|
||||
|
||||
String userJmxFilter =
|
||||
(String) this.env.get(RMIConnectorServer.SERIAL_FILTER_PATTERN);
|
||||
if(userJmxFilter != null && !userJmxFilter.isEmpty())
|
||||
jmxRmiFilter = ObjectInputFilter.Config.createFilter(userJmxFilter);
|
||||
else
|
||||
jmxRmiFilter = null;
|
||||
}
|
||||
|
||||
protected void export() throws IOException {
|
||||
if (exportedWrapper != null) {
|
||||
export(exportedWrapper);
|
||||
} else {
|
||||
export(this);
|
||||
}
|
||||
export(this, cFilter);
|
||||
}
|
||||
|
||||
private void export(Remote obj) throws RemoteException {
|
||||
private void export(Remote obj, ObjectInputFilter typeFilter) throws RemoteException {
|
||||
final RMIExporter exporter =
|
||||
(RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
|
||||
final boolean daemon = EnvHelp.isServerDaemon(env);
|
||||
|
@ -137,16 +149,14 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
|||
" cannot be used to specify an exporter!");
|
||||
}
|
||||
|
||||
if (daemon) {
|
||||
if (csf == null && ssf == null) {
|
||||
new UnicastServerRef(port).exportObject(obj, null, true);
|
||||
} else {
|
||||
new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
|
||||
}
|
||||
} else if (exporter != null) {
|
||||
exporter.exportObject(obj, port, csf, ssf);
|
||||
if (exporter != null) {
|
||||
exporter.exportObject(obj, port, csf, ssf, typeFilter);
|
||||
} else {
|
||||
UnicastRemoteObject.exportObject(obj, port, csf, ssf);
|
||||
if (csf == null && ssf == null) {
|
||||
new UnicastServerRef(new LiveRef(port), typeFilter).exportObject(obj, null, daemon);
|
||||
} else {
|
||||
new UnicastServerRef2(port, csf, ssf, typeFilter).exportObject(obj, null, daemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,11 +183,7 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
|||
* RMIJRMPServerImpl has not been exported yet.
|
||||
*/
|
||||
public Remote toStub() throws IOException {
|
||||
if (exportedWrapper != null) {
|
||||
return RemoteObject.toStub(exportedWrapper);
|
||||
} else {
|
||||
return RemoteObject.toStub(this);
|
||||
}
|
||||
return RemoteObject.toStub(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +213,7 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
|||
RMIConnection client =
|
||||
new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
|
||||
subject, env);
|
||||
export(client);
|
||||
export(client, jmxRmiFilter);
|
||||
return client;
|
||||
}
|
||||
|
||||
|
@ -224,56 +230,39 @@ public class RMIJRMPServerImpl extends RMIServerImpl {
|
|||
* server failed.
|
||||
*/
|
||||
protected void closeServer() throws IOException {
|
||||
if (exportedWrapper != null) {
|
||||
unexport(exportedWrapper, true);
|
||||
} else {
|
||||
unexport(this, true);
|
||||
unexport(this, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a type in the remote invocation of {@link RMIServerImpl#newClient}
|
||||
* is one of the {@code allowedTypes}.
|
||||
*
|
||||
* @param clazz the class; may be null
|
||||
* @param size the size for arrays, otherwise is 0
|
||||
* @param nObjectRefs the current number of object references
|
||||
* @param depth the current depth
|
||||
* @param streamBytes the current number of bytes consumed
|
||||
* @return {@code ObjectInputFilter.Status.ALLOWED} if the class is allowed,
|
||||
* otherwise {@code ObjectInputFilter.Status.REJECTED}
|
||||
*/
|
||||
ObjectInputFilter.Status newClientCheckInput(ObjectInputFilter.FilterInfo filterInfo) {
|
||||
ObjectInputFilter.Status status = ObjectInputFilter.Status.UNDECIDED;
|
||||
if (allowedTypes != null && filterInfo.serialClass() != null) {
|
||||
// If enabled, check type
|
||||
String type = filterInfo.serialClass().getName();
|
||||
if (allowedTypes.contains(type))
|
||||
status = ObjectInputFilter.Status.ALLOWED;
|
||||
else
|
||||
status = ObjectInputFilter.Status.REJECTED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
private final int port;
|
||||
private final RMIClientSocketFactory csf;
|
||||
private final RMIServerSocketFactory ssf;
|
||||
private final Map<String, ?> env;
|
||||
|
||||
private static class ExportedWrapper implements RMIServer, DeserializationChecker {
|
||||
private final RMIServer impl;
|
||||
private final List<String> allowedTypes;
|
||||
|
||||
private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
|
||||
this.impl = impl;
|
||||
allowedTypes = credentialsTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() throws RemoteException {
|
||||
return impl.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RMIConnection newClient(Object credentials) throws IOException {
|
||||
return impl.newClient(credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(Method method, ObjectStreamClass descriptor,
|
||||
int paramIndex, int callID) {
|
||||
String type = descriptor.getName();
|
||||
if (!allowedTypes.contains(type)) {
|
||||
throw new ClassCastException("Unsupported type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkProxyClass(Method method, String[] ifaces,
|
||||
int paramIndex, int callID) {
|
||||
if (ifaces != null && ifaces.length > 0) {
|
||||
for (String iface : ifaces) {
|
||||
if (!allowedTypes.contains(iface)) {
|
||||
throw new ClassCastException("Unsupported type: " + iface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private final Set<String> allowedTypes;
|
||||
private final ObjectInputFilter jmxRmiFilter;
|
||||
private final ObjectInputFilter cFilter;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue