Skip to content

Commit df6ed70

Browse files
author
Stephane Landelle
committed
Introduce acceptAnyCertificate config, defaulting to false, close AsyncHttpClient#526, close AsyncHttpClient#352
1 parent e5e6489 commit df6ed70

File tree

12 files changed

+104
-17
lines changed

12 files changed

+104
-17
lines changed

api/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ public class AsyncHttpClientConfig {
112112
protected int spdyInitialWindowSize;
113113
protected int spdyMaxConcurrentStreams;
114114
protected TimeConverter timeConverter;
115+
protected boolean acceptAnyCertificate;
115116

116117
protected AsyncHttpClientConfig() {
117118
}
@@ -151,7 +152,8 @@ private AsyncHttpClientConfig(int maxTotalConnections, //
151152
boolean spdyEnabled, //
152153
int spdyInitialWindowSize, //
153154
int spdyMaxConcurrentStreams, //
154-
TimeConverter timeConverter) {
155+
TimeConverter timeConverter, //
156+
boolean acceptAnyCertificate) {
155157

156158
this.maxTotalConnections = maxTotalConnections;
157159
this.maxConnectionPerHost = maxConnectionPerHost;
@@ -187,6 +189,7 @@ private AsyncHttpClientConfig(int maxTotalConnections, //
187189
this.spdyInitialWindowSize = spdyInitialWindowSize;
188190
this.spdyMaxConcurrentStreams = spdyMaxConcurrentStreams;
189191
this.timeConverter = timeConverter;
192+
this.acceptAnyCertificate = acceptAnyCertificate;
190193

191194
}
192195

@@ -533,6 +536,10 @@ public TimeConverter getTimeConverter() {
533536
return timeConverter;
534537
}
535538

539+
public boolean isAcceptAnyCertificate() {
540+
return acceptAnyCertificate;
541+
}
542+
536543
/**
537544
* Builder for an {@link AsyncHttpClient}
538545
*/
@@ -564,6 +571,7 @@ public static class Builder {
564571
private boolean spdyEnabled = defaultSpdyEnabled();
565572
private int spdyInitialWindowSize = defaultSpdyInitialWindowSize();
566573
private int spdyMaxConcurrentStreams = defaultSpdyMaxConcurrentStreams();
574+
private boolean acceptAnyCertificate = defaultAcceptAnyCertificate();
567575

568576
private ScheduledExecutorService reaper;
569577
private ExecutorService applicationThreadPool;
@@ -1078,6 +1086,11 @@ public Builder setTimeConverter(TimeConverter timeConverter) {
10781086
return this;
10791087
}
10801088

1089+
public Builder setAcceptAnyCertificate(boolean acceptAnyCertificate) {
1090+
this.acceptAnyCertificate = acceptAnyCertificate;
1091+
return this;
1092+
}
1093+
10811094
/**
10821095
* Create a config builder with values taken from the given prototype configuration.
10831096
*
@@ -1186,7 +1199,8 @@ public Thread newThread(Runnable r) {
11861199
spdyEnabled, //
11871200
spdyInitialWindowSize, //
11881201
spdyMaxConcurrentStreams, //
1189-
timeConverter);
1202+
timeConverter, //
1203+
acceptAnyCertificate);
11901204
}
11911205
}
11921206
}

api/src/main/java/org/asynchttpclient/AsyncHttpClientConfigBean.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void configureDefaults() {
7070
spdyEnabled = defaultSpdyEnabled();
7171
spdyInitialWindowSize = defaultSpdyInitialWindowSize();
7272
spdyMaxConcurrentStreams = defaultSpdyMaxConcurrentStreams();
73+
acceptAnyCertificate = defaultAcceptAnyCertificate();
7374
if (defaultUseProxySelector()) {
7475
proxyServerSelector = ProxyUtils.getJdkDefaultProxyServerSelector();
7576
} else if (defaultUseProxyProperties()) {
@@ -234,4 +235,9 @@ public AsyncHttpClientConfigBean setIoThreadMultiplier(int ioThreadMultiplier) {
234235
this.ioThreadMultiplier = ioThreadMultiplier;
235236
return this;
236237
}
238+
239+
public AsyncHttpClientConfigBean setAcceptAnyCertificate(boolean acceptAnyCertificate) {
240+
this.acceptAnyCertificate = acceptAnyCertificate;
241+
return this;
242+
}
237243
}

api/src/main/java/org/asynchttpclient/AsyncHttpClientConfigDefaults.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,8 @@ public static int defaultSpdyInitialWindowSize() {
133133
public static int defaultSpdyMaxConcurrentStreams() {
134134
return Integer.getInteger(ASYNC_CLIENT + "spdyMaxConcurrentStreams", 100);
135135
}
136+
137+
public static boolean defaultAcceptAnyCertificate() {
138+
return getBoolean(ASYNC_CLIENT + "acceptAnyCertificate", false);
139+
}
136140
}

api/src/main/java/org/asynchttpclient/SimpleAsyncHttpClient.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,11 @@ public Builder setProviderClass(String providerClass) {
678678
return this;
679679
}
680680

681+
public Builder setAcceptAnyCertificate(boolean acceptAnyCertificate) {
682+
configBuilder.setAcceptAnyCertificate(acceptAnyCertificate);
683+
return this;
684+
}
685+
681686
public SimpleAsyncHttpClient build() {
682687

683688
if (realmBuilder != null) {

api/src/main/java/org/asynchttpclient/util/MiscUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,8 @@ public static boolean getBoolean(String systemPropName, boolean defaultValue) {
4444
String systemPropValue = System.getProperty(systemPropName);
4545
return systemPropValue != null ? systemPropValue.equalsIgnoreCase("true") : defaultValue;
4646
}
47+
48+
public static <T> T withDefault(T value, T defaults) {
49+
return value != null? value : value;
50+
}
4751
}

api/src/main/java/org/asynchttpclient/util/SslUtils.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,47 @@
1616
package org.asynchttpclient.util;
1717

1818
import javax.net.ssl.SSLContext;
19+
import javax.net.ssl.TrustManager;
20+
import javax.net.ssl.X509TrustManager;
21+
1922
import java.io.IOException;
2023
import java.security.GeneralSecurityException;
24+
import java.security.KeyManagementException;
25+
import java.security.NoSuchAlgorithmException;
26+
import java.security.SecureRandom;
2127

2228
/**
2329
* This class is a copy of http://github.com/sonatype/wagon-ning/raw/master/src/main/java/org/apache/maven/wagon/providers/http/SslUtils.java
2430
*/
2531
public class SslUtils {
32+
33+
static class LooseTrustManager implements X509TrustManager {
34+
35+
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
36+
return new java.security.cert.X509Certificate[0];
37+
}
38+
39+
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
40+
}
2641

42+
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
43+
}
44+
}
45+
46+
private SSLContext looseTrustManagerSSLContext = looseTrustManagerSSLContext();
47+
48+
private SSLContext looseTrustManagerSSLContext() {
49+
try {
50+
SSLContext sslContext = SSLContext.getInstance("TLS");
51+
sslContext.init(null, new TrustManager[] { new LooseTrustManager() }, new SecureRandom());
52+
return sslContext;
53+
} catch (NoSuchAlgorithmException e) {
54+
throw new ExceptionInInitializerError(e);
55+
} catch (KeyManagementException e) {
56+
throw new ExceptionInInitializerError(e);
57+
}
58+
}
59+
2760
private static class SingletonHolder {
2861
public static final SslUtils instance = new SslUtils();
2962
}
@@ -32,7 +65,7 @@ public static SslUtils getInstance() {
3265
return SingletonHolder.instance;
3366
}
3467

35-
public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
36-
return SSLContext.getDefault();
68+
public SSLContext getSSLContext(boolean acceptAnyCertificate) throws GeneralSecurityException, IOException {
69+
return acceptAnyCertificate? looseTrustManagerSSLContext: SSLContext.getDefault();
3770
}
3871
}

