From commits-return-49247-archive-asf-public=cust-asf.ponee.io@cxf.apache.org Fri May 25 18:08:43 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 7AC6718067A for ; Fri, 25 May 2018 18:08:42 +0200 (CEST) Received: (qmail 88628 invoked by uid 500); 25 May 2018 16:08:41 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 88485 invoked by uid 99); 25 May 2018 16:08:39 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 25 May 2018 16:08:39 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id CDD6E82B21; Fri, 25 May 2018 16:08:38 +0000 (UTC) Date: Fri, 25 May 2018 16:08:38 +0000 To: "commits@cxf.apache.org" Subject: [cxf] 01/02: CXF-7744 - CXF clients do not fall back to use the javax.net.ssl.trustStore System property MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit From: coheigea@apache.org In-Reply-To: <152726451779.26830.17690768998199723557@gitbox.apache.org> References: <152726451779.26830.17690768998199723557@gitbox.apache.org> X-Git-Host: gitbox.apache.org X-Git-Repo: cxf X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Rev: fe709de68e80e42edae1a6cea27d6ec0c05ff9d7 X-Git-NotificationType: diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated Message-Id: <20180525160838.CDD6E82B21@gitbox.apache.org> 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 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 @@ + + + + + + + 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 @@ + + + + + + + + + + + -- To stop receiving notification emails like this one, please contact coheigea@apache.org.