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
- *
- *
- *
- *
- *
- * Issue a certificate signing request (CSR)
- *
keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore
- *
- *
- *
- *
- * Send the certificate request to the trusted Certificate Authority for signature.
- * One may choose to act as her own CA and sign the certificate request using a PKI
- * tool, such as OpenSSL.
- *
- *
- *
- *
- * Import the trusted CA root certificate
- *
keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore
- *
- *
- *
- *
- * Import the PKCS#7 file containg the complete certificate chain
- *
keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore
- *
- *
- *
- *
- * Verify the content the resultant keystore file
- *
keytool -list -v -keystore my.keystore
- *
- *
- *
+ * 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 {