-
Notifications
You must be signed in to change notification settings - Fork 3.9k
okhttp: use new APIs for configuring TLS whenever possible (Android Q+) #6912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
okhttp: use new APIs for configuring TLS whenever possible (Android Q+) #6912
Conversation
c47f4dd
to
f035d6e
Compare
f035d6e
to
aa9b7ec
Compare
b005895
to
0e6e2d0
Compare
…ypt is bundled with apps.
…tApplicationProtocols is not available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
com.google.android.gms.org.conscrypt on R should support the new API. I'm concerned to hear it doesn't. We should probably discuss, since there may be something that invalidated your test.
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
Note: we'd ideally not do this work in the Android Platform and instead use JdkAlpnPlatform. We should be thinking about swapping to the new SNI APIs as well. |
With some testing @voidzcy confirmed that Conscrypt was truly not throwing UnsupportedOperationException for getApplicationProtocols and also failing to do ALPN. On investigating, it appears it is simply because Conscrypt ignores the ALPN SSLParameters on Android: google/conscrypt#832 . This feels like it will be a thorn in our side for a good while. We will want to figure out a workaround if we can. From the code it looks like we can getSSLParamaters after calling setSSLParameters to see if the ALPN configuration is still present. |
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
sslSocket.setSSLParameters(sslParams); | ||
// Check protocol configuration through SSLParameters succeeds. If not, fall back to | ||
// configure with the old reflective method. | ||
// Workaround for Conscrypt issue: https://github.com/google/conscrypt/issues/832 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As written, this is not working around Conscrypt. This is checking whether the API is supported in a Conscrypt-compatible way. For this to be a workaround we would need to do the does-GET_APPLICATION_PROTOCOL-throw check before this, or we would need to say "we aren't checking getApplicationProtocol as a Conscrypt workaround".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you are really referring to SSLParameters#getApplicationProtocols()
instead of SSLSocket#getApplicationProtocol()
here. The former never throw (we aren't doing the latter during configuration). The getApplicationProtocols()
check really is to see if protocols configured on SSLParameters
are propagated to SSLSocket
, which is only because Conscrypt on Android does this incorrectly. Normally we wouldn't need to do this. Isn't this a workaround?
I agree now it looks more like checking whether the API is supported in a Conscrypt-compatible way due to using duck-type method calls. After changing to normal Method
and only do this when APIs are available, it would be clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring to SSLSocket.getApplicationProtocol().
An API was added in Java 9 and Android API 27 to configure ALPN. But that API is implemented by multiple implementations. So we can't assume that if the API is there that it works. I was suggesting to use SSLSocket.getApplicationProtocol()
before any negotiation has occurred to see if ALPN is supported in this fashion. If the method throws UnsupportedOperationException
then the implementation does not support that API and we should try other APIs. That is the way we decided to handle it in Netty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. That was what we used to find the Conscrypt bug. Due to that bug, even the invocation of SSLSocket.getApplicationProtocol()
before any negotiation has occurred does not throw UnsupportedOperationException
, ALPN is still not configured correctly. Here, we are working around that bug. Consequently, this check also helps us verifying the SSLSocket is configured with ALPN, isn't it? So do we still need the does-GET_APPLICATION_PROTOCOL-throw check?
Addressed all the comments and tested locally with different Conscrypt settings. PTAL. Thanks. |
…). It cannot be verified now as we are using reflections loaded statically.
… if setApplicationProtocols() can be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java
Outdated
Show resolved
Hide resolved
…+) (grpc#6912) Use new APIs for configuring TLS in Android environment. Starting from Android 29, there is a new set of public APIs for configuring ALPN (and starting from Android 24, there is API for enabling SNI). This change migrates to use these new APIs whenever possible. Only fallback to call the old hidden APIs if new ones do not exist (or do not work).
…grpc#6959) * Revert "okhttp: Skip enabling SNI and session ticket for fake/test host names (grpc#6949)" This reverts commit eb8e314. * Revert "okhttp: use new APIs for configuring TLS whenever possible (Android Q+) (grpc#6912)" This reverts commit 5803dfd.
Use Android Q+'s new APIs for configuring TLS whenever possible. The new APIs are
SSLSockets#isSupportedSocket(SSLSocket)
SSLSockets#setUseSessionTickets(SSLSocket, boolean)
SSLParameters#setApplicationProtocols (String[])
SSLSocket#getApplicationProtocol()
Calling the hidden methods
SSLSocket#setAlpnProtocols(...)
andSSLSocket#getAlpnProtocol()
in Android R throws anUnsupportedAppUsage
exception in internal version of Android R (annotated on Android's Conscrypt). This PR migrates to invoke new public APIs for configuring Conscrypt whenever possible. Only fall back to invoke the old reflective APIs in when new APIs are not available (and for work around Conscrypt's bug as mentioned in #6912 (comment)).There is also a new API for enabling SNI on
SSLParameters
introduced from Android 24. It requires constructingSNIHostName
(also introduced from API 24). This PR also migrates to use that whenever possible.I tested code execution for configuring Conscrypt under different environments:
(Note
SSLSockets#setUseSessionTickets(...)
is only supported forcom.android.org.conscrypt
sockets).