Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions src/main/java/com/ibm/cloud/sdk/core/http/HttpClientSingleton.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,13 @@ protected SSLSocket configureSocket(SSLSocket socket) throws IOException {
// Find the TLS protocols supported by this socket
List<String> supportedTlsNames = Arrays.asList(socket.getSupportedProtocols());
LOG.log(Level.FINEST, "Socket supported protocols {0}", supportedTlsNames);

// Get the union of MODERN_TLS_NAMES and the socket's supported protocols
List<String> protocolsToEnable = new ArrayList<>();
protocolsToEnable.addAll(supportedTlsNames);
protocolsToEnable.retainAll(MODERN_TLS_NAMES);
LOG.log(Level.FINEST, "Filtered protocols to enable {0}", protocolsToEnable);

socket.setEnabledProtocols(protocolsToEnable.toArray(new String[]{}));
return socket;
}
Expand Down Expand Up @@ -304,36 +306,41 @@ private OkHttpClient setLoggingLevel(OkHttpClient client, LoggingLevel loggingLe
}

/**
* Specifically enable all TLS protocols. See: https://github.com/watson-developer-cloud/java-sdk/issues/610
* Set the required TLS-related configuration on "builder".
*
* @param builder the {@link OkHttpClient} builder.
* @param builder the {@link OkHttpClient} Builder instance
*/
public static void setupTLSProtocol(final OkHttpClient.Builder builder) {
try {
// Create a trust manager with default behavior.
// Specifically, this means that we'll use a user-supplied truststore
// if the "javax.net.ssl.trustStore" system property is set,
// or the JVM's default truststore (cacerts) if not.
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}

X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

// On IBM JDKs this gets only TLSv1
SSLContext sslContext = SSLContext.getInstance("TLS");
// Next, we need to get the socket factory from the default SSLContext.
// We do this for two reasons:
// 1. We want our FilteredSSLSocketFactory instance to delegate to this "default" socket factory.
// 2. We want this default socket factory to use a key manager with default behavior.
// Specifically, this means that the key manager will manage a user-supplied keystore
// if the "javax.net.ssl.keyStore" system property is set,
// or an "empty" key manager if not.
SSLContext defaultContext = SSLContext.getDefault();
SSLSocketFactory sslSocketFactory = new FilteredSSLSocketFactory(defaultContext.getSocketFactory());

sslContext.init(null, new TrustManager[] { trustManager }, null);
SSLSocketFactory sslSocketFactory = new FilteredSSLSocketFactory(sslContext.getSocketFactory());
builder.sslSocketFactory(sslSocketFactory, trustManager);
// Now set the ssl socket factory and trust manager on the client builder.
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagers[0]);

} catch (NoSuchAlgorithmException e) {
LOG.log(Level.SEVERE, "The cryptographic algorithm requested is not available in the environment.", e);
} catch (KeyStoreException e) {
LOG.log(Level.SEVERE, "Error using the keystore.", e);
} catch (KeyManagementException e) {
LOG.log(Level.SEVERE, "Error initializing the SSL Context.", e);
}
}

Expand Down