Skip to content

Commit 54c759c

Browse files
author
Stephane Landelle
committed
Merge pull request AsyncHttpClient#572 from AsyncHttpClient/ssl-refactoring
Enable SSL validation
2 parents 01e61a1 + df6ed70 commit 54c759c

File tree

13 files changed

+115
-166
lines changed

13 files changed

+115
-166
lines changed

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

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
import javax.net.ssl.HostnameVerifier;
2727
import javax.net.ssl.SSLContext;
28-
import javax.net.ssl.SSLEngine;
2928

3029
import java.io.IOException;
3130
import java.io.InputStream;
@@ -94,7 +93,6 @@ public class AsyncHttpClientConfig {
9493
protected ExecutorService applicationThreadPool;
9594
protected ProxyServerSelector proxyServerSelector;
9695
protected SSLContext sslContext;
97-
protected SSLEngineFactory sslEngineFactory;
9896
protected AsyncHttpProviderConfig<?, ?> providerConfig;
9997
protected Realm realm;
10098
protected List<RequestFilter> requestFilters;
@@ -114,6 +112,7 @@ public class AsyncHttpClientConfig {
114112
protected int spdyInitialWindowSize;
115113
protected int spdyMaxConcurrentStreams;
116114
protected TimeConverter timeConverter;
115+
protected boolean acceptAnyCertificate;
117116

118117
protected AsyncHttpClientConfig() {
119118
}
@@ -153,7 +152,8 @@ private AsyncHttpClientConfig(int maxTotalConnections, //
153152
boolean spdyEnabled, //
154153
int spdyInitialWindowSize, //
155154
int spdyMaxConcurrentStreams, //
156-
TimeConverter timeConverter) {
155+
TimeConverter timeConverter, //
156+
boolean acceptAnyCertificate) {
157157

158158
this.maxTotalConnections = maxTotalConnections;
159159
this.maxConnectionPerHost = maxConnectionPerHost;
@@ -169,7 +169,6 @@ private AsyncHttpClientConfig(int maxTotalConnections, //
169169
this.userAgent = userAgent;
170170
this.allowPoolingConnection = keepAlive;
171171
this.sslContext = sslContext;
172-
this.sslEngineFactory = sslEngineFactory;
173172
this.providerConfig = providerConfig;
174173
this.realm = realm;
175174
this.requestFilters = requestFilters;
@@ -190,6 +189,7 @@ private AsyncHttpClientConfig(int maxTotalConnections, //
190189
this.spdyInitialWindowSize = spdyInitialWindowSize;
191190
this.spdyMaxConcurrentStreams = spdyMaxConcurrentStreams;
192191
this.timeConverter = timeConverter;
192+
this.acceptAnyCertificate = acceptAnyCertificate;
193193

194194
}
195195

@@ -332,28 +332,6 @@ public SSLContext getSSLContext() {
332332
return sslContext;
333333
}
334334

335-
/**
336-
* Return an instance of {@link SSLEngineFactory} used for SSL connection.
337-
*
338-
* @return an instance of {@link SSLEngineFactory} used for SSL connection.
339-
*/
340-
public SSLEngineFactory getSSLEngineFactory() {
341-
if (sslEngineFactory == null) {
342-
return new SSLEngineFactory() {
343-
public SSLEngine newSSLEngine() {
344-
if (sslContext != null) {
345-
SSLEngine sslEngine = sslContext.createSSLEngine();
346-
sslEngine.setUseClientMode(true);
347-
return sslEngine;
348-
} else {
349-
return null;
350-
}
351-
}
352-
};
353-
}
354-
return sslEngineFactory;
355-
}
356-
357335
/**
358336
* Return the {@link AsyncHttpProviderConfig}
359337
*
@@ -558,6 +536,10 @@ public TimeConverter getTimeConverter() {
558536
return timeConverter;
559537
}
560538

539+
public boolean isAcceptAnyCertificate() {
540+
return acceptAnyCertificate;
541+
}
542+
561543
/**
562544
* Builder for an {@link AsyncHttpClient}
563545
*/
@@ -589,6 +571,7 @@ public static class Builder {
589571
private boolean spdyEnabled = defaultSpdyEnabled();
590572
private int spdyInitialWindowSize = defaultSpdyInitialWindowSize();
591573
private int spdyMaxConcurrentStreams = defaultSpdyMaxConcurrentStreams();
574+
private boolean acceptAnyCertificate = defaultAcceptAnyCertificate();
592575

593576
private ScheduledExecutorService reaper;
594577
private ExecutorService applicationThreadPool;
@@ -1103,6 +1086,11 @@ public Builder setTimeConverter(TimeConverter timeConverter) {
11031086
return this;
11041087
}
11051088

1089+
public Builder setAcceptAnyCertificate(boolean acceptAnyCertificate) {
1090+
this.acceptAnyCertificate = acceptAnyCertificate;
1091+
return this;
1092+
}
1093+
11061094
/**
11071095
* Create a config builder with values taken from the given prototype configuration.
11081096
*
@@ -1122,7 +1110,6 @@ public Builder(AsyncHttpClientConfig prototype) {
11221110
realm = prototype.getRealm();
11231111
requestTimeoutInMs = prototype.getRequestTimeoutInMs();
11241112
sslContext = prototype.getSSLContext();
1125-
sslEngineFactory = prototype.getSSLEngineFactory();
11261113
userAgent = prototype.getUserAgent();
11271114
redirectEnabled = prototype.isRedirectEnabled();
11281115
compressionEnabled = prototype.isCompressionEnabled();
@@ -1212,7 +1199,8 @@ public Thread newThread(Runnable r) {
12121199
spdyEnabled, //
12131200
spdyInitialWindowSize, //
12141201
spdyMaxConcurrentStreams, //
1215-
timeConverter);
1202+
timeConverter, //
1203+
acceptAnyCertificate);
12161204
}
12171205
}
12181206
}

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

Lines changed: 6 additions & 5 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()) {
@@ -175,11 +176,6 @@ public AsyncHttpClientConfigBean setSslContext(SSLContext sslContext) {
175176
return this;
176177
}
177178

178-
public AsyncHttpClientConfigBean setSslEngineFactory(SSLEngineFactory sslEngineFactory) {
179-
this.sslEngineFactory = sslEngineFactory;
180-
return this;
181-
}
182-
183179
public AsyncHttpClientConfigBean setProviderConfig(AsyncHttpProviderConfig<?, ?> providerConfig) {
184180
this.providerConfig = providerConfig;
185181
return this;
@@ -239,4 +235,9 @@ public AsyncHttpClientConfigBean setIoThreadMultiplier(int ioThreadMultiplier) {
239235
this.ioThreadMultiplier = ioThreadMultiplier;
240236
return this;
241237
}
238+
239+
public AsyncHttpClientConfigBean setAcceptAnyCertificate(boolean acceptAnyCertificate) {
240+
this.acceptAnyCertificate = acceptAnyCertificate;
241+
return this;
242+
}
242243
}

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: 25 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -15,94 +15,23 @@
1515
*/
1616
package org.asynchttpclient.util;
1717

18-
import javax.net.ssl.KeyManager;
19-
import javax.net.ssl.KeyManagerFactory;
2018
import javax.net.ssl.SSLContext;
21-
import javax.net.ssl.SSLEngine;
2219
import javax.net.ssl.TrustManager;
23-
import javax.net.ssl.TrustManagerFactory;
2420
import javax.net.ssl.X509TrustManager;
2521

26-
import java.io.FileInputStream;
2722
import java.io.IOException;
28-
import java.io.InputStream;
2923
import java.security.GeneralSecurityException;
30-
import java.security.KeyStore;
24+
import java.security.KeyManagementException;
25+
import java.security.NoSuchAlgorithmException;
3126
import java.security.SecureRandom;
32-
import java.security.Security;
3327

3428
/**
3529
* 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
3630
*/
3731
public class SslUtils {
38-
39-
private static SSLContext context = null;
40-
41-
public static SSLEngine getSSLEngine() throws GeneralSecurityException, IOException {
42-
SSLEngine engine = null;
43-
44-
SSLContext context = getSSLContext();
45-
if (context != null) {
46-
engine = context.createSSLEngine();
47-
engine.setUseClientMode(true);
48-
}
49-
50-
return engine;
51-
}
52-
53-
public static SSLContext getSSLContext() throws GeneralSecurityException, IOException {
54-
if (context == null) {
55-
SSLConfig config = new SSLConfig();
56-
if (config.keyStoreLocation == null || config.trustStoreLocation == null) {
57-
context = getLooseSSLContext();
58-
} else {
59-
context = getStrictSSLContext(config);
60-
}
61-
}
62-
return context;
63-
}
64-
65-
static SSLContext getStrictSSLContext(SSLConfig config) throws GeneralSecurityException, IOException {
66-
KeyStore keyStore = KeyStore.getInstance(config.keyStoreType);
67-
InputStream keystoreInputStream = new FileInputStream(config.keyStoreLocation);
68-
try {
69-
keyStore.load(keystoreInputStream, (config.keyStorePassword == null) ? null : config.keyStorePassword.toCharArray());
70-
} finally {
71-
keystoreInputStream.close();
72-
}
73-
74-
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(config.keyManagerAlgorithm);
75-
keyManagerFactory.init(keyStore, (config.keyManagerPassword == null) ? null : config.keyManagerPassword.toCharArray());
76-
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
77-
78-
KeyStore trustStore = KeyStore.getInstance(config.trustStoreType);
79-
InputStream truststoreInputStream = new FileInputStream(config.trustStoreLocation);
80-
try {
81-
trustStore.load(truststoreInputStream, (config.trustStorePassword == null) ? null : config.trustStorePassword.toCharArray());
82-
} finally {
83-
truststoreInputStream.close();
84-
}
85-
86-
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(config.trustManagerAlgorithm);
87-
trustManagerFactory.init(trustStore);
88-
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
89-
90-
SSLContext context = SSLContext.getInstance("TLS");
91-
context.init(keyManagers, trustManagers, null);
92-
93-
return context;
94-
}
95-
96-
static SSLContext getLooseSSLContext() throws GeneralSecurityException {
97-
SSLContext sslContext = SSLContext.getInstance("TLS");
98-
sslContext.init(null, new TrustManager[] { LooseTrustManager.INSTANCE }, new SecureRandom());
99-
return sslContext;
100-
}
101-
32+
10233
static class LooseTrustManager implements X509TrustManager {
10334

104-
public static final LooseTrustManager INSTANCE = new LooseTrustManager();
105-
10635
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
10736
return new java.security.cert.X509Certificate[0];
10837
}
@@ -114,53 +43,29 @@ public void checkServerTrusted(java.security.cert.X509Certificate[] certs, Strin
11443
}
11544
}
11645

117-
private final static class SSLConfig {
118-
119-
public String keyStoreLocation;
120-
121-
public String keyStoreType = "JKS";
122-
123-
public String keyStorePassword = "changeit";
124-
125-
public String keyManagerAlgorithm = "SunX509";
126-
127-
public String keyManagerPassword = "changeit";
128-
129-
public String trustStoreLocation;
130-
131-
public String trustStoreType = "JKS";
132-
133-
public String trustStorePassword = "changeit";
134-
135-
public String trustManagerAlgorithm = "SunX509";
136-
137-
public SSLConfig() {
138-
keyStoreLocation = System.getProperty("javax.net.ssl.keyStore");
139-
keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword", "changeit");
140-
keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
141-
keyManagerAlgorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
142-
143-
if (keyManagerAlgorithm == null) {
144-
keyManagerAlgorithm = "SunX509";
145-
}
146-
147-
keyManagerPassword = System.getProperty("javax.net.ssl.keyStorePassword", "changeit");
148-
149-
trustStoreLocation = System.getProperty("javax.net.ssl.trustStore");
150-
if (trustStoreLocation == null) {
151-
trustStoreLocation = keyStoreLocation;
152-
trustStorePassword = keyStorePassword;
153-
trustStoreType = keyStoreType;
154-
} else {
155-
trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", "changeit");
156-
trustStoreType = System.getProperty("javax.net.ssl.trustStoreType", KeyStore.getDefaultType());
157-
}
158-
trustManagerAlgorithm = Security.getProperty("ssl.TrustManagerFactory.algorithm");
159-
160-
if (trustManagerAlgorithm == null) {
161-
trustManagerAlgorithm = "SunX509";
162-
}
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);
16357
}
16458
}
59+
60+
private static class SingletonHolder {
61+
public static final SslUtils instance = new SslUtils();
62+
}
16563

64+
public static SslUtils getInstance() {
65+
return SingletonHolder.instance;
66+
}
67+
68+
public SSLContext getSSLContext(boolean acceptAnyCertificate) throws GeneralSecurityException, IOException {
69+
return acceptAnyCertificate? looseTrustManagerSSLContext: SSLContext.getDefault();
70+
}
16671
}

0 commit comments

Comments
 (0)