This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/4.1.x-fixes by this push:
     new 43877d6d13 CXF-9194: Support SNI in CXF client with Apache 
HttpComponents HttpClient 4 / HttpClient 5 (#2822)
43877d6d13 is described below

commit 43877d6d1315d4f8c6ce3d82d3f4c985174f7455
Author: Andriy Redko <[email protected]>
AuthorDate: Sat Jan 24 08:13:00 2026 -0500

    CXF-9194: Support SNI in CXF client with Apache HttpComponents HttpClient 4 
/ HttpClient 5 (#2822)
    
    (cherry picked from commit 9b224a7de6cba1c8edb5c5ddc43a1fc9b4755da8)
---
 .../configuration/jsse/TLSClientParameters.java    |  24 +++++
 .../jsse/TLSClientParametersConfig.java            |   3 +
 .../resources/schemas/configuration/security.xsd   |  28 +++++-
 .../http/asyncclient/AsyncHTTPConduit.java         |  10 ++
 .../http/asyncclient/hc5/AsyncHTTPConduit.java     |  10 ++
 .../spring/HttpConduitBeanDefinitionParser.java    |   3 +
 .../cxf/systest/hc5/https/sni/ClientSniServer.java |  47 +++++++++
 .../cxf/systest/hc5/https/sni/ClientSniTest.java   | 104 +++++++++++++++++++
 .../systest/hc5/https/sni/client-sni-server.xml    |  56 +++++++++++
 .../cxf/systest/hc5/https/sni/client-sni.xml       |  44 +++++++++
 .../cxf/systest/https/sni/ClientSniServer.java     |  47 +++++++++
 .../cxf/systest/https/sni/ClientSniTest.java       | 110 +++++++++++++++++++++
 .../cxf/systest/https/sni/client-sni-server.xml    |  56 +++++++++++
 .../apache/cxf/systest/https/sni/client-sni.xml    |  44 +++++++++
 14 files changed, 581 insertions(+), 5 deletions(-)

diff --git 
a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParameters.java 
b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParameters.java
index ad1992823c..c7cebf0665 100644
--- 
a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParameters.java
+++ 
b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParameters.java
@@ -58,6 +58,7 @@ public class TLSClientParameters extends TLSParameterBase {
     private boolean useHttpsURLConnectionDefaultHostnameVerifier;
     private HostnameVerifier hostnameVerifier;
     private SSLContext sslContext;
+    private List<String> serverNames;
 
     /**
      * Set custom HostnameVerifier
@@ -165,6 +166,21 @@ public class TLSClientParameters extends TLSParameterBase {
         this.useHttpsURLConnectionDefaultHostnameVerifier = 
useHttpsURLConnectionDefaultHostnameVerifier;
     }
 
+    /**
+     * Sets SNI server names
+     * @param serverNames SNI server names
+     */
+    public void setServerNames(List<String> serverNames) {
+        this.serverNames = serverNames;
+    }
+
+    /**
+     * Returns SNI server names
+     */
+    public List<String> getServerNames() {
+        return serverNames;
+    }
+
     public int hashCode() {
         int hash = disableCNCheck ? 37 : 17;
         if (sslSocketFactory != null) {
@@ -193,6 +209,9 @@ public class TLSClientParameters extends TLSParameterBase {
             hash = hash(hash, certConstraints.getIssuerDNConstraints());
             hash = hash(hash, certConstraints.getSubjectDNConstraints());
         }
+        if (serverNames != null) {
+            hash = hash(hash, serverNames);
+        }
         return hash;
     }
     private int hash(int i, Object o) {
@@ -253,6 +272,11 @@ public class TLSClientParameters extends TLSParameterBase {
             } else {
                 eq &= that.certConstraints == null;
             }
+            if (serverNames != null) {
+                eq &= equals(serverNames, that.serverNames);
+            } else {
+                eq &= that.serverNames == null;
+            }
             return eq;
         }
         return false;
diff --git 
a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
 
b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
index 781abcc15f..7eb060074f 100644
--- 
a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
+++ 
b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSClientParametersConfig.java
@@ -137,6 +137,9 @@ public final class TLSClientParametersConfig {
         if (iparams != null && iparams.isSetTrustManagersRef() && 
!usingDefaults) {
             ret.setTrustManagers(iparams.getTrustManagersRef());
         }
+        if (iparams != null && iparams.isSetServerNames()) {
+            ret.setServerNames(iparams.getServerNames().getServerName());
+        }
         return ret;
     }
 
diff --git a/core/src/main/resources/schemas/configuration/security.xsd 
b/core/src/main/resources/schemas/configuration/security.xsd
index 73f5e1767f..fbc28a30e7 100644
--- a/core/src/main/resources/schemas/configuration/security.xsd
+++ b/core/src/main/resources/schemas/configuration/security.xsd
@@ -436,7 +436,18 @@
         <xs:enumeration value="ALL"/>
       </xs:restriction>
     </xs:simpleType>
-    
+
+    <xs:complexType name="ServerNames">
+      <xs:annotation>
+        <xs:documentation>
+        This structure holds the list of SNI server names.
+        </xs:documentation>
+      </xs:annotation>
+      <xs:sequence>
+        <xs:element name="serverName" type="xs:string" minOccurs="0" 
maxOccurs="unbounded"/>
+      </xs:sequence>
+    </xs:complexType>
+
     <!-- Although there are common elements of TLSClientParametersType
       ** and TLSServerParametersType they are listed separate so we
       ** can use the xs:all element.
@@ -460,7 +471,7 @@
            <xs:element name="cipherSuites" type="tns:CipherSuites" 
minOccurs="0">
               <xs:annotation>
                 <xs:documentation>
-                This element contains the the CipherSuites that will be 
supported.
+                This element contains the CipherSuites that will be supported.
                 </xs:documentation>
               </xs:annotation>
            </xs:element>
@@ -494,6 +505,13 @@
                 </xs:documentation>
               </xs:annotation>
            </xs:element>
+           <xs:element name="serverNames" type="tns:ServerNames" minOccurs="0">
+              <xs:annotation>
+                <xs:documentation>
+                This element contains the SNI server names.
+                </xs:documentation>
+              </xs:annotation>
+           </xs:element>
         </xs:all>
            <xs:attribute name="useHttpsURLConnectionDefaultSslSocketFactory" 
type="pt:ParameterizedBoolean" default="false">
              <xs:annotation>
@@ -577,7 +595,7 @@
            <xs:element name="cipherSuites" type="tns:CipherSuites" 
minOccurs="0">
               <xs:annotation>
                 <xs:documentation>
-                This element contains the the CipherSuites that will be 
supported.
+                This element contains the CipherSuites that will be supported.
                 </xs:documentation>
               </xs:annotation>
            </xs:element>
@@ -592,14 +610,14 @@
            <xs:element name="excludeProtocols" type="tns:ExcludeProtocols" 
minOccurs="0">
               <xs:annotation>
                 <xs:documentation>
-                This element contains the the Protocols that will be excluded
+                This element contains the Protocols that will be excluded
                 </xs:documentation>
               </xs:annotation>
            </xs:element>
            <xs:element name="includeProtocols" type="tns:IncludeProtocols" 
minOccurs="0">
               <xs:annotation>
                 <xs:documentation>
-                This element contains the the Protocols that will be included
+                This element contains the Protocols that will be included
                 </xs:documentation>
               </xs:annotation>
            </xs:element>
diff --git 
a/rt/transports/http-hc/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java
 
b/rt/transports/http-hc/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java
index edf8b8cfb9..f7e4867d7e 100755
--- 
a/rt/transports/http-hc/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java
+++ 
b/rt/transports/http-hc/src/main/java/org/apache/cxf/transport/http/asyncclient/AsyncHTTPConduit.java
@@ -39,12 +39,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Future;
 import java.util.logging.Level;
+import java.util.stream.Collectors;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.KeyManager;
+import javax.net.ssl.SNIHostName;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 
@@ -977,6 +980,13 @@ public class AsyncHTTPConduit extends 
HttpClientHTTPConduit {
         if (p != null) {
             sslengine.setEnabledProtocols(p);
         }
+        
+        final List<String> serverNames = tlsClientParameters.getServerNames();
+        if (serverNames != null && !serverNames.isEmpty()) {
+            final SSLParameters params = new SSLParameters();
+            
params.setServerNames(serverNames.stream().map(SNIHostName::new).collect(Collectors.toList()));
+            sslengine.setSSLParameters(params);
+        }
     }
 
     private String[] findProtocols(String p, String[] options) {
diff --git 
a/rt/transports/http-hc5/src/main/java/org/apache/cxf/transport/http/asyncclient/hc5/AsyncHTTPConduit.java
 
b/rt/transports/http-hc5/src/main/java/org/apache/cxf/transport/http/asyncclient/hc5/AsyncHTTPConduit.java
index c990ecf719..92a68a2956 100644
--- 
a/rt/transports/http-hc5/src/main/java/org/apache/cxf/transport/http/asyncclient/hc5/AsyncHTTPConduit.java
+++ 
b/rt/transports/http-hc5/src/main/java/org/apache/cxf/transport/http/asyncclient/hc5/AsyncHTTPConduit.java
@@ -39,11 +39,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Future;
 import java.util.logging.Level;
+import java.util.stream.Collectors;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.KeyManager;
+import javax.net.ssl.SNIHostName;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;
 
@@ -982,6 +985,13 @@ public class AsyncHTTPConduit extends 
HttpClientHTTPConduit {
         if (p != null) {
             sslengine.setEnabledProtocols(p);
         }
+
+        final List<String> serverNames = tlsClientParameters.getServerNames();
+        if (serverNames != null && !serverNames.isEmpty()) {
+            final SSLParameters params = new SSLParameters();
+            
params.setServerNames(serverNames.stream().map(SNIHostName::new).collect(Collectors.toList()));
+            sslengine.setSSLParameters(params);
+        }
     }
     
     @Override
diff --git 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java
 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java
index f751847826..994b29a343 100644
--- 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java
+++ 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java
@@ -36,6 +36,7 @@ import org.apache.cxf.configuration.security.FiltersType;
 import org.apache.cxf.configuration.security.KeyManagersType;
 import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
 import org.apache.cxf.configuration.security.SecureRandomParameters;
+import org.apache.cxf.configuration.security.ServerNames;
 import org.apache.cxf.configuration.security.TrustManagersType;
 import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
 import org.apache.cxf.transport.http.HTTPConduit;
@@ -171,6 +172,8 @@ public class HttpConduitBeanDefinitionParser
                                          CertificateConstraintsType.class);
             } else if ("certAlias".equals(ename)) {
                 paramsbean.addPropertyValue(ename, n.getTextContent());
+            } else if ("serverNames".equals(ename)) {
+                mapElementToJaxbProperty((Element)n, paramsbean, ename, 
ServerNames.class);
             }
             n = n.getNextSibling();
         }
diff --git 
a/systests/transport-hc5/src/test/java/org/apache/cxf/systest/hc5/https/sni/ClientSniServer.java
 
b/systests/transport-hc5/src/test/java/org/apache/cxf/systest/hc5/https/sni/ClientSniServer.java
new file mode 100644
index 0000000000..901629fae9
--- /dev/null
+++ 
b/systests/transport-hc5/src/test/java/org/apache/cxf/systest/hc5/https/sni/ClientSniServer.java
@@ -0,0 +1,47 @@
+/**
+ * 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.cxf.systest.hc5.https.sni;
+
+import java.net.URL;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class ClientSniServer extends AbstractBusTestServerBase {
+
+    public ClientSniServer() {
+
+    }
+
+    protected void run()  {
+        URL busFile = 
ClientSniServer.class.getResource("client-sni-server.xml");
+        Bus busLocal = new SpringBusFactory().createBus(busFile);
+        BusFactory.setDefaultBus(busLocal);
+        setBus(busLocal);
+
+        try {
+            new ClientSniServer();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git 
a/systests/transport-hc5/src/test/java/org/apache/cxf/systest/hc5/https/sni/ClientSniTest.java
 
b/systests/transport-hc5/src/test/java/org/apache/cxf/systest/hc5/https/sni/ClientSniTest.java
new file mode 100644
index 0000000000..8a390bd46c
--- /dev/null
+++ 
b/systests/transport-hc5/src/test/java/org/apache/cxf/systest/hc5/https/sni/ClientSniTest.java
@@ -0,0 +1,104 @@
+/**
+ * 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.cxf.systest.hc5.https.sni;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+
+import jakarta.xml.ws.BindingProvider;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.hello_world.Greeter;
+import org.apache.hello_world.services.SOAPService;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * A set of tests for TLS SNI
+ */
+@RunWith(value = org.junit.runners.Parameterized.class)
+public class ClientSniTest extends AbstractBusClientServerTestBase {
+    static final String PORT = allocatePort(ClientSniServer.class);
+
+    final Boolean async;
+
+    public ClientSniTest(Boolean async) {
+        this.async = async;
+    }
+    
+    @Parameters(name = "{0}")
+    public static Collection<Boolean> data() {
+        return Arrays.asList(new Boolean[] {Boolean.FALSE, Boolean.TRUE});
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue(
+            "Server failed to launch",
+            // run the server in the same process
+            // set this to false to fork
+            launchServer(ClientSniServer.class, true)
+        );
+    }
+
+    @AfterClass
+    public static void cleanup() throws Exception {
+        stopAllServers();
+    }
+
+    // Server directly trusts the client cert
+    @org.junit.Test
+    public void testSniServerNames() throws Exception {
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = ClientSniTest.class.getResource("client-sni.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        BusFactory.setDefaultBus(bus);
+        BusFactory.setThreadDefaultBus(bus);
+
+        URL url = SOAPService.WSDL_LOCATION;
+        SOAPService service = new SOAPService(url, SOAPService.SERVICE);
+        assertNotNull("Service is null", service);
+        final Greeter port = service.getHttpsPort();
+        assertNotNull("Port is null", port);
+
+        updateAddressPort(port, PORT);
+
+        // Enable Async
+        if (async) {
+            
((BindingProvider)port).getRequestContext().put("use.async.http.conduit", true);
+        }
+
+        assertEquals(port.greetMe("Kitty"), "Hello Kitty");
+
+        ((java.io.Closeable)port).close();
+        bus.shutdown(true);
+    }
+}
diff --git 
a/systests/transport-hc5/src/test/resources/org/apache/cxf/systest/hc5/https/sni/client-sni-server.xml
 
b/systests/transport-hc5/src/test/resources/org/apache/cxf/systest/hc5/https/sni/client-sni-server.xml
new file mode 100644
index 0000000000..378aa31a7f
--- /dev/null
+++ 
b/systests/transport-hc5/src/test/resources/org/apache/cxf/systest/hc5/https/sni/client-sni-server.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:jaxws="http://cxf.apache.org/jaxws";
+    xmlns:http="http://cxf.apache.org/transports/http/configuration";
+    xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration";
+    xmlns:sec="http://cxf.apache.org/configuration/security";
+    xmlns:cxf="http://cxf.apache.org/core";
+    xmlns:p="http://cxf.apache.org/policy";
+    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd 
http://cxf.apache.org/policy http://cxf.apache.org/schemas/policy.xsd 
http://cxf.apache.org/transports/http/configuration 
http://cxf.apache.org/schemas/configuration/http-conf.xsd 
http://cxf.apache.org/transports/http-jetty/confi [...]
+    <bean 
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <bean class="org.apache.cxf.ext.logging.LoggingFeature"/>
+        </cxf:features>
+    </cxf:bus>
+   
+    <httpj:engine-factory id="tls-settings">
+        <httpj:engine port="${testutil.ports.ClientSniServer}">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="jks" password="password" 
resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore type="jks" password="password" 
resource="keys/Truststore.jks"/>
+                </sec:trustManagers>
+            </httpj:tlsServerParameters>
+        </httpj:engine>
+    </httpj:engine-factory>
+    
+    <jaxws:endpoint xmlns:e="http://apache.org/hello_world/services"; 
+                     xmlns:s="http://apache.org/hello_world/services"; 
+                     id="DirectTrustServer" 
+                     implementor="org.apache.cxf.systest.hc5.GreeterImpl"
+                     
address="https://localhost:${testutil.ports.ClientSniServer}/SoapContext/HttpsPort";
 
+                     serviceName="s:SOAPService" 
+                     endpointName="e:HttpsPort" depends-on="tls-settings"/>
+</beans>
\ No newline at end of file
diff --git 
a/systests/transport-hc5/src/test/resources/org/apache/cxf/systest/hc5/https/sni/client-sni.xml
 
b/systests/transport-hc5/src/test/resources/org/apache/cxf/systest/hc5/https/sni/client-sni.xml
new file mode 100644
index 0000000000..cca43394e7
--- /dev/null
+++ 
b/systests/transport-hc5/src/test/resources/org/apache/cxf/systest/hc5/https/sni/client-sni.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:http="http://cxf.apache.org/transports/http/configuration";
+    xmlns:jaxws="http://cxf.apache.org/jaxws";
+    xmlns:cxf="http://cxf.apache.org/core";
+    xmlns:p="http://cxf.apache.org/policy";
+    xmlns:sec="http://cxf.apache.org/configuration/security";
+    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 
http://cxf.apache.org/transports/http/configuration 
http://cxf.apache.org/schemas/configuration/http-conf.xsd 
http://cxf.apache.org/configuration/security 
http://cxf.apache.org/schemas/configuration/security.xsd 
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd 
http://cxf.apache [...]
+    
+    <cxf:bus>
+        <cxf:features>
+            <bean class="org.apache.cxf.ext.logging.LoggingFeature"/>
+        </cxf:features>
+    </cxf:bus>
+    <http:conduit name="https://localhost:.*";>
+        <http:tlsClientParameters disableCNCheck="true">
+            <sec:trustManagers>
+                <sec:keyStore type="jks" password="password" 
resource="keys/Truststore.jks"/>
+            </sec:trustManagers>
+            <sec:serverNames>
+                <sec:serverName>bethal</sec:serverName>
+            </sec:serverNames>
+        </http:tlsClientParameters>
+    </http:conduit>
+</beans>
\ No newline at end of file
diff --git 
a/systests/transports/src/test/java/org/apache/cxf/systest/https/sni/ClientSniServer.java
 
b/systests/transports/src/test/java/org/apache/cxf/systest/https/sni/ClientSniServer.java
new file mode 100644
index 0000000000..b453e225fc
--- /dev/null
+++ 
b/systests/transports/src/test/java/org/apache/cxf/systest/https/sni/ClientSniServer.java
@@ -0,0 +1,47 @@
+/**
+ * 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.cxf.systest.https.sni;
+
+import java.net.URL;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class ClientSniServer extends AbstractBusTestServerBase {
+
+    public ClientSniServer() {
+
+    }
+
+    protected void run()  {
+        URL busFile = 
ClientSniServer.class.getResource("client-sni-server.xml");
+        Bus busLocal = new SpringBusFactory().createBus(busFile);
+        BusFactory.setDefaultBus(busLocal);
+        setBus(busLocal);
+
+        try {
+            new ClientSniServer();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git 
a/systests/transports/src/test/java/org/apache/cxf/systest/https/sni/ClientSniTest.java
 
b/systests/transports/src/test/java/org/apache/cxf/systest/https/sni/ClientSniTest.java
new file mode 100644
index 0000000000..f6d1cfb180
--- /dev/null
+++ 
b/systests/transports/src/test/java/org/apache/cxf/systest/https/sni/ClientSniTest.java
@@ -0,0 +1,110 @@
+/**
+ * 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.cxf.systest.https.sni;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+
+import jakarta.xml.ws.BindingProvider;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.hello_world.Greeter;
+import org.apache.hello_world.services.SOAPService;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * A set of tests for TLS SNI
+ */
+@RunWith(value = org.junit.runners.Parameterized.class)
+public class ClientSniTest extends AbstractBusClientServerTestBase {
+    static final String PORT = allocatePort(ClientSniServer.class);
+
+    final String clientKey;
+    final Object clientVal;
+
+    public ClientSniTest(String ck, Object value) {
+        this.clientKey = ck;
+        this.clientVal = value;
+    }
+    
+    @Parameters(name = "{0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {
+            {"force.urlconnection.http.conduit", true},
+            {"use.async.http.conduit", true},
+            {"defaultConduit", true},
+            {"org.apache.cxf.transport.http.forceVersion", "1.1"},
+            {"org.apache.cxf.transport.http.forceVersion", "2"}
+        });
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue(
+            "Server failed to launch",
+            // run the server in the same process
+            // set this to false to fork
+            launchServer(ClientSniServer.class, true)
+        );
+    }
+
+    @AfterClass
+    public static void cleanup() throws Exception {
+        stopAllServers();
+    }
+
+    // Server directly trusts the client cert
+    @org.junit.Test
+    public void testSniServerNames() throws Exception {
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = ClientSniTest.class.getResource("client-sni.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        BusFactory.setDefaultBus(bus);
+        BusFactory.setThreadDefaultBus(bus);
+
+        URL url = SOAPService.WSDL_LOCATION;
+        SOAPService service = new SOAPService(url, SOAPService.SERVICE);
+        assertNotNull("Service is null", service);
+        final Greeter port = service.getHttpsPort();
+        assertNotNull("Port is null", port);
+
+        updateAddressPort(port, PORT);
+
+        ((BindingProvider)port).getRequestContext().put(clientKey, clientVal);
+
+        
+        assertEquals(port.greetMe("Kitty"), "Hello Kitty");
+
+        ((java.io.Closeable)port).close();
+        bus.shutdown(true);
+    }
+}
diff --git 
a/systests/transports/src/test/resources/org/apache/cxf/systest/https/sni/client-sni-server.xml
 
b/systests/transports/src/test/resources/org/apache/cxf/systest/https/sni/client-sni-server.xml
new file mode 100644
index 0000000000..da1ed372fb
--- /dev/null
+++ 
b/systests/transports/src/test/resources/org/apache/cxf/systest/https/sni/client-sni-server.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:jaxws="http://cxf.apache.org/jaxws";
+    xmlns:http="http://cxf.apache.org/transports/http/configuration";
+    xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration";
+    xmlns:sec="http://cxf.apache.org/configuration/security";
+    xmlns:cxf="http://cxf.apache.org/core";
+    xmlns:p="http://cxf.apache.org/policy";
+    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd 
http://cxf.apache.org/policy http://cxf.apache.org/schemas/policy.xsd 
http://cxf.apache.org/transports/http/configuration 
http://cxf.apache.org/schemas/configuration/http-conf.xsd 
http://cxf.apache.org/transports/http-jetty/confi [...]
+    <bean 
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <bean class="org.apache.cxf.ext.logging.LoggingFeature"/>
+        </cxf:features>
+    </cxf:bus>
+   
+    <httpj:engine-factory id="tls-settings">
+        <httpj:engine port="${testutil.ports.ClientSniServer}">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="jks" password="password" 
resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore type="jks" password="password" 
resource="keys/Truststore.jks"/>
+                </sec:trustManagers>
+            </httpj:tlsServerParameters>
+        </httpj:engine>
+    </httpj:engine-factory>
+    
+    <jaxws:endpoint xmlns:e="http://apache.org/hello_world/services"; 
+                     xmlns:s="http://apache.org/hello_world/services"; 
+                     id="DirectTrustServer" 
+                     implementor="org.apache.cxf.systest.http.GreeterImpl" 
+                     
address="https://localhost:${testutil.ports.ClientSniServer}/SoapContext/HttpsPort";
 
+                     serviceName="s:SOAPService" 
+                     endpointName="e:HttpsPort" depends-on="tls-settings"/>
+</beans>
\ No newline at end of file
diff --git 
a/systests/transports/src/test/resources/org/apache/cxf/systest/https/sni/client-sni.xml
 
b/systests/transports/src/test/resources/org/apache/cxf/systest/https/sni/client-sni.xml
new file mode 100644
index 0000000000..cca43394e7
--- /dev/null
+++ 
b/systests/transports/src/test/resources/org/apache/cxf/systest/https/sni/client-sni.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xmlns:http="http://cxf.apache.org/transports/http/configuration";
+    xmlns:jaxws="http://cxf.apache.org/jaxws";
+    xmlns:cxf="http://cxf.apache.org/core";
+    xmlns:p="http://cxf.apache.org/policy";
+    xmlns:sec="http://cxf.apache.org/configuration/security";
+    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 
http://cxf.apache.org/transports/http/configuration 
http://cxf.apache.org/schemas/configuration/http-conf.xsd 
http://cxf.apache.org/configuration/security 
http://cxf.apache.org/schemas/configuration/security.xsd 
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd 
http://cxf.apache [...]
+    
+    <cxf:bus>
+        <cxf:features>
+            <bean class="org.apache.cxf.ext.logging.LoggingFeature"/>
+        </cxf:features>
+    </cxf:bus>
+    <http:conduit name="https://localhost:.*";>
+        <http:tlsClientParameters disableCNCheck="true">
+            <sec:trustManagers>
+                <sec:keyStore type="jks" password="password" 
resource="keys/Truststore.jks"/>
+            </sec:trustManagers>
+            <sec:serverNames>
+                <sec:serverName>bethal</sec:serverName>
+            </sec:serverNames>
+        </http:tlsClientParameters>
+    </http:conduit>
+</beans>
\ No newline at end of file


Reply via email to