diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index c8a194331..9fbebdda0 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -3,15 +3,14 @@ Changes since 4.3 ALPHA1 * [HTTPCLIENT-1317] InetAddressUtils should handle IPv6 Addresses with Embedded IPv4 Addresses Contributed Sebastian Bazley . +* [HTTPCLIENT-1320] Leverage javax.net.ssl.SSLSocketFactory#getDefault() to initialize SSL context + based on system defaults instead of using an internal custom routine. + Contributed by Abe Backus and Oleg Kalnichevski + * [HTTPCLIENT-1315] NTLM support did not work properly when the target (as returned in the Type 2 message) differed from the domain as supplied by the user. Contributed by Karl Wright -* [HTTPCLIENT-1320] SSLSocketFactory#createSystemSSLContext causes UnrecoverableKeyException - 'Password verification failed' when a truststore is specified with 'javax.net.ssl.trustStore' - system property is used without a password. - Contributed by Abe Backus - * [HTTPCLIENT-1316] Certificate verification rejects IPv6 addresses which are not String-equal. Contributed Sebastian Bazley . diff --git a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java index 01e69e6ff..d05d9db1f 100644 --- a/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java +++ b/httpclient/src/examples/org/apache/http/examples/client/ClientConfiguration.java @@ -61,6 +61,7 @@ import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainSocketFactory; import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier; +import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.impl.DefaultHttpResponseFactory; @@ -140,7 +141,7 @@ public class ClientConfiguration { // SSL context for secure connections can be created either based on // system or application specific properties. - SSLContext sslcontext = SSLSocketFactory.createSystemSSLContext(); + SSLContext sslcontext = SSLContexts.createSystemDefault(); // Use custom hostname verifier to customize SSL hostname verification. X509HostnameVerifier hostnameVerifier = new BrowserCompatHostnameVerifier(); diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContexts.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContexts.java new file mode 100644 index 000000000..851e90975 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContexts.java @@ -0,0 +1,81 @@ +/* + * ==================================================================== + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.conn.ssl; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.SSLContext; + +import org.apache.http.annotation.Immutable; + +/** + * {@link SSLContext} factory methods. + * + * @since 4.3 + */ +@Immutable +public class SSLContexts { + + /** + * Creates default factory based on the standard JSSE trust material + * (cacerts file in the security properties directory). System properties + * are not taken into consideration. + * + * @return the default SSL socket factory + */ + public static final SSLContext createDefault() throws SSLInitializationException { + try { + final SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(null, null, null); + return sslcontext; + } catch (final NoSuchAlgorithmException ex) { + throw new SSLInitializationException(ex.getMessage(), ex); + } catch (final KeyManagementException ex) { + throw new SSLInitializationException(ex.getMessage(), ex); + } + } + + /** + * Creates default SSL context based on system properties. This method obtains + * default SSL context by calling SSLContext.getInstance("Default"). + * Please note that Default algorithm is supported as of Java 6. + * This method will fall back onto {@link #createDefault()} when + * Default algorithm is not available. + * + * @return default system SSL context + */ + public static final SSLContext createSystemDefault() throws SSLInitializationException { + try { + return SSLContext.getInstance("Default"); + } catch (final NoSuchAlgorithmException ex) { + return createDefault(); + } + } + +} diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java index b146db047..b9fba0dad 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -27,8 +27,6 @@ package org.apache.http.conn.ssl; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -39,10 +37,8 @@ import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; @@ -158,45 +154,32 @@ public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeL public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER = new StrictHostnameVerifier(); - private final static char[] EMPTY_PASSWORD = "".toCharArray(); - /** - * Gets the default factory, which uses the default JSSE settings for initializing - * the SSL context. + * Obtains default SSL socket factory with an SSL context based on the standard JSSE + * trust material (cacerts file in the security properties directory). + * System properties are not taken into consideration. * - * @return the default SSL socket factory + * @return default SSL socket factory */ public static SSLSocketFactory getSocketFactory() throws SSLInitializationException { - return new SSLSocketFactory(createDefaultSSLContext()); + return new SSLSocketFactory( + SSLContexts.createDefault(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); } /** - * Gets the default factory, which uses system properties for initializing the SSL context + * Obtains default SSL socket factory with an SSL context based on system properties * as described in * * "JavaTM Secure Socket Extension (JSSE) Reference Guide for the JavaTM 2 Platform * Standard Edition 5 - *

- * The following system properties are taken into account by this method: - *

    - *
  • ssl.TrustManagerFactory.algorithm
  • - *
  • javax.net.ssl.trustStoreType
  • - *
  • javax.net.ssl.trustStore
  • - *
  • javax.net.ssl.trustStoreProvider
  • - *
  • javax.net.ssl.trustStorePassword
  • - *
  • java.home
  • - *
  • ssl.KeyManagerFactory.algorithm
  • - *
  • javax.net.ssl.keyStoreType
  • - *
  • javax.net.ssl.keyStore
  • - *
  • javax.net.ssl.keyStoreProvider
  • - *
  • javax.net.ssl.keyStorePassword
  • - *
- *

* - * @return the system SSL socket factory + * @return default system SSL socket factory */ public static SSLSocketFactory getSystemSocketFactory() throws SSLInitializationException { - return new SSLSocketFactory(createSystemSSLContext()); + return new SSLSocketFactory( + (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); } private final javax.net.ssl.SSLSocketFactory socketfactory; @@ -238,138 +221,6 @@ public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeL return sslcontext; } - private static SSLContext createSystemSSLContext( - String algorithm, - final SecureRandom random) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, - KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException { - if (algorithm == null) { - algorithm = TLS; - } - TrustManagerFactory tmfactory = null; - - String trustAlgorithm = System.getProperty("ssl.TrustManagerFactory.algorithm"); - if (trustAlgorithm == null) { - trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); - } - String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType"); - if (trustStoreType == null) { - trustStoreType = KeyStore.getDefaultType(); - } - if ("none".equalsIgnoreCase(trustStoreType)) { - tmfactory = TrustManagerFactory.getInstance(trustAlgorithm); - } else { - File trustStoreFile = null; - final String s = System.getProperty("javax.net.ssl.trustStore"); - if (s != null) { - trustStoreFile = new File(s); - tmfactory = TrustManagerFactory.getInstance(trustAlgorithm); - final String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider"); - KeyStore trustStore; - if (trustStoreProvider != null) { - trustStore = KeyStore.getInstance(trustStoreType, trustStoreProvider); - } else { - trustStore = KeyStore.getInstance(trustStoreType); - } - final String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); - final FileInputStream instream = new FileInputStream(trustStoreFile); - try { - trustStore.load(instream, trustStorePassword != null ? - trustStorePassword.toCharArray() : null); - } finally { - instream.close(); - } - tmfactory.init(trustStore); - } else { - final File javaHome = new File(System.getProperty("java.home")); - File file = new File(javaHome, "lib/security/jssecacerts"); - if (!file.exists()) { - file = new File(javaHome, "lib/security/cacerts"); - trustStoreFile = file; - } else { - trustStoreFile = file; - } - tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - final KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - final String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); - final FileInputStream instream = new FileInputStream(trustStoreFile); - try { - trustStore.load(instream, trustStorePassword != null ? trustStorePassword.toCharArray() : null); - } finally { - instream.close(); - } - tmfactory.init(trustStore); - } - } - - KeyManagerFactory kmfactory = null; - String keyAlgorithm = System.getProperty("ssl.KeyManagerFactory.algorithm"); - if (keyAlgorithm == null) { - keyAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); - } - String keyStoreType = System.getProperty("javax.net.ssl.keyStoreType"); - if (keyStoreType == null) { - keyStoreType = KeyStore.getDefaultType(); - } - if ("none".equalsIgnoreCase(keyStoreType)) { - kmfactory = KeyManagerFactory.getInstance(keyAlgorithm); - } else { - File keyStoreFile = null; - final String s = System.getProperty("javax.net.ssl.keyStore"); - if (s != null) { - keyStoreFile = new File(s); - } - if (keyStoreFile != null) { - kmfactory = KeyManagerFactory.getInstance(keyAlgorithm); - final String keyStoreProvider = System.getProperty("javax.net.ssl.keyStoreProvider"); - KeyStore keyStore; - if (keyStoreProvider != null) { - keyStore = KeyStore.getInstance(keyStoreType, keyStoreProvider); - } else { - keyStore = KeyStore.getInstance(keyStoreType); - } - final String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword"); - final FileInputStream instream = new FileInputStream(keyStoreFile); - try { - keyStore.load(instream, keyStorePassword != null ? - keyStorePassword.toCharArray() : EMPTY_PASSWORD); - } finally { - instream.close(); - } - kmfactory.init(keyStore, keyStorePassword != null ? - keyStorePassword.toCharArray() : EMPTY_PASSWORD); - } - } - - final SSLContext sslcontext = SSLContext.getInstance(algorithm); - sslcontext.init( - kmfactory != null ? kmfactory.getKeyManagers() : null, - tmfactory != null ? tmfactory.getTrustManagers() : null, - random); - return sslcontext; - } - - /** - * @since 4.3 - */ - public static SSLContext createDefaultSSLContext() throws SSLInitializationException { - try { - return createSSLContext(TLS, null, null, null, null, null); - } catch (final Exception ex) { - throw new SSLInitializationException("Failure initializing default SSL context", ex); - } - } - - /** - * @since 4.3 - */ - public static SSLContext createSystemSSLContext() throws SSLInitializationException { - try { - return createSystemSSLContext(TLS, null); - } catch (final Exception ex) { - throw new SSLInitializationException("Failure initializing default system SSL context", ex); - } - } - /** * @deprecated (4.1) Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore, * SecureRandom, X509HostnameVerifier)}