diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java index 1a418b93b6..bf17de99ec 100644 --- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java +++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java @@ -65,9 +65,6 @@ public class RmiConnector { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); - static final String JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES = - "jmx.remote.rmi.server.credential.types"; - /** * JDK 10+ JMX environment property scoping a JEP 290 deserialization * filter to the credentials object passed during {@code newClient()}. @@ -75,15 +72,16 @@ public class RmiConnector * {@code jmx.remote.rmi.server.serial.filter.pattern}) avoids breaking * legitimate JMX traffic such as MBean invocations and notifications, * which may legitimately carry non-String types. + *

+ * Note: this property is mutually exclusive with + * {@code jmx.remote.rmi.server.credential.types}; specifying both makes + * {@code RMIJRMPServerImpl} throw an {@link IllegalArgumentException} and + * prevents the connector from starting. The filter pattern is preferred + * because it additionally constrains array length and nesting depth. */ static final String JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN = "jmx.remote.rmi.server.credentials.filter.pattern"; - private static final String[] JMX_CREDENTIAL_TYPES = - { - String.class.getName(), - String[].class.getName() - }; private static final String JMX_CREDENTIAL_SERIAL_FILTER = "maxdepth=3;maxarray=2;java.lang.String;!*"; @@ -392,11 +390,13 @@ private void startConnectorNoClientCertificate() throws Exception static void configureJmxDeserializationProtection(Map env) { - env.put(JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES, - JMX_CREDENTIAL_TYPES.clone()); // Scope the JEP 290 deserialization filter to the credentials object // only, so legitimate JMX RMI traffic (MBean operations, notifications, // etc.) is not affected by the restrictive allowlist. + // + // Do NOT also set "jmx.remote.rmi.server.credential.types": the JDK + // rejects an environment that defines both properties, which would + // prevent the RMI connector from starting. env.put(JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN, JMX_CREDENTIAL_SERIAL_FILTER); } diff --git a/opendj-server-legacy/src/test/java/org/opends/server/protocols/jmx/RmiAuthenticatorTest.java b/opendj-server-legacy/src/test/java/org/opends/server/protocols/jmx/RmiAuthenticatorTest.java index 6c7b5eb3ec..7dce751fce 100644 --- a/opendj-server-legacy/src/test/java/org/opends/server/protocols/jmx/RmiAuthenticatorTest.java +++ b/opendj-server-legacy/src/test/java/org/opends/server/protocols/jmx/RmiAuthenticatorTest.java @@ -67,29 +67,15 @@ public void configuresCredentialDeserializationProtection() Map env = new HashMap<>(); RmiConnector.configureJmxDeserializationProtection(env); - assertEquals(env.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES), - new String[] { String.class.getName(), String[].class.getName() }); assertEquals(env.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN), "maxdepth=3;maxarray=2;java.lang.String;!*"); // The connector-wide filter must NOT be set, so legitimate JMX traffic // (MBean operations, notifications) is not affected by the allowlist. assertNull(env.get("jmx.remote.rmi.server.serial.filter.pattern")); - } - - /** Verifies that each environment receives its own credential type array. */ - @Test - public void credentialTypesAreDefensivelyCopied() - { - Map env = new HashMap<>(); - RmiConnector.configureJmxDeserializationProtection(env); - String[] credentialTypes = - (String[]) env.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES); - credentialTypes[0] = Date.class.getName(); - - Map env2 = new HashMap<>(); - RmiConnector.configureJmxDeserializationProtection(env2); - assertEquals(((String[]) env2.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES))[0], - String.class.getName()); + // "jmx.remote.rmi.server.credential.types" is mutually exclusive with the + // credentials filter pattern: setting both prevents the connector from + // starting, so only the filter pattern must be configured. + assertNull(env.get("jmx.remote.rmi.server.credential.types")); } /** Verifies the configured filter allows only the expected credential payload. */