diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index f1a2e3233..aa3ab6805 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,6 +1,10 @@ Changes since release 4.3 BETA1 ------------------- +* [HTTPCLIENT-1343] SSLSocketFactory optional parameters for supported SSL protocols and cipher + suites. + Contributed by Oleg Kalnichevski + * [HTTPCLIENT-1238] Contribute Bundle Activator And Central Proxy Configuration. Contributed by Simone Tripodi diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContextBuilder.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContextBuilder.java index 7f8d1ead5..cf2e3ef27 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContextBuilder.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLContextBuilder.java @@ -74,6 +74,11 @@ public SSLContextBuilder useProtocol(final String protocol) { return this; } + public SSLContextBuilder setSecureRandom(final SecureRandom secureRandom) { + this.secureRandom = secureRandom; + return this; + } + public SSLContextBuilder loadTrustMaterial( final KeyStore truststore, final char[] truststorePassword, 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 c34e15fdd..8d7983028 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 @@ -57,6 +57,7 @@ import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; import org.apache.http.util.Asserts; +import org.apache.http.util.TextUtils; /** * Layered socket factory for TLS/SSL connections. @@ -84,50 +85,7 @@ * itself to the target HTTPS server during the SSL session handshake if * requested to do so by the server. * The target HTTPS server will in its turn verify the certificate presented - * by the client in order to establish client's authenticity - *

- * Use the following sequence of actions to generate a key-store file - *

- * + * by the client in order to establish client's authenticity. * * @since 4.0 */ @@ -162,6 +120,13 @@ public static SSLSocketFactory getSocketFactory() throws SSLInitializationExcept BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); } + private static String[] split(final String s) { + if (TextUtils.isBlank(s)) { + return null; + } + return s.split(" *, *"); + } + /** * Obtains default SSL socket factory with an SSL context based on system properties * as described in @@ -174,6 +139,8 @@ public static SSLSocketFactory getSocketFactory() throws SSLInitializationExcept public static SSLSocketFactory getSystemSocketFactory() throws SSLInitializationException { return new SSLSocketFactory( (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(), + split(System.getProperty("https.protocols")), + split(System.getProperty("https.cipherSuites")), BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); } @@ -181,9 +148,11 @@ public static SSLSocketFactory getSystemSocketFactory() throws SSLInitialization private final HostNameResolver nameResolver; // TODO: make final private volatile X509HostnameVerifier hostnameVerifier; + private final String[] supportedProtocols; + private final String[] supportedCipherSuites; /** - * @deprecated (4.1) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext))}. + * @deprecated (4.1) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)}. */ @Deprecated public SSLSocketFactory( @@ -206,7 +175,7 @@ public SSLSocketFactory( * @since 4.1 * * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext, - * X509HostnameVerifier)))} + * X509HostnameVerifier)} */ @Deprecated public SSLSocketFactory( @@ -230,7 +199,7 @@ public SSLSocketFactory( * @since 4.1 * * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext, - * X509HostnameVerifier)))} + * X509HostnameVerifier)} */ @Deprecated public SSLSocketFactory( @@ -250,7 +219,7 @@ public SSLSocketFactory( } /** - * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)))} + * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)} */ @Deprecated public SSLSocketFactory( @@ -266,7 +235,7 @@ public SSLSocketFactory( } /** - * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)))} + * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)} */ @Deprecated public SSLSocketFactory( @@ -280,7 +249,7 @@ public SSLSocketFactory( } /** - * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)))} + * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)} */ @Deprecated public SSLSocketFactory( @@ -295,7 +264,8 @@ public SSLSocketFactory( /** * @since 4.1 * - * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext, X509HostnameVerifier))))} + * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext, + * X509HostnameVerifier)} */ @Deprecated public SSLSocketFactory( @@ -311,7 +281,7 @@ public SSLSocketFactory( /** * @since 4.1 * - * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext))))} + * @deprecated (4.3) Use {@link SSLContextBuilder} and {@link #SSLSocketFactory(SSLContext)} */ @Deprecated public SSLSocketFactory( @@ -337,6 +307,8 @@ public SSLSocketFactory( this.socketfactory = sslContext.getSocketFactory(); this.hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; this.nameResolver = nameResolver; + this.supportedProtocols = null; + this.supportedCipherSuites = null; } /** @@ -344,11 +316,20 @@ public SSLSocketFactory( */ public SSLSocketFactory( final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) { - super(); - Args.notNull(sslContext, "SSL context"); - this.socketfactory = sslContext.getSocketFactory(); - this.hostnameVerifier = hostnameVerifier; - this.nameResolver = null; + this(Args.notNull(sslContext, "SSL context").getSocketFactory(), + null, null, hostnameVerifier); + } + + /** + * @since 4.3 + */ + public SSLSocketFactory( + final SSLContext sslContext, + final String[] supportedProtocols, + final String[] supportedCipherSuites, + final X509HostnameVerifier hostnameVerifier) { + this(Args.notNull(sslContext, "SSL context").getSocketFactory(), + supportedProtocols, supportedCipherSuites, hostnameVerifier); } /** @@ -357,8 +338,21 @@ public SSLSocketFactory( public SSLSocketFactory( final javax.net.ssl.SSLSocketFactory socketfactory, final X509HostnameVerifier hostnameVerifier) { + this(socketfactory, null, null, hostnameVerifier); + } + + /** + * @since 4.3 + */ + public SSLSocketFactory( + final javax.net.ssl.SSLSocketFactory socketfactory, + final String[] supportedProtocols, + final String[] supportedCipherSuites, + final X509HostnameVerifier hostnameVerifier) { Args.notNull(socketfactory, "SSL socket factory"); this.socketfactory = socketfactory; + this.supportedProtocols = supportedProtocols; + this.supportedCipherSuites = supportedCipherSuites; this.hostnameVerifier = hostnameVerifier; this.nameResolver = null; } @@ -522,6 +516,16 @@ public Socket createSocket( protected void prepareSocket(final SSLSocket socket) throws IOException { } + private void internalPrepareSocket(final SSLSocket socket) throws IOException { + if (supportedProtocols != null) { + socket.setEnabledProtocols(supportedProtocols); + } + if (supportedCipherSuites != null) { + socket.setEnabledCipherSuites(supportedCipherSuites); + } + prepareSocket(socket); + } + /** * {@inheritDoc} * @@ -529,7 +533,7 @@ protected void prepareSocket(final SSLSocket socket) throws IOException { */ public Socket createSocket(final HttpContext context) throws IOException { final SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); - prepareSocket(sock); + internalPrepareSocket(sock); return sock; } @@ -575,9 +579,9 @@ public Socket createLayeredSocket( target, port, true); - prepareSocket(sslSocket); - verifyHostname(sslSocket, target); - return sslSocket; + internalPrepareSocket(sslSocket); + verifyHostname(sslSocket, target); + return sslSocket; } private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException {