diff options
author | Adam Vartanian <flooey@google.com> | 2019-03-22 11:57:18 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-03-22 11:57:18 -0700 |
commit | 38cdd2e75ecd31b6c5de29ccf9c357626456ee2f (patch) | |
tree | e2aab8860d5da24d381fa23203ac751badfeb149 | |
parent | a8fdc956d4f16e0ee0eb012cee3fa4a026983e93 (diff) | |
parent | 7c89c012daeaaa7b4634008d3e0243697bb69222 (diff) | |
download | okhttp-38cdd2e75ecd31b6c5de29ccf9c357626456ee2f.tar.gz |
Merge "Use public API for Conscrypt features" am: daf92ccb09 am: d980250445
am: 7c89c012da
Change-Id: Ie29b1c987f7de1f85ebdafad68877af6016e4d70
-rw-r--r-- | Android.bp | 6 | ||||
-rw-r--r-- | android/src/main/java/com/squareup/okhttp/internal/Platform.java | 60 | ||||
-rw-r--r-- | repackaged/android/src/main/java/com/android/okhttp/internal/Platform.java | 60 |
3 files changed, 106 insertions, 20 deletions
@@ -39,6 +39,8 @@ java_library { no_standard_libs: true, libs: [ "core-all", + // TODO(b/129126571): Depend on Conscrypt stubs instead + "conscrypt", ], system_modules: "core-all-system-modules", java_version: "1.7", @@ -63,6 +65,8 @@ java_library { no_standard_libs: true, libs: [ "core-all", + // TODO(b/129126571): Depend on Conscrypt stubs instead + "conscrypt", ], system_modules: "core-all-system-modules", java_version: "1.7", @@ -80,6 +84,8 @@ java_library { no_standard_libs: true, libs: [ "core-all", + // TODO(b/129126571): Depend on Conscrypt stubs instead + "conscrypt", ], dex_preopt: { enabled: false, diff --git a/android/src/main/java/com/squareup/okhttp/internal/Platform.java b/android/src/main/java/com/squareup/okhttp/internal/Platform.java index f4828f2..9edd58e 100644 --- a/android/src/main/java/com/squareup/okhttp/internal/Platform.java +++ b/android/src/main/java/com/squareup/okhttp/internal/Platform.java @@ -16,6 +16,7 @@ */ package com.squareup.okhttp.internal; +import android.net.ssl.SSLSockets; import com.squareup.okhttp.Protocol; import com.squareup.okhttp.internal.tls.RealTrustRootIndex; import com.squareup.okhttp.internal.tls.TrustRootIndex; @@ -25,8 +26,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; @@ -74,6 +79,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); @@ -101,22 +113,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); } /** @@ -127,6 +148,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; @@ -200,6 +228,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 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 |