Skip to content

Commit d4a95c2

Browse files
authored
Fix JMX RMI connector startup failure introduced by CVE-2026-46495 hardening (#651)
1 parent 2b395d0 commit d4a95c2

2 files changed

Lines changed: 14 additions & 28 deletions

File tree

opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,23 @@ public class RmiConnector
6565
{
6666
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
6767

68-
static final String JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES =
69-
"jmx.remote.rmi.server.credential.types";
70-
7168
/**
7269
* JDK 10+ JMX environment property scoping a JEP 290 deserialization
7370
* filter to the credentials object passed during {@code newClient()}.
7471
* Using the credentials-scoped filter (instead of the connector-wide
7572
* {@code jmx.remote.rmi.server.serial.filter.pattern}) avoids breaking
7673
* legitimate JMX traffic such as MBean invocations and notifications,
7774
* which may legitimately carry non-String types.
75+
* <p>
76+
* Note: this property is mutually exclusive with
77+
* {@code jmx.remote.rmi.server.credential.types}; specifying both makes
78+
* {@code RMIJRMPServerImpl} throw an {@link IllegalArgumentException} and
79+
* prevents the connector from starting. The filter pattern is preferred
80+
* because it additionally constrains array length and nesting depth.
7881
*/
7982
static final String JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN =
8083
"jmx.remote.rmi.server.credentials.filter.pattern";
8184

82-
private static final String[] JMX_CREDENTIAL_TYPES =
83-
{
84-
String.class.getName(),
85-
String[].class.getName()
86-
};
8785

8886
private static final String JMX_CREDENTIAL_SERIAL_FILTER =
8987
"maxdepth=3;maxarray=2;java.lang.String;!*";
@@ -392,11 +390,13 @@ private void startConnectorNoClientCertificate() throws Exception
392390

393391
static void configureJmxDeserializationProtection(Map<String, Object> env)
394392
{
395-
env.put(JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES,
396-
JMX_CREDENTIAL_TYPES.clone());
397393
// Scope the JEP 290 deserialization filter to the credentials object
398394
// only, so legitimate JMX RMI traffic (MBean operations, notifications,
399395
// etc.) is not affected by the restrictive allowlist.
396+
//
397+
// Do NOT also set "jmx.remote.rmi.server.credential.types": the JDK
398+
// rejects an environment that defines both properties, which would
399+
// prevent the RMI connector from starting.
400400
env.put(JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN,
401401
JMX_CREDENTIAL_SERIAL_FILTER);
402402
}

opendj-server-legacy/src/test/java/org/opends/server/protocols/jmx/RmiAuthenticatorTest.java

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,15 @@ public void configuresCredentialDeserializationProtection()
6767
Map<String, Object> env = new HashMap<>();
6868
RmiConnector.configureJmxDeserializationProtection(env);
6969

70-
assertEquals(env.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES),
71-
new String[] { String.class.getName(), String[].class.getName() });
7270
assertEquals(env.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN),
7371
"maxdepth=3;maxarray=2;java.lang.String;!*");
7472
// The connector-wide filter must NOT be set, so legitimate JMX traffic
7573
// (MBean operations, notifications) is not affected by the allowlist.
7674
assertNull(env.get("jmx.remote.rmi.server.serial.filter.pattern"));
77-
}
78-
79-
/** Verifies that each environment receives its own credential type array. */
80-
@Test
81-
public void credentialTypesAreDefensivelyCopied()
82-
{
83-
Map<String, Object> env = new HashMap<>();
84-
RmiConnector.configureJmxDeserializationProtection(env);
85-
String[] credentialTypes =
86-
(String[]) env.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES);
87-
credentialTypes[0] = Date.class.getName();
88-
89-
Map<String, Object> env2 = new HashMap<>();
90-
RmiConnector.configureJmxDeserializationProtection(env2);
91-
assertEquals(((String[]) env2.get(RmiConnector.JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES))[0],
92-
String.class.getName());
75+
// "jmx.remote.rmi.server.credential.types" is mutually exclusive with the
76+
// credentials filter pattern: setting both prevents the connector from
77+
// starting, so only the filter pattern must be configured.
78+
assertNull(env.get("jmx.remote.rmi.server.credential.types"));
9379
}
9480

9581
/** Verifies the configured filter allows only the expected credential payload. */

0 commit comments

Comments
 (0)