diff options
| author | Adam Vartanian <flooey@google.com> | 2019-03-19 09:36:23 +0000 |
|---|---|---|
| committer | Adam Vartanian <flooey@google.com> | 2019-03-22 13:28:08 +0000 |
| commit | ed34271096dedb7af95976e27a94826a2f653cc1 (patch) | |
| tree | e2aab8860d5da24d381fa23203ac751badfeb149 /repackaged/android | |
| parent | 6858021441b5c56decd5e3679106db22f9f21e57 (diff) | |
| download | platform_external_okhttp-ed34271096dedb7af95976e27a94826a2f653cc1.tar.gz platform_external_okhttp-ed34271096dedb7af95976e27a94826a2f653cc1.tar.bz2 platform_external_okhttp-ed34271096dedb7af95976e27a94826a2f653cc1.zip | |
Use public API for Conscrypt features
Historically, extra Conscrypt features were enabled by calling hidden
APIs. We now have public APIs for these, so use those instead.
Continue calling the non-public APIs in most cases because older
versions of Conscrypt may be bundled with apps and third-party
SSLSocket providers may have taken advantage of our duck-typing to
enable compatibility with these features, but never call them when
dealing with a platform socket to ensure we can't break this with
Conscrypt module updates.
In future, we want to depend on Conscrypt stubs instead, but those
don't exist yet. b/129126571 tracks that work.
Test: cts -m CtsLibcoreTestCases
Test: cts -m CtsLibcoreOkHttpTestCases
Bug: 128280837
Change-Id: Id5a04a14ebe9737a85d3347a230132c151e1ec5a
Diffstat (limited to 'repackaged/android')
| -rw-r--r-- | repackaged/android/src/main/java/com/android/okhttp/internal/Platform.java | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/repackaged/android/src/main/java/com/android/okhttp/internal/Platform.java b/repackaged/android/src/main/java/com/android/okhttp/internal/Platform.java index 6ddff7e..f4505af 100644 --- a/repackaged/android/src/main/java/com/android/okhttp/internal/Platform.java +++ b/repackaged/android/src/main/java/com/android/okhttp/internal/Platform.java @@ -17,6 +17,7 @@ */ package com.android.okhttp.internal; +import android.net.ssl.SSLSockets; import com.android.okhttp.Protocol; import com.android.okhttp.internal.tls.RealTrustRootIndex; import com.android.okhttp.internal.tls.TrustRootIndex; @@ -26,8 +27,12 @@ import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; +import javax.net.ssl.SNIHostName; +import javax.net.ssl.SNIServerName; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509TrustManager; @@ -77,6 +82,13 @@ public class Platform { return INSTANCE_HOLDER.getAndSet(platform); } + // NOTE: Prior to Android Q, the standard way of accessing some Conscrypt features was to + // use reflection to call hidden APIs. Beginning in Q, there is public API for all of these + // features. We attempt to use the public API where possible, but also still call the + // hidden versions to continue to support old versions of Conscrypt that might be bundled with + // apps or third-party TLS providers that might have taken advantage of being able to + // duck-type their way into compatibility. For more background, see b/128280837. + /** setUseSessionTickets(boolean) */ private static final OptionalMethod<Socket> SET_USE_SESSION_TICKETS = new OptionalMethod<Socket>(null, "setUseSessionTickets", Boolean.TYPE); @@ -105,22 +117,31 @@ public class Platform { public void configureTlsExtensions( SSLSocket sslSocket, String hostname, List<Protocol> protocols) { - // Enable SNI and session tickets. + // All extensions here use both public API and reflective calls, see note above. + SSLParameters sslParams = sslSocket.getSSLParameters(); if (hostname != null) { - SET_USE_SESSION_TICKETS.invokeOptionalWithoutCheckedException(sslSocket, true); - SET_HOSTNAME.invokeOptionalWithoutCheckedException(sslSocket, hostname); + // Enable session tickets + if (SSLSockets.isSupportedSocket(sslSocket)) { + SSLSockets.setUseSessionTickets(sslSocket, true); + } else { + SET_USE_SESSION_TICKETS.invokeOptionalWithoutCheckedException(sslSocket, true); + } + // Enable SNI + sslParams.setServerNames( + Collections.<SNIServerName>singletonList(new SNIHostName(hostname))); + if (!isPlatformSocket(sslSocket)) { + SET_HOSTNAME.invokeOptionalWithoutCheckedException(sslSocket, hostname); + } } - // Enable ALPN. - boolean alpnSupported = SET_ALPN_PROTOCOLS.isSupported(sslSocket); - if (!alpnSupported) { - return; - } + // Enable ALPN, if necessary + sslParams.setApplicationProtocols(getProtocolIds(protocols)); - Object[] parameters = { concatLengthPrefixed(protocols) }; - if (alpnSupported) { + if (!isPlatformSocket(sslSocket) && SET_ALPN_PROTOCOLS.isSupported(sslSocket)) { + Object[] parameters = {concatLengthPrefixed(protocols)}; SET_ALPN_PROTOCOLS.invokeWithoutCheckedException(sslSocket, parameters); } + sslSocket.setSSLParameters(sslParams); } /** @@ -131,6 +152,13 @@ public class Platform { } public String getSelectedProtocol(SSLSocket socket) { + // This API was added in Android Q + try { + return socket.getApplicationProtocol(); + } catch (UnsupportedOperationException ignored) { + // The socket doesn't support this API, try the old reflective method + } + // This method was used through Android P, see note above boolean alpnSupported = GET_ALPN_SELECTED_PROTOCOL.isSupported(socket); if (!alpnSupported) { return null; @@ -204,6 +232,18 @@ public class Platform { return null; } + private static boolean isPlatformSocket(SSLSocket socket) { + return socket.getClass().getName().startsWith("com.android.org.conscrypt"); + } + + private static String[] getProtocolIds(List<Protocol> protocols) { + String[] result = new String[protocols.size()]; + for (int i = 0; i < protocols.size(); i++) { + result[i] = protocols.get(i).toString(); + } + return result; + } + /** * Returns the concatenation of 8-bit, length prefixed protocol names. * http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4 |