api/src/test/java/org/asynchttpclient/async/HttpToHttpsRedirectTest.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ public void runAllSequentiallyBecauseNotThreadSafe() throws Exception {
9696
public void httpToHttpsRedirect() throws Exception {
9797
redirectDone.getAndSet(false);
9898

99-
AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setMaxRedirects(5).setFollowRedirects(true).build();
99+
AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder()//
100+
.setMaxRedirects(5)//
101+
.setFollowRedirects(true)//
102+
.setAcceptAnyCertificate(true)//
103+
.build();
100104
AsyncHttpClient c = getAsyncHttpClient(cg);
101105
try {
102106
Response response = c.prepareGet(getTargetUrl()).setHeader("X-redirect", getTargetUrl2()).execute().get();
@@ -112,7 +116,11 @@ public void httpToHttpsRedirect() throws Exception {
112116
public void httpToHttpsProperConfig() throws Exception {
113117
redirectDone.getAndSet(false);
114118

115-
AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setMaxRedirects(5).setFollowRedirects(true).build();
119+
AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder()//
120+
.setMaxRedirects(5)//
121+
.setFollowRedirects(true)//
122+
.setAcceptAnyCertificate(true)//
123+
.build();
116124
AsyncHttpClient c = getAsyncHttpClient(cg);
117125
try {
118126
Response response = c.prepareGet(getTargetUrl()).setHeader("X-redirect", getTargetUrl2() + "/test2").execute().get();
@@ -134,7 +142,11 @@ public void httpToHttpsProperConfig() throws Exception {
134142
public void relativeLocationUrl() throws Exception {
135143
redirectDone.getAndSet(false);
136144

137-
AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder().setMaxRedirects(5).setFollowRedirects(true).build();
145+
AsyncHttpClientConfig cg = new AsyncHttpClientConfig.Builder()//
146+
.setMaxRedirects(5)//
147+
.setFollowRedirects(true)//
148+
.setAcceptAnyCertificate(true)//
149+
.build();
138150
AsyncHttpClient c = getAsyncHttpClient(cg);
139151
try {
140152
Response response = c.prepareGet(getTargetUrl()).setHeader("X-redirect", "/foo/test").execute().get();

api/src/test/java/org/asynchttpclient/async/ProxyTunnellingTest.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,14 @@ public void tearDownGlobal() throws Exception {
7474

7575
@Test(groups = { "online", "default_provider" })
7676
public void testRequestProxy() throws IOException, InterruptedException, ExecutionException, TimeoutException {
77-
AsyncHttpClientConfig.Builder b = new AsyncHttpClientConfig.Builder();
78-
b.setFollowRedirects(true);
7977

8078
ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1);
8179

82-
AsyncHttpClientConfig config = b.build();
80+
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder()//
81+
.setFollowRedirects(true)//
82+
.setAcceptAnyCertificate(true)//
83+
.build();
84+
8385
AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config);
8486
try {
8587
RequestBuilder rb = new RequestBuilder("GET").setProxyServer(ps).setUrl(getTargetUrl2());
@@ -108,6 +110,7 @@ public void testConfigProxy() throws IOException, InterruptedException, Executio
108110
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder()//
109111
.setFollowRedirects(true)//
110112
.setProxyServer(new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1))//
113+
.setAcceptAnyCertificate(true)//
111114
.build();
112115
AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config);
113116
try {
@@ -136,7 +139,12 @@ public void testSimpleAHCConfigProxy() throws IOException, InterruptedException,
136139

137140
SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder()//
138141
.setProviderClass(getProviderClass())//
139-
.setProxyProtocol(ProxyServer.Protocol.HTTPS).setProxyHost("127.0.0.1").setProxyPort(port1).setFollowRedirects(true).setUrl(getTargetUrl2())//
142+
.setProxyProtocol(ProxyServer.Protocol.HTTPS)//
143+
.setProxyHost("127.0.0.1")//
144+
.setProxyPort(port1)//
145+
.setFollowRedirects(true)//
146+
.setUrl(getTargetUrl2())//
147+
.setAcceptAnyCertificate(true)//
140148
.setHeader("Content-Type", "text/html")//
141149
.build();
142150
try {

api/src/test/java/org/asynchttpclient/websocket/ProxyTunnellingTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ protected String getTargetUrl() {
7878
public void echoText() throws Exception {
7979

8080
ProxyServer ps = new ProxyServer(ProxyServer.Protocol.HTTPS, "127.0.0.1", port1);
81-
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setProxyServer(ps).build();
81+
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setProxyServer(ps).setAcceptAnyCertificate(true).build();
8282
AsyncHttpClient asyncHttpClient = getAsyncHttpClient(config);
8383
try {
8484
final CountDownLatch latch = new CountDownLatch(1);

providers/grizzly/src/main/java/org/asynchttpclient/providers/grizzly/GrizzlyAsyncHttpProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ public void onTimeout(Connection connection) {
253253
SSLContext context = clientConfig.getSSLContext();
254254
if (context == null) {
255255
try {
256-
context = SslUtils.getInstance().getSSLContext();
256+
context = SslUtils.getInstance().getSSLContext(clientConfig.isAcceptAnyCertificate());
257257
} catch (Exception e) {
258258
throw new IllegalStateException(e);
259259
}

providers/grizzly/src/test/java/org/asynchttpclient/providers/grizzly/GrizzlyFeedableBodyGeneratorTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ private void doSimpleFeeder(final boolean secure) {
138138
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder()
139139
.setMaxConnectionsPerHost(60)
140140
.setMaxConnectionsTotal(60)
141+
.setAcceptAnyCertificate(true)
141142
.build();
142143
final AsyncHttpClient client =
143144
new DefaultAsyncHttpClient(new GrizzlyAsyncHttpProvider(config), config);
@@ -240,6 +241,7 @@ private void doNonBlockingFeeder(final boolean secure) {
240241
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder()
241242
.setMaxConnectionsPerHost(60)
242243
.setMaxConnectionsTotal(60)
244+
.setAcceptAnyCertificate(true)
243245
.build();
244246
final AsyncHttpClient client =
245247
new DefaultAsyncHttpClient(new GrizzlyAsyncHttpProvider(config), config);

providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,9 @@ private SSLEngine createSSLEngine() throws IOException, GeneralSecurityException
209209

210210
} else {
211211
SSLContext sslContext = config.getSSLContext();
212-
if (sslContext == null) {
213-
sslContext = SslUtils.getInstance().getSSLContext();
214-
}
215-
212+
if (sslContext == null)
213+
sslContext = SslUtils.getInstance().getSSLContext(config.isAcceptAnyCertificate());
214+
216215
SSLEngine sslEngine = sslContext.createSSLEngine();
217216
sslEngine.setUseClientMode(true);
218217
return sslEngine;

0 commit comments

Comments
 (0)