diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml
index ca48f350e..c7f8ee608 100644
--- a/httpclient5/pom.xml
+++ b/httpclient5/pom.xml
@@ -52,6 +52,12 @@
slf4j-api
compile
+
+ org.conscrypt
+ conscrypt-openjdk-uber
+ compile
+ true
+
org.apache.httpcomponents.core5
httpcore5-reactive
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
index 610d9ab70..9273282d7 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
@@ -29,11 +29,13 @@ package org.apache.hc.client5.http.impl.nio;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.ssl.ConscryptClientTlsStrategy;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
import org.apache.hc.core5.pool.PoolReusePolicy;
+import org.apache.hc.core5.util.ReflectionUtils;
import org.apache.hc.core5.util.TimeValue;
/**
@@ -176,10 +178,18 @@ public class PoolingAsyncClientConnectionManagerBuilder {
if (tlsStrategy != null) {
tlsStrategyCopy = tlsStrategy;
} else {
- if (systemProperties) {
- tlsStrategyCopy = DefaultClientTlsStrategy.getSystemDefault();
+ if (ReflectionUtils.determineJRELevel() <= 8 && ConscryptClientTlsStrategy.isSupported()) {
+ if (systemProperties) {
+ tlsStrategyCopy = ConscryptClientTlsStrategy.getSystemDefault();
+ } else {
+ tlsStrategyCopy = ConscryptClientTlsStrategy.getDefault();
+ }
} else {
- tlsStrategyCopy = DefaultClientTlsStrategy.getDefault();
+ if (systemProperties) {
+ tlsStrategyCopy = DefaultClientTlsStrategy.getSystemDefault();
+ } else {
+ tlsStrategyCopy = DefaultClientTlsStrategy.getDefault();
+ }
}
}
final PoolingAsyncClientConnectionManager poolingmgr = new PoolingAsyncClientConnectionManager(
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java
new file mode 100644
index 000000000..c4cf48b96
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java
@@ -0,0 +1,149 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.ssl;
+
+import java.net.SocketAddress;
+import java.util.Arrays;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSession;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.ssl.H2TlsSupport;
+import org.apache.hc.core5.net.NamedEndpoint;
+import org.apache.hc.core5.reactor.ssl.SSLBufferMode;
+import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
+import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
+import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
+import org.apache.hc.core5.util.Args;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Contract(threading = ThreadingBehavior.STATELESS)
+abstract class AbstractClientTlsStrategy implements TlsStrategy {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final SSLContext sslContext;
+ private final String[] supportedProtocols;
+ private final String[] supportedCipherSuites;
+ private final SSLBufferMode sslBufferManagement;
+ private final HostnameVerifier hostnameVerifier;
+ private final TlsSessionValidator tlsSessionValidator;
+
+ AbstractClientTlsStrategy(
+ final SSLContext sslContext,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final SSLBufferMode sslBufferManagement,
+ final HostnameVerifier hostnameVerifier) {
+ super();
+ this.sslContext = Args.notNull(sslContext, "SSL context");
+ this.supportedProtocols = supportedProtocols;
+ this.supportedCipherSuites = supportedCipherSuites;
+ this.sslBufferManagement = sslBufferManagement != null ? sslBufferManagement : SSLBufferMode.STATIC;
+ this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : HttpsSupport.getDefaultHostnameVerifier();
+ this.tlsSessionValidator = new TlsSessionValidator(log);
+ }
+
+ @Override
+ public boolean upgrade(
+ final TransportSecurityLayer tlsSession,
+ final HttpHost host,
+ final SocketAddress localAddress,
+ final SocketAddress remoteAddress,
+ final Object attachment) {
+ tlsSession.startTls(sslContext, host, sslBufferManagement, new SSLSessionInitializer() {
+
+ @Override
+ public void initialize(final NamedEndpoint endpoint, final SSLEngine sslEngine) {
+
+ final HttpVersionPolicy versionPolicy = attachment instanceof HttpVersionPolicy ?
+ (HttpVersionPolicy) attachment : HttpVersionPolicy.NEGOTIATE;
+
+ final SSLParameters sslParameters = sslEngine.getSSLParameters();
+ if (supportedProtocols != null) {
+ sslParameters.setProtocols(supportedProtocols);
+ } else if (versionPolicy != HttpVersionPolicy.FORCE_HTTP_1) {
+ sslParameters.setProtocols(H2TlsSupport.excludeBlacklistedProtocols(sslParameters.getProtocols()));
+ }
+ if (supportedCipherSuites != null) {
+ sslParameters.setCipherSuites(supportedCipherSuites);
+ } else if (versionPolicy != HttpVersionPolicy.FORCE_HTTP_1) {
+ sslParameters.setCipherSuites(H2TlsSupport.excludeBlacklistedCiphers(sslParameters.getCipherSuites()));
+ }
+
+ if (versionPolicy != HttpVersionPolicy.FORCE_HTTP_1) {
+ H2TlsSupport.setEnableRetransmissions(sslParameters, false);
+ }
+
+ applyParameters(sslEngine, sslParameters, H2TlsSupport.selectApplicationProtocols(attachment));
+
+ initializeEngine(sslEngine);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Enabled protocols: " + Arrays.asList(sslEngine.getEnabledProtocols()));
+ log.debug("Enabled cipher suites:" + Arrays.asList(sslEngine.getEnabledCipherSuites()));
+ }
+ }
+
+ }, new SSLSessionVerifier() {
+
+ @Override
+ public TlsDetails verify(final NamedEndpoint endpoint, final SSLEngine sslEngine) throws SSLException {
+ verifySession(host.getHostName(), sslEngine.getSession());
+ return createTlsDetails(sslEngine);
+ }
+
+ });
+ return true;
+ }
+
+ abstract void applyParameters(SSLEngine sslEngine, SSLParameters sslParameters, String[] appProtocols);
+
+ abstract TlsDetails createTlsDetails(SSLEngine sslEngine);
+
+ protected void initializeEngine(final SSLEngine sslEngine) {
+ }
+
+ protected void verifySession(
+ final String hostname,
+ final SSLSession sslsession) throws SSLException {
+ tlsSessionValidator.verifySession(hostname, sslsession, hostnameVerifier);
+ }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/ConscryptClientTlsStrategy.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/ConscryptClientTlsStrategy.java
new file mode 100644
index 000000000..9ec8dbf75
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/ConscryptClientTlsStrategy.java
@@ -0,0 +1,119 @@
+/*
+ * ====================================================================
+ * 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.hc.client5.http.ssl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.http2.ssl.H2TlsSupport;
+import org.apache.hc.core5.reactor.ssl.SSLBufferMode;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
+import org.apache.hc.core5.ssl.SSLContexts;
+import org.conscrypt.Conscrypt;
+
+/**
+ * TLS upgrade strategy for non-blocking client connections using Conscrypt TLS library.
+ *
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.STATELESS)
+public class ConscryptClientTlsStrategy extends AbstractClientTlsStrategy {
+
+ public static TlsStrategy getDefault() {
+ return new ConscryptClientTlsStrategy(
+ SSLContexts.createDefault(),
+ HttpsSupport.getDefaultHostnameVerifier());
+ }
+
+ public static TlsStrategy getSystemDefault() {
+ return new ConscryptClientTlsStrategy(
+ SSLContexts.createSystemDefault(),
+ HttpsSupport.getSystemProtocols(),
+ HttpsSupport.getSystemCipherSuits(),
+ SSLBufferMode.STATIC,
+ HttpsSupport.getDefaultHostnameVerifier());
+ }
+
+ public ConscryptClientTlsStrategy(
+ final SSLContext sslContext,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final SSLBufferMode sslBufferManagement,
+ final HostnameVerifier hostnameVerifier) {
+ super(sslContext, supportedProtocols, supportedCipherSuites, sslBufferManagement, hostnameVerifier);
+ }
+
+ public ConscryptClientTlsStrategy(
+ final SSLContext sslcontext,
+ final HostnameVerifier hostnameVerifier) {
+ this(sslcontext, null, null, SSLBufferMode.STATIC, hostnameVerifier);
+ }
+
+ public ConscryptClientTlsStrategy(final SSLContext sslcontext) {
+ this(sslcontext, HttpsSupport.getDefaultHostnameVerifier());
+ }
+
+ @Override
+ void applyParameters(final SSLEngine sslEngine, final SSLParameters sslParameters, final String[] appProtocols) {
+ if (Conscrypt.isConscrypt(sslEngine)) {
+ sslEngine.setSSLParameters(sslParameters);
+ Conscrypt.setApplicationProtocols(sslEngine, appProtocols);
+ } else {
+ H2TlsSupport.setApplicationProtocols(sslParameters, appProtocols);
+ sslEngine.setSSLParameters(sslParameters);
+ }
+ }
+
+ @Override
+ TlsDetails createTlsDetails(final SSLEngine sslEngine) {
+ if (Conscrypt.isConscrypt(sslEngine)) {
+ return new TlsDetails(sslEngine.getSession(), Conscrypt.getApplicationProtocol(sslEngine));
+ } else {
+ return null;
+ }
+ }
+
+ public static boolean isSupported() {
+ try {
+ final Class> clazz = Class.forName("org.conscrypt.Conscrypt");
+ final Method method = clazz.getMethod("isAvailable");
+ return (Boolean) method.invoke(null);
+ } catch (final ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ return false;
+ }
+ }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/DefaultClientTlsStrategy.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/DefaultClientTlsStrategy.java
index 9e491fa53..9a089db33 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/DefaultClientTlsStrategy.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/DefaultClientTlsStrategy.java
@@ -27,42 +27,27 @@
package org.apache.hc.client5.http.ssl;
-import java.net.SocketAddress;
-import java.util.Arrays;
-
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLSession;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.function.Factory;
-import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
-import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
import org.apache.hc.core5.http2.ssl.H2TlsSupport;
-import org.apache.hc.core5.net.NamedEndpoint;
import org.apache.hc.core5.reactor.ssl.SSLBufferMode;
-import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
-import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
-import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
import org.apache.hc.core5.ssl.SSLContexts;
-import org.apache.hc.core5.util.Args;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
- * Default SSL upgrade strategy for non-blocking client connections.
+ * TLS upgrade strategy for non-blocking client connections.
*
* @since 5.0
*/
@Contract(threading = ThreadingBehavior.STATELESS)
-public class DefaultClientTlsStrategy implements TlsStrategy {
+public class DefaultClientTlsStrategy extends AbstractClientTlsStrategy {
public static TlsStrategy getDefault() {
return new DefaultClientTlsStrategy(
@@ -79,15 +64,7 @@ public class DefaultClientTlsStrategy implements TlsStrategy {
HttpsSupport.getDefaultHostnameVerifier());
}
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private final SSLContext sslContext;
- private final String[] supportedProtocols;
- private final String[] supportedCipherSuites;
- private final SSLBufferMode sslBufferManagement;
- private final HostnameVerifier hostnameVerifier;
private final Factory tlsDetailsFactory;
- private final TlsSessionValidator tlsSessionValidator;
public DefaultClientTlsStrategy(
final SSLContext sslContext,
@@ -96,14 +73,8 @@ public class DefaultClientTlsStrategy implements TlsStrategy {
final SSLBufferMode sslBufferManagement,
final HostnameVerifier hostnameVerifier,
final Factory tlsDetailsFactory) {
- super();
- this.sslContext = Args.notNull(sslContext, "SSL context");
- this.supportedProtocols = supportedProtocols;
- this.supportedCipherSuites = supportedCipherSuites;
- this.sslBufferManagement = sslBufferManagement != null ? sslBufferManagement : SSLBufferMode.STATIC;
- this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : HttpsSupport.getDefaultHostnameVerifier();
+ super(sslContext, supportedProtocols, supportedCipherSuites, sslBufferManagement, hostnameVerifier);
this.tlsDetailsFactory = tlsDetailsFactory;
- this.tlsSessionValidator = new TlsSessionValidator(log);
}
public DefaultClientTlsStrategy(
@@ -126,78 +97,14 @@ public class DefaultClientTlsStrategy implements TlsStrategy {
}
@Override
- public boolean upgrade(
- final TransportSecurityLayer tlsSession,
- final HttpHost host,
- final SocketAddress localAddress,
- final SocketAddress remoteAddress,
- final Object attachment) {
- tlsSession.startTls(sslContext, host, sslBufferManagement, new SSLSessionInitializer() {
-
- @Override
- public void initialize(final NamedEndpoint endpoint, final SSLEngine sslEngine) {
-
- final HttpVersionPolicy versionPolicy = attachment instanceof HttpVersionPolicy ?
- (HttpVersionPolicy) attachment : HttpVersionPolicy.NEGOTIATE;
-
- final SSLParameters sslParameters = sslEngine.getSSLParameters();
- if (supportedProtocols != null) {
- sslParameters.setProtocols(supportedProtocols);
- } else if (versionPolicy != HttpVersionPolicy.FORCE_HTTP_1) {
- sslParameters.setProtocols(H2TlsSupport.excludeBlacklistedProtocols(sslParameters.getProtocols()));
- }
- if (supportedCipherSuites != null) {
- sslParameters.setCipherSuites(supportedCipherSuites);
- } else if (versionPolicy != HttpVersionPolicy.FORCE_HTTP_1) {
- sslParameters.setCipherSuites(H2TlsSupport.excludeBlacklistedCiphers(sslParameters.getCipherSuites()));
- }
-
- switch (versionPolicy) {
- case FORCE_HTTP_1:
- H2TlsSupport.setApplicationProtocols(sslParameters, new String[] {
- ApplicationProtocols.HTTP_1_1.id });
- break;
- case FORCE_HTTP_2:
- H2TlsSupport.setEnableRetransmissions(sslParameters, false);
- H2TlsSupport.setApplicationProtocols(sslParameters, new String[] {
- ApplicationProtocols.HTTP_2.id });
- break;
- case NEGOTIATE:
- H2TlsSupport.setEnableRetransmissions(sslParameters, false);
- H2TlsSupport.setApplicationProtocols(sslParameters, new String[] {
- ApplicationProtocols.HTTP_2.id, ApplicationProtocols.HTTP_1_1.id });
- break;
- }
-
- sslEngine.setSSLParameters(sslParameters);
-
- initializeEngine(sslEngine);
-
- if (log.isDebugEnabled()) {
- log.debug("Enabled protocols: " + Arrays.asList(sslEngine.getEnabledProtocols()));
- log.debug("Enabled cipher suites:" + Arrays.asList(sslEngine.getEnabledCipherSuites()));
- }
- }
-
- }, new SSLSessionVerifier() {
-
- @Override
- public TlsDetails verify(final NamedEndpoint endpoint, final SSLEngine sslEngine) throws SSLException {
- verifySession(host.getHostName(), sslEngine.getSession());
- return tlsDetailsFactory != null ? tlsDetailsFactory.create(sslEngine) : null;
- }
-
- });
- return true;
+ void applyParameters(final SSLEngine sslEngine, final SSLParameters sslParameters, final String[] appProtocols) {
+ H2TlsSupport.setApplicationProtocols(sslParameters, appProtocols);
+ sslEngine.setSSLParameters(sslParameters);
}
- protected void initializeEngine(final SSLEngine sslEngine) {
- }
-
- protected void verifySession(
- final String hostname,
- final SSLSession sslsession) throws SSLException {
- tlsSessionValidator.verifySession(hostname, sslsession, hostnameVerifier);
+ @Override
+ TlsDetails createTlsDetails(final SSLEngine sslEngine) {
+ return tlsDetailsFactory != null ? tlsDetailsFactory.create(sslEngine) : null;
}
}
diff --git a/pom.xml b/pom.xml
index 5e439a613..36fbc7a3c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,7 @@
5.0-beta6
2.9.1
1.11
+ 1.4.1
3.4.0
2.12.3
1.7.25
@@ -123,6 +124,11 @@
commons-codec
${commons-codec.version}
+
+ org.conscrypt
+ conscrypt-openjdk-uber
+ ${conscrypt.version}
+
org.ehcache.modules
ehcache-api