Skip to content

Commit

Permalink
Some changes based on similar comments in the authority check for Net…
Browse files Browse the repository at this point in the history
…ty PR.
  • Loading branch information
kannanjgithub committed Jan 17, 2025
1 parent ce800f7 commit 649f53c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 57 deletions.
2 changes: 1 addition & 1 deletion api/src/main/java/io/grpc/ManagedChannelRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,4 @@ public ProviderNotFoundException(String msg) {
super(msg);
}
}
}
}
83 changes: 33 additions & 50 deletions okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,11 @@ class OkHttpClientTransport implements ConnectionClientTransport, TransportExcep
private static final Logger log = Logger.getLogger(OkHttpClientTransport.class.getName());
private static final String GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK =
"GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK";
static boolean enablePerRpcAuthorityCheck =
GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false);
private final ChannelCredentials channelCredentials;
private Socket sock;
private SSLSession sslSession;
private final Logger logger = Logger.getLogger(OkHttpClientTransport.class.getName());

private static Map<ErrorCode, Status> buildErrorCodeToStatusMap() {
Map<ErrorCode, Status> errorToStatus = new EnumMap<>(ErrorCode.class);
Expand Down Expand Up @@ -179,9 +180,8 @@ private static Map<ErrorCode, Status> buildErrorCodeToStatusMap() {
} catch (ClassNotFoundException e) {
// Per-rpc authority override via call options will be disallowed.
} catch (NoSuchMethodException e) {
// Should never happen.
Logger.getLogger(OkHttpClientTransport.class.getName()).warning("Method checkServerTrusted "
+ "not found in javax.net.ssl.X509ExtendedTrustManager");
// Should never happen since X509ExtendedTrustManager was introduced in Android API level 24
// along with checkServerTrusted.
}
}

Expand Down Expand Up @@ -246,13 +246,13 @@ private static Map<ErrorCode, Status> buildErrorCodeToStatusMap() {
private final boolean useGetForSafeMethods;
@GuardedBy("lock")
private final TransportTracer transportTracer;
private final LinkedHashMap<String, Status> peerVerificationResults =
private final Map<String, Status> peerVerificationResults = Collections.synchronizedMap(
new LinkedHashMap<String, Status>() {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Status> eldest) {
return size() > 100;
}
};
});

@GuardedBy("lock")
private final InUseStateAggregator<OkHttpClientStream> inUseState =
Expand Down Expand Up @@ -453,69 +453,52 @@ public ClientStream newStream(
if (hostnameVerifier != null && socket instanceof SSLSocket
&& !hostnameVerifier.verify(callOptions.getAuthority(),
((SSLSocket) socket).getSession())) {
if (GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false)) {
if (enablePerRpcAuthorityCheck) {
return new FailingClientStream(Status.UNAVAILABLE.withDescription(
String.format("HostNameVerifier verification failed for authority '%s'",
callOptions.getAuthority())), tracers);
}
logger.warning(String.format("HostNameVerifier verification failed for authority '%s'.",
callOptions.getAuthority()));
}
if (socket instanceof SSLSocket && callOptions.getAuthority() != null
&& channelCredentials != null && channelCredentials instanceof TlsChannelCredentials) {
Status peerVerificationStatus = null;
if (peerVerificationResults.containsKey(callOptions.getAuthority())) {
peerVerificationStatus = peerVerificationResults.get(callOptions.getAuthority());
} else {
TrustManager x509ExtendedTrustManager = null;
boolean warningLogged = false;
TrustManager x509ExtendedTrustManager;
try {
x509ExtendedTrustManager = x509ExtendedTrustManagerClass != null
? getX509ExtendedTrustManager((TlsChannelCredentials) channelCredentials) : null;
} catch (GeneralSecurityException e) {
if (GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false)) {
return new FailingClientStream(Status.UNAVAILABLE.withDescription(
"Failure getting X509ExtendedTrustManager from TlsCredentials").withCause(e),
tracers);
}
logger.warning(String.format("Failure getting X509ExtendedTrustManager from "
+ "TlsCredentials due to: %s", e.getMessage()));
warningLogged = true;
}
if (x509ExtendedTrustManager == null) {
if (GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false)) {
return new FailingClientStream(Status.UNAVAILABLE.withDescription(
"Can't allow authority override in rpc when X509ExtendedTrustManager is not "
+ "available"), tracers);
}
if (!warningLogged) {
logger.warning("Authority override set for rpc when X509ExtendedTrustManager is not "
+ "available.");
}
} else {
try {
Certificate[] peerCertificates = sslSession.getPeerCertificates();
X509Certificate[] x509PeerCertificates = new X509Certificate[peerCertificates.length];
for (int i = 0; i < peerCertificates.length; i++) {
x509PeerCertificates[i] = (X509Certificate) peerCertificates[i];
if (x509ExtendedTrustManager == null) {
if (GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false)) {
return new FailingClientStream(Status.UNAVAILABLE.withDescription(
"Can't allow authority override in rpc when X509ExtendedTrustManager is not "
+ "available"), tracers);
}
// Should never happen
if (checkServerTrustedMethod == null) {
peerVerificationStatus = Status.UNAVAILABLE.withDescription(
"Method checkServerTrusted not found in "
+ "javax.net.ssl.X509ExtendedTrustManager");
} else {
} else {
try {
Certificate[] peerCertificates = sslSession.getPeerCertificates();
X509Certificate[] x509PeerCertificates = new X509Certificate[peerCertificates.length];
for (int i = 0; i < peerCertificates.length; i++) {
x509PeerCertificates[i] = (X509Certificate) peerCertificates[i];
}
checkServerTrustedMethod.invoke(x509ExtendedTrustManager, x509PeerCertificates,
"RSA", new SslSocketWrapper((SSLSocket) socket, callOptions.getAuthority()));
peerVerificationStatus = Status.OK;
} catch (SSLPeerUnverifiedException | InvocationTargetException
| IllegalAccessException e) {
peerVerificationStatus = Status.UNAVAILABLE.withDescription(
String.format("Failure in verifying authority '%s' against peer during rpc",
callOptions.getAuthority())).withCause(e);
}
} catch (SSLPeerUnverifiedException | InvocationTargetException
| IllegalAccessException e) {
peerVerificationStatus = Status.UNAVAILABLE.withDescription(
String.format("Failure in verifying authority '%s' against peer during rpc",
callOptions.getAuthority())).withCause(e);
peerVerificationResults.put(callOptions.getAuthority(), peerVerificationStatus);
}
} catch (GeneralSecurityException e) {
if (GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false)) {
return new FailingClientStream(Status.UNAVAILABLE.withDescription(
"Failure getting X509ExtendedTrustManager from TlsCredentials").withCause(e),
tracers);
}
peerVerificationResults.put(callOptions.getAuthority(), peerVerificationStatus);
}
}
if (peerVerificationStatus != null && !peerVerificationStatus.isOk()) {
Expand Down Expand Up @@ -1610,7 +1593,7 @@ public void alternateService(int streamId, String origin, ByteString protocol, S
/**
* SSLSocket wrapper that provides a fake SSLSession for handshake session.
*/
static class SslSocketWrapper extends NoopSslSocket {
static final class SslSocketWrapper extends NoopSslSocket {

private final SSLSession sslSession;
private final SSLSocket sslSocket;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ public void perRpcAuthoritySpecified_hostnameVerification_SslSocket_successCase(
@Test
public void perRpcAuthoritySpecified_hostnameVerification_SslSocket_failureCase()
throws Exception {
System.setProperty("GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK", "true");
OkHttpClientTransport.enablePerRpcAuthorityCheck = true;
try {
startTransport(
DEFAULT_START_STREAM_ID, null, true, null,
Expand All @@ -833,7 +833,7 @@ public void perRpcAuthoritySpecified_hostnameVerification_SslSocket_failureCase(
+ "cause=null}");
shutdownAndVerify();
} finally {
System.clearProperty("GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK");
OkHttpClientTransport.enablePerRpcAuthorityCheck = false;
}
}

Expand Down
11 changes: 7 additions & 4 deletions okhttp/src/test/java/io/grpc/okhttp/TlsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;

import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
Expand All @@ -69,6 +71,7 @@

/** Verify OkHttp's TLS integration. */
@RunWith(JUnit4.class)
@IgnoreJRERequirement
public class TlsTest {
@Rule
public final GrpcCleanupRule grpcCleanupRule = new GrpcCleanupRule();
Expand Down Expand Up @@ -110,7 +113,7 @@ public void basicTls_succeeds() throws Exception {

@Test
public void perRpcAuthorityOverride_checkServerTrustedIsCalled() throws Exception {
System.setProperty("GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK", "true");
OkHttpClientTransport.enablePerRpcAuthorityCheck = true;
try {
ServerCredentials serverCreds;
try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
Expand All @@ -137,7 +140,7 @@ public void perRpcAuthorityOverride_checkServerTrustedIsCalled() throws Exceptio
SimpleRequest.getDefaultInstance());
assertThat(fakeTrustManager.checkServerTrustedCalled).isTrue();
} finally {
System.clearProperty("GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK");
OkHttpClientTransport.enablePerRpcAuthorityCheck = false;
}
}

Expand All @@ -148,7 +151,7 @@ public void perRpcAuthorityOverride_checkServerTrustedIsCalled() throws Exceptio
@Test
public void perRpcAuthorityOverride_tlsCreds_noX509ExtendedTrustManager_fails()
throws Exception {
System.setProperty("GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK", "true");
OkHttpClientTransport.enablePerRpcAuthorityCheck = true;
try {
ServerCredentials serverCreds;
try (InputStream serverCert = TlsTesting.loadCert("server1.pem");
Expand Down Expand Up @@ -180,7 +183,7 @@ public void perRpcAuthorityOverride_tlsCreds_noX509ExtendedTrustManager_fails()
+ "available");
}
} finally {
System.clearProperty("GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK");
OkHttpClientTransport.enablePerRpcAuthorityCheck = false;
}
}

Expand Down

0 comments on commit 649f53c

Please sign in to comment.