Reputation: 40500
I'm using the Async Apache HttpClient (CloseableHttpAsyncClient) to connect to a server but I run into the following exception:
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at org.apache.http.concurrent.BasicFuture.failed(BasicFuture.java:130)
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.failed(DefaultClientExchangeHandlerImpl.java:258)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.exception(HttpAsyncRequestExecutor.java:123)
at org.apache.http.impl.nio.client.InternalIODispatch.onException(InternalIODispatch.java:68)
at org.apache.http.impl.nio.client.InternalIODispatch.onException(InternalIODispatch.java:37)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:124)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:159)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:338)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:316)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:277)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:105)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:584)
at java.lang.Thread.run(Thread.java:695)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Handshaker.java:1015)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:485)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(SSLEngineImpl.java:1108)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(SSLEngineImpl.java:1080)
at javax.net.ssl.SSLEngine.wrap(SSLEngine.java:452)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doWrap(SSLIOSession.java:220)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:254)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:391)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:119)
... 7 more
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1508)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:243)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1209)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:135)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Handshaker.java:533)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Handshaker.java:952)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doRunTask(SSLIOSession.java:238)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:276)
... 9 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1188)
... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
... 22 more
Since this is a test server I just want CloseableHttpAsyncClient to ignore all SSL errors. I know how to do this using the non-async version of HttpClient (this has been answered here for example) but I cannot get this to work using the async version.
I've tried the following:
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] certificate, String authType) {
return true;
}
};
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
} catch (Exception e) {
// Handle error
}
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLContext(sslContext).build();
but it doesn't work. Does anyone know how to solve this?
Upvotes: 1
Views: 6266
Reputation: 40500
Actually the code that I provided in my question worked. The problem was that I was using Unirest (which uses Apache HttpClient under the hood) and had configured it like this:
Unirest.setAsyncHttpClient(createHttpAsyncClient(CONNECTION_TIMEOUT, SOCKET_TIMEOUT));
Unirest.setTimeouts(CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
The problem was that "setTimeouts" overrode the configuration I made in createHttpAsyncClient
without any indication. Changing to
Unirest.setTimeouts(CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
Unirest.setAsyncHttpClient(createHttpAsyncClient(CONNECTION_TIMEOUT, SOCKET_TIMEOUT));
made everything work.
So if someone else has the same problem with plain Async Apache HTTPClient then the code to make it trust all certificates is the following:
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] certificate, String authType) {
return true;
}
};
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
} catch (Exception e) {
// Handle error
}
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLContext(sslContext).build();
Upvotes: 5
Reputation: 27528
I suspect this problem has nothing to do with hostname verification. SSL handshake likely fails much earlier, before an SSL session could be negotiated. There can be various reasons for such failure, SSL protocol version mismatch being most likely. You should run your application with SSL debug log activated (using -Djavax.net.debug=all
system property) and analyze the log output
Upvotes: 0