Skip to content
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

ok-http: Per-rpc call option authority verification #11754

Open
wants to merge 35 commits into
base: master
Choose a base branch
from

Conversation

kannanjgithub
Copy link
Contributor

No description provided.

Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need to look at the core of it, but the shape looks right. These comments are mostly surface-level.

@Override
public SSLParameters getSSLParameters() {
SSLParameters sslParameters = sslSocket.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The endpointIdentificationAlgorithm in sslParameters of the real sslSocket is null. In the case of Netty we are setting it here

sslParams.setEndpointIdentificationAlgorithm("HTTPS");
for the handshake but not for Okhttp.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But changing here isn't actually changing it for the connection. I think we're generally depending on the HostnameVerifier instead. setEndpointIdentificationAlgorithm() was added in Android API level 24. We're claiming to support API level 21 (although we should change that to 23)

I'm really bothered by the lack of failure building this. AnimalSniffer missed some things at times, but it seems to be completely broken right now. Running with --console=plain I see animalsnifferMain is SKIPPED. Digging deeper, it seems we're missing @signature in the version so it hasn't been running.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the setting endpoint algorithm in the wrapper SslSocket was for causing the hostname check to occur when we do the per rpc check using the X509ExrendedTrustManager. Do we not want that to happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as we don't have a minimum API level of 24 we can't check authority using X509ExtendedTrustManager. Should we then remove these changes and use only HostnameVerifier, and disallow per rpc authority override if one is not provided?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline and understood we let the same checks during handshake apply during RPC and removed calling setEndpointIdentificationAlgorithm.

@kannanjgithub
Copy link
Contributor Author

Yet to make the changes to use X509ExtendedTrustManager only via reflection if it is available in the class loader.

@kannanjgithub
Copy link
Contributor Author

kannanjgithub commented Jan 13, 2025

Yet to make the changes to use X509ExtendedTrustManager only via reflection if it is available in the class loader.

Done.

@kannanjgithub
Copy link
Contributor Author

Moved the authority verification from OkHttpClientTransport.newStream down to the point just before sending the headers over the network so any overwrites to the authority gets seen.

@ejona86 ejona86 self-requested a review February 26, 2025 00:39
Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to look at it more, but sending what I have.

@@ -45,7 +45,7 @@ dependencies {
protobuf {
protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.70.0" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -23,6 +23,7 @@
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.ServerCallStreamObserver;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert changes to this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

throws GeneralSecurityException {
InputStream rootCertsStream = new ByteArrayInputStream(rootCerts);
try {
return io.grpc.internal.CertificateUtils.createTrustManager(rootCertsStream);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete io.grpc.internal.CertificateUtils.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -389,13 +442,14 @@ public void ping(final PingCallback callback, Executor executor) {
}

@Override
public OkHttpClientStream newStream(
public ClientStream newStream(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (tlsCreds.getTrustManagers() != null) {
tm = tlsCreds.getTrustManagers().toArray(new TrustManager[0]);
} else if (tlsCreds.getRootCertificates() != null) {
tm = CertificateUtils.createTrustManager(tlsCreds.getRootCertificates());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to create a trust manager each RPC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (hostnameVerifier != null
&& socket instanceof SSLSocket
&& !hostnameVerifier.verify(authority,
((SSLSocket) socket).getSession())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unwrap this line. It shouldn't be at the same indentation level as the previous line, because the verify() method has wrapped, but it didn't need to be wrapped anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (goAwayStatus != null) {
clientStream.transportState().transportReportStatus(
goAwayStatus, RpcProgress.MISCARRIED, true, new Metadata());
} else if (streams.size() >= maxConcurrentStreams) {
pendingStreams.add(clientStream);
setInUse(clientStream);
} else {
if (hostnameVerifier != null
&& socket instanceof SSLSocket
&& !hostnameVerifier.verify(authority,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to do hostname verification each RPC. This should be part of the peerVerificationResults cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

# Conflicts:
#	core/src/main/java/io/grpc/internal/CertificateUtils.java
#	okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants