Skip to content

okhttp 3.x thinks it is running on Java 9+ from Java 8u252 #6019

@jonatan-ivanov

Description

@jonatan-ivanov

The OkHttpClient.Builder has a deprecated method to inject SSLSocketFactory: OkHttpClient.Builder#sslSocketFactory(SSLSocketFactory)

This method is fetching the X509TrustManager via reflection.
This is not supported on Java 9+ (I guess JPMS restricts it).

From Java 8u252 (8u242 is fine), the Jdk9Platform is picked because the logic which picks the right platform is based on checking if certain methods exist via reflection and those methods were backported into Java 8 from 8u252: Jdk9Platform.java#L92-L94. This breaks the OkHttpClient.Builder#sslSocketFactory(SSLSocketFactory), it always throws an exception on 8u252.

Here is SSLParameters#setApplicationProtocols(String[]) in 8u252
While 8u242 does not contain it

And here is SSLSocket#getApplicationProtocol() in 8u252
While 8u242 does not contain it

Here's a test suite to demo the issue:

  • Both cases are ok on java 8u242
  • The first one (shouldCreateTheClientWithoutTheTrustManager) fails on 8u252
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;

class OkHttpJavaDetectionTest {
  @Test
  void shouldCreateTheClientWithoutTheTrustManager() throws NoSuchAlgorithmException {
    OkHttpClient client = new OkHttpClient.Builder()
      .sslSocketFactory(SSLContext.getDefault().getSocketFactory())
      .build();

    assertNotNull(client);
  }

  @Test
  void shouldCreateTheClientWitTheTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
    OkHttpClient client = new OkHttpClient.Builder()
      .sslSocketFactory(SSLContext.getDefault().getSocketFactory(), createTrustManager())
      .build();

    assertNotNull(client);
  }

  private X509TrustManager createTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
    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));
    }

    return (X509TrustManager) trustManagers[0];
  }
}

Here's the relevant section of the stacktrace:

java.lang.UnsupportedOperationException: clientBuilder.sslSocketFactory(SSLSocketFactory) not supported on JDK 9+

	at okhttp3.internal.platform.Jdk9Platform.trustManager(Jdk9Platform.java:77)
	at okhttp3.internal.platform.Platform.buildCertificateChainCleaner(Platform.java:177)
	at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.java:743)
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs infoMore information needed from reporter

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions