Reputation: 935
Experiencing an error when connecting a Java HTTP client code with a WebSphere server URL. The test throws an SSL handshake error message:
The code deploy was tested with Java7 and Java8:
java -Djavax.net.ssl.keyStore=mykey.jks -Djdk.tls.client.protocols=TLSv1.2 -Djavax.net.debug=ssl,handshake postHTTPWAS
Log file:
..
jdk.tls.client.protocols is defined as TLSv1.2
SSLv3 protocol was requested but was not enabled
.. Extension server_name, server_name: [type=host_name (0), value=myhost.domain.com]
***
main, WRITE: TLSv1 Handshake, length = 155
main, received EOFException: error
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
main, SEND TLSv1.2 ALERT: fatal, description = handshake_failure
main, WRITE: TLSv1.2 Alert, length = 2
main, called closeSocket()
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
The java.security settings of the JRE are configured as followed:
...
jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
jdk.tls.disabledAlgorithms=SSLv3
jdk.certpath.disabledAlgorithms=SSLv3
com.ibm.jsse2.disableSSLv3=true
Questions:
1) Why does the SSL trace show a reference to SSLv3, a protocol that was logically disabled at the client security setup?
2) What is the root error of the SSLHandshakeException?
3) Is it possible to enable TLSv1.2 as a default choice for all HTTPS client connections and which is the right system property to set it?
Upvotes: 1
Views: 7270
Reputation: 935
I've isolated the error.
The newer releases of WAS application server (full) expect that the client will connect with TLSv1.2. For manual Java JRE invocation use the parameter -Dhttps.protocols=TLSv1.2, shown below:
/opt/java8/ibm-java-x86_64-80/bin/javac SSLTest.java && /opt/java8/ibm-java-x86_64-80/jre/bin/java -Dhttps.protocols=TLSv1.2 SSLTest
For Apache HTTPS clients (> V.4.5.2), I added a few additional sections, to get the HTTPS connected with TLSv1.2. Both connections now are working OK.
// for TLSv1.2 add:
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import javax.net.ssl.SSLContext;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;
import org.apache.http.ssl.SSLContexts;
//Set the https use TLSv1.2
private static Registry<ConnectionSocketFactory> getRegistry() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext sslContext = SSLContexts.custom().build();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
}
// for TLSv1.2 use:
PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(getRegistry());
clientConnectionManager.setMaxTotal(100);
clientConnectionManager.setDefaultMaxPerRoute(20);
HttpClient client = HttpClients.custom().setConnectionManager(clientConnectionManager).build();
Upvotes: 3