This is an automated email from the ASF dual-hosted git repository. rzo1 pushed a commit to branch tomee-10.x in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 54223860e44d1f106d65cb7b62301c04f93be25e Author: Markus Jung <[email protected]> AuthorDate: Sun Aug 23 21:44:48 2026 +0200 verify peer hostname on ejbds client connections (cherry picked from commit 4784e54541a009cb16da6cd2591245aa41af820f) --- .../openejb/client/SocketConnectionFactory.java | 25 ++++++++-- .../client/SocketConnectionFactoryTest.java | 56 ++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java b/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java index 928870f704..0309bd6480 100644 --- a/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java +++ b/server/openejb-client/src/main/java/org/apache/openejb/client/SocketConnectionFactory.java @@ -20,6 +20,7 @@ import org.apache.openejb.client.event.ConnectionOpened; import org.apache.openejb.client.event.ConnectionPoolCreated; import org.apache.openejb.client.event.ConnectionPoolTimeout; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import java.io.BufferedInputStream; @@ -54,6 +55,7 @@ public class SocketConnectionFactory implements ConnectionFactory { private static final String PROPERTY_POOL_SIZE2 = "openejb.client.connectionpool.size"; public static final String PROPERTY_KEEPALIVE = "openejb.client.keepalive"; public static final String ENABLED_CIPHER_SUITES = "openejb.client.enabledCipherSuites"; + public static final String DISABLE_ENDPOINT_IDENTIFICATION = "openejb.client.disableEndpointIdentification"; private static final Map<URI, Pool> connections = new ConcurrentHashMap<>(); private int size = 5; @@ -283,22 +285,35 @@ public class SocketConnectionFactory implements ConnectionFactory { try { final String scheme = uri.getScheme(); if (scheme.equalsIgnoreCase("ejbds") || scheme.equalsIgnoreCase("zejbds")) { - final SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); + // connect a plain socket first so the configured connect timeout applies, + // then layer TLS over it against the host taken from the location + final Socket plain = new Socket(); + this.socket = plain; + plain.setTcpNoDelay(true); + plain.setSoLinger(true, SocketConnectionFactory.this.timeoutLinger); + plain.connect(address, SocketConnectionFactory.this.timeoutConnect); + + final SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()) + .createSocket(plain, uri.getHost(), uri.getPort(), true); this.socket = sslSocket; sslSocket.setEnabledCipherSuites(SocketConnectionFactory.this.enabledCipherSuites); + if (!Boolean.getBoolean(DISABLE_ENDPOINT_IDENTIFICATION)) { + final SSLParameters sslParameters = sslSocket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslSocket.setSSLParameters(sslParameters); + } } else { this.socket = new Socket(); + this.socket.setTcpNoDelay(true); + this.socket.setSoLinger(true, SocketConnectionFactory.this.timeoutLinger); + this.socket.connect(address, SocketConnectionFactory.this.timeoutConnect); } if (scheme.startsWith("z")) { this.gzip = true; } - this.socket.setTcpNoDelay(true); - this.socket.setSoLinger(true, SocketConnectionFactory.this.timeoutLinger); - this.socket.connect(address, SocketConnectionFactory.this.timeoutConnect); - //Four hours default this.socket.setSoTimeout(SocketConnectionFactory.this.timeoutRead); diff --git a/server/openejb-client/src/test/java/org/apache/openejb/client/SocketConnectionFactoryTest.java b/server/openejb-client/src/test/java/org/apache/openejb/client/SocketConnectionFactoryTest.java new file mode 100644 index 0000000000..d95c2d6792 --- /dev/null +++ b/server/openejb-client/src/test/java/org/apache/openejb/client/SocketConnectionFactoryTest.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.client; + +import org.junit.Test; + +import javax.net.ssl.SSLSocket; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; + +import static org.junit.Assert.assertEquals; + +public class SocketConnectionFactoryTest { + + @Test + public void ejbdsSocketVerifiesThePeerHostname() throws Exception { + // a plain server socket is enough: the TLS handshake only starts on first read/write + final ServerSocket server = new ServerSocket(0, 1, InetAddress.getByName("localhost")); + System.setProperty(SocketConnectionFactory.ENABLED_CIPHER_SUITES, "TLS_AES_128_GCM_SHA256"); + try { + final SocketConnectionFactory factory = new SocketConnectionFactory(); + final URI uri = new URI("ejbds://localhost:" + server.getLocalPort()); + final SocketConnectionFactory.SocketConnection connection = factory.new SocketConnection(uri, null); + connection.open(uri); + + final Field socketField = SocketConnectionFactory.SocketConnection.class.getDeclaredField("socket"); + socketField.setAccessible(true); + final Socket socket = (Socket) socketField.get(connection); + try { + assertEquals("HTTPS", ((SSLSocket) socket).getSSLParameters().getEndpointIdentificationAlgorithm()); + } finally { + socket.close(); + } + } finally { + System.clearProperty(SocketConnectionFactory.ENABLED_CIPHER_SUITES); + server.close(); + } + } +}
