This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git
commit fe709de68e80e42edae1a6cea27d6ec0c05ff9d7
Author: Colm O hEigeartaigh <coheigea@apache.org>
AuthorDate: Fri May 25 15:47:48 2018 +0100
CXF-7744 - CXF clients do not fall back to use the javax.net.ssl.trustStore System property
---
.../apache/cxf/configuration/jsse/SSLUtils.java | 93 +++++++++++++++++++++-
.../configuration/jsse/TLSParameterJaxBUtils.java | 13 ++-
.../org/apache/cxf/transport/https/SSLUtils.java | 9 ++-
.../cxf/systest/https/trust/TrustManagerTest.java | 66 +++++++++++++++
.../systest/https/trust/client-trust-config.xml | 32 ++++++++
.../https/trust/client-trust-empty-config.xml | 36 +++++++++
6 files changed, 242 insertions(+), 7 deletions(-)
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java
index 49eb6ed..f889541 100644
--- a/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLUtils.java
@@ -43,9 +43,13 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.SystemPropertyAction;
import org.apache.cxf.configuration.security.FiltersType;
+import org.apache.cxf.resource.ResourceManager;
/**
@@ -96,16 +100,24 @@ public final class SSLUtils {
String location = getKeystore(null, log);
String keyStorePassword = getKeystorePassword(null, log);
String keyPassword = getKeyPassword(null, log);
+ String keyStoreType = getKeystoreType(null, log);
InputStream is = null;
try {
- File file = new File(location);
- if (file.exists()) {
+ if (location != null) {
+ File file = new File(location);
+ if (file.exists()) {
+ is = Files.newInputStream(file.toPath());
+ } else {
+ is = getResourceAsStream(location);
+ }
+ }
+
+ if (is != null) {
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ KeyStore ks = KeyStore.getInstance(keyStoreType != null ? keyStoreType :
KeyStore.getDefaultType());
- is = Files.newInputStream(file.toPath());
ks.load(is, (keyStorePassword != null) ? keyStorePassword.toCharArray() :
null);
kmf.init(ks, (keyPassword != null) ? keyPassword.toCharArray() : null);
defaultManagers = kmf.getKeyManagers();
@@ -127,6 +139,63 @@ public final class SSLUtils {
}
}
+ // We don't cache the default TrustStore managers here (see above) for backwards compatibility
reasons
+ // We also return null rather than an empty array in case this changes using the default
trust managers when
+ // initing the SSLContext
+ public static TrustManager[] getDefaultTrustStoreManagers(Logger log) {
+ String location = getTruststore(null, log);
+ String trustStorePassword = getTruststorePassword(null, log);
+ String trustStoreType = getTrustStoreType(null, log, DEFAULT_TRUST_STORE_TYPE);
+ InputStream is = null;
+
+ try {
+ if (location != null) {
+ File file = new File(location);
+ if (file.exists()) {
+ is = Files.newInputStream(file.toPath());
+ } else {
+ is = getResourceAsStream(location);
+ }
+ }
+
+ if (is != null) {
+ TrustManagerFactory tmf =
+ TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ KeyStore ks = KeyStore.getInstance(trustStoreType);
+
+ ks.load(is, (trustStorePassword != null) ? trustStorePassword.toCharArray()
: null);
+ tmf.init(ks);
+ return tmf.getTrustManagers();
+ } else {
+ log.log(Level.FINER, "No default trust keystore {0}", location);
+ }
+ } catch (Exception e) {
+ log.log(Level.WARNING, "Default trust managers cannot be initialized: " + e.getMessage(),
e);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ log.warning("Keystore stream cannot be closed: " + e.getMessage());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static InputStream getResourceAsStream(String resource) {
+ InputStream is = ClassLoaderUtils.getResourceAsStream(resource, SSLUtils.class);
+ if (is == null) {
+ Bus bus = BusFactory.getThreadDefaultBus(true);
+ ResourceManager rm = bus.getExtension(ResourceManager.class);
+ if (rm != null) {
+ is = rm.getResourceAsStream(resource);
+ }
+ }
+ return is;
+ }
+
public static KeyManager[] loadKeyStore(KeyManagerFactory kmf,
KeyStore ks,
ByteArrayInputStream bin,
@@ -431,6 +500,22 @@ public final class SSLUtils {
return cipherSuites;
}
+ public static String getTruststore(String trustStoreLocation, Logger log) {
+ String logMsg = null;
+ if (trustStoreLocation != null) {
+ logMsg = "TRUST_STORE_SET";
+ } else {
+ trustStoreLocation = SystemPropertyAction.getProperty("javax.net.ssl.trustStore");
+ if (trustStoreLocation != null) {
+ logMsg = "TRUST_STORE_SYSTEM_PROPERTY_SET";
+ } else {
+ logMsg = "TRUST_STORE_NOT_SET";
+ }
+ }
+ LogUtils.log(log, Level.FINE, logMsg, trustStoreLocation);
+ return trustStoreLocation;
+ }
+
public static String getTrustStoreType(String trustStoreType, Logger log) {
return getTrustStoreType(trustStoreType, log, DEFAULT_TRUST_STORE_TYPE);
}
diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
index 58fc21b..cba8742 100644
--- a/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
+++ b/core/src/main/java/org/apache/cxf/configuration/jsse/TLSParameterJaxBUtils.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
@@ -163,10 +164,20 @@ public final class TLSParameterJaxBUtils {
} else if (kst.isSetUrl()) {
keyStore.load(new URL(kst.getUrl()).openStream(), password);
} else {
- String loc = SSLUtils.getKeystore(null, LOG);
+ String loc = null;
+ if (trustStore) {
+ loc = SSLUtils.getTruststore(null, LOG);
+ } else {
+ loc = SSLUtils.getKeystore(null, LOG);
+ }
if (loc != null) {
try (InputStream ins = Files.newInputStream(Paths.get(loc))) {
keyStore.load(ins, password);
+ } catch (NoSuchFileException ex) {
+ // Fall back to load the location as a stream
+ try (InputStream ins = getResourceAsStream(loc)) {
+ keyStore.load(ins, password);
+ }
}
}
}
diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
index 48a4b7c..8db57de 100644
--- a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
+++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java
@@ -26,6 +26,7 @@ import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import org.apache.cxf.common.logging.LogUtils;
@@ -78,8 +79,12 @@ public final class SSLUtils {
}
configureKeyManagersWithCertAlias(parameters, keyManagers);
- ctx.init(keyManagers, parameters.getTrustManagers(),
- parameters.getSecureRandom());
+ TrustManager[] trustManagers = parameters.getTrustManagers();
+ if (trustManagers == null && parameters instanceof TLSClientParameters) {
+ trustManagers = org.apache.cxf.configuration.jsse.SSLUtils.getDefaultTrustStoreManagers(LOG);
+ }
+
+ ctx.init(keyManagers, trustManagers, parameters.getSecureRandom());
return ctx;
}
diff --git a/systests/transports/src/test/java/org/apache/cxf/systest/https/trust/TrustManagerTest.java
b/systests/transports/src/test/java/org/apache/cxf/systest/https/trust/TrustManagerTest.java
index 4cc75fd..f9edba0 100644
--- a/systests/transports/src/test/java/org/apache/cxf/systest/https/trust/TrustManagerTest.java
+++ b/systests/transports/src/test/java/org/apache/cxf/systest/https/trust/TrustManagerTest.java
@@ -150,6 +150,72 @@ public class TrustManagerTest extends AbstractBusClientServerTestBase
{
bus.shutdown(true);
}
+ // Here we're using spring config but getting the truststore from the standard system
properties
+ @org.junit.Test
+ public void testSystemPropertiesWithEmptyTLSClientParametersConfig() throws Exception
{
+ try {
+ System.setProperty("javax.net.ssl.trustStore", "keys/Bethal.jks");
+ System.setProperty("javax.net.ssl.trustStorePassword", "password");
+ System.setProperty("javax.net.ssl.trustStoreType", "JKS");
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = TrustManagerTest.class.getResource("client-trust-config.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);
+
+ assertEquals(port.greetMe("Kitty"), "Hello Kitty");
+
+ ((java.io.Closeable)port).close();
+ bus.shutdown(true);
+ } finally {
+ System.clearProperty("javax.net.ssl.trustStore");
+ System.clearProperty("javax.net.ssl.trustStorePassword");
+ System.clearProperty("javax.net.ssl.trustStoreType");
+ }
+ }
+
+ // Here we're using spring config but getting the truststore from the standard system
properties
+ @org.junit.Test
+ public void testSystemPropertiesWithEmptyKeystoreConfig() throws Exception {
+ try {
+ System.setProperty("javax.net.ssl.trustStore", "keys/Bethal.jks");
+ System.setProperty("javax.net.ssl.trustStorePassword", "password");
+ System.setProperty("javax.net.ssl.trustStoreType", "JKS");
+ SpringBusFactory bf = new SpringBusFactory();
+ URL busFile = TrustManagerTest.class.getResource("client-trust-empty-config.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);
+
+ assertEquals(port.greetMe("Kitty"), "Hello Kitty");
+
+ ((java.io.Closeable)port).close();
+ bus.shutdown(true);
+ } finally {
+ System.clearProperty("javax.net.ssl.trustStore");
+ System.clearProperty("javax.net.ssl.trustStorePassword");
+ System.clearProperty("javax.net.ssl.trustStoreType");
+ }
+ }
+
// Here the Trust Manager checks the server cert. this time we are invoking on the
// service that is configured in code (not by spring)
@org.junit.Test
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/https/trust/client-trust-config.xml
b/systests/transports/src/test/resources/org/apache/cxf/systest/https/trust/client-trust-config.xml
new file mode 100644
index 0000000..5feb0c2
--- /dev/null
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/https/trust/client-trust-config.xml
@@ -0,0 +1,32 @@
+<?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-b
[...]
+
+ <cxf:bus>
+ <cxf:features>
+ <cxf:logging/>
+ </cxf:features>
+ </cxf:bus>
+
+ <http:conduit name="https://localhost:.*">
+ <http:tlsClientParameters disableCNCheck="true" />
+ </http:conduit>
+
+</beans>
diff --git a/systests/transports/src/test/resources/org/apache/cxf/systest/https/trust/client-trust-empty-config.xml
b/systests/transports/src/test/resources/org/apache/cxf/systest/https/trust/client-trust-empty-config.xml
new file mode 100644
index 0000000..1f6eb1f
--- /dev/null
+++ b/systests/transports/src/test/resources/org/apache/cxf/systest/https/trust/client-trust-empty-config.xml
@@ -0,0 +1,36 @@
+<?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-b
[...]
+
+ <cxf:bus>
+ <cxf:features>
+ <cxf:logging/>
+ </cxf:features>
+ </cxf:bus>
+
+ <http:conduit name="https://localhost:.*">
+ <http:tlsClientParameters disableCNCheck="true">
+ <sec:trustManagers>
+ <sec:keyStore/>
+ </sec:trustManagers>
+ </http:tlsClientParameters>
+ </http:conduit>
+
+</beans>
--
To stop receiving notification emails like this one, please contact
coheigea@apache.org.
|