Skip to content

Commit 40dda61

Browse files
committed
Move the authority verification logic using hostname verifier and trust manager to a separate method
1 parent 5f8ca63 commit 40dda61

File tree

1 file changed

+60
-67
lines changed

1 file changed

+60
-67
lines changed

okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java

Lines changed: 60 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,7 @@ protected boolean removeEldestEntry(Map.Entry<String, T> eldest) {
259259
}
260260

261261
@GuardedBy("lock")
262-
private final Map<String, Boolean> hostnameVerificationResults = new LruCache<>();
263-
@GuardedBy("lock")
264-
private final Map<String, Status> peerVerificationResults = new LruCache<>();
262+
private final Map<String, Status> authorityVerificationResults = new LruCache<>();
265263

266264
@GuardedBy("lock")
267265
private final InUseStateAggregator<OkHttpClientStream> inUseState =
@@ -522,82 +520,77 @@ void streamReadyToStart(OkHttpClientStream clientStream, String authority) {
522520
setInUse(clientStream);
523521
} else {
524522
if (!authority.equals(defaultAuthority)) {
525-
Boolean hostnameVerificationResult;
526-
if (hostnameVerificationResults.containsKey(authority)) {
527-
hostnameVerificationResult = hostnameVerificationResults.get(authority);
523+
Status authorityVerificationResult;
524+
if (authorityVerificationResults.containsKey(authority)) {
525+
authorityVerificationResult = authorityVerificationResults.get(authority);
528526
} else {
529-
hostnameVerificationResult = hostnameVerifier.verify(
530-
authority, ((SSLSocket) socket).getSession());
531-
hostnameVerificationResults.put(authority, hostnameVerificationResult);
532-
if (!hostnameVerificationResult && !enablePerRpcAuthorityCheck) {
533-
log.log(Level.WARNING, String.format("HostNameVerifier verification failed for "
534-
+ "authority '%s'. This will be an error in the future.",
535-
authority));
536-
}
527+
authorityVerificationResult = verifyAuthority(authority);
528+
authorityVerificationResults.put(authority, authorityVerificationResult);
537529
}
538-
if (!hostnameVerificationResult) {
530+
if (!authorityVerificationResult.isOk()) {
539531
if (enablePerRpcAuthorityCheck) {
540532
clientStream.transportState().transportReportStatus(
541-
Status.UNAVAILABLE.withDescription(String.format(
542-
"HostNameVerifier verification failed for authority '%s'",
543-
authority)),
544-
RpcProgress.PROCESSED, true, new Metadata());
533+
authorityVerificationResult, RpcProgress.PROCESSED, true, new Metadata());
545534
return;
546535
}
547536
}
548-
Status peerVerificationStatus = null;
549-
if (peerVerificationResults.containsKey(authority)) {
550-
peerVerificationStatus = peerVerificationResults.get(authority);
551-
} else {
552-
// The status is trivially assigned in this case, but we are still making use of the
553-
// cache to keep track that a warning log had been logged for the authority when
554-
// enablePerRpcAuthorityCheck is false. When we permanently enable the feature, the
555-
// status won't need to be cached for case of x509TrustManager == null.
556-
if (x509TrustManager == null) {
557-
peerVerificationStatus = Status.UNAVAILABLE.withDescription(
558-
String.format("Could not verify authority '%s' for the rpc with no "
559-
+ "X509TrustManager available",
560-
authority));
561-
} else if (x509ExtendedTrustManagerClass.isInstance(x509TrustManager)) {
562-
try {
563-
Certificate[] peerCertificates = sslSession.getPeerCertificates();
564-
X509Certificate[] x509PeerCertificates =
565-
new X509Certificate[peerCertificates.length];
566-
for (int i = 0; i < peerCertificates.length; i++) {
567-
x509PeerCertificates[i] = (X509Certificate) peerCertificates[i];
568-
}
569-
checkServerTrustedMethod.invoke(x509TrustManager, x509PeerCertificates,
570-
"RSA", new SslSocketWrapper((SSLSocket) socket, authority));
571-
peerVerificationStatus = Status.OK;
572-
} catch (SSLPeerUnverifiedException | InvocationTargetException
573-
| IllegalAccessException e) {
574-
peerVerificationStatus = Status.UNAVAILABLE.withCause(e).withDescription(
575-
"Peer verification failed");
576-
}
577-
if (peerVerificationStatus != null) {
578-
peerVerificationResults.put(authority, peerVerificationStatus);
579-
}
537+
}
538+
startStream(clientStream);
539+
}
540+
}
541+
542+
private Status verifyAuthority(String authority) {
543+
Status authorityVerificationResult;
544+
if (hostnameVerifier.verify(
545+
authority, ((SSLSocket) socket).getSession())) {
546+
authorityVerificationResult = Status.OK;
547+
} else {
548+
authorityVerificationResult = Status.UNAVAILABLE.withDescription(String.format(
549+
"HostNameVerifier verification failed for authority '%s'",
550+
authority));
551+
}
552+
if (!authorityVerificationResult.isOk() && !enablePerRpcAuthorityCheck) {
553+
log.log(Level.WARNING, String.format("HostNameVerifier verification failed for "
554+
+ "authority '%s'. This will be an error in the future.",
555+
authority));
556+
}
557+
if (authorityVerificationResult.isOk()) {
558+
// The status is trivially assigned in this case, but we are still making use of the
559+
// cache to keep track that a warning log had been logged for the authority when
560+
// enablePerRpcAuthorityCheck is false. When we permanently enable the feature, the
561+
// status won't need to be cached for case when x509TrustManager is null.
562+
if (x509TrustManager == null) {
563+
authorityVerificationResult = Status.UNAVAILABLE.withDescription(
564+
String.format("Could not verify authority '%s' for the rpc with no "
565+
+ "X509TrustManager available",
566+
authority));
567+
} else if (x509ExtendedTrustManagerClass.isInstance(x509TrustManager)) {
568+
try {
569+
Certificate[] peerCertificates = sslSession.getPeerCertificates();
570+
X509Certificate[] x509PeerCertificates =
571+
new X509Certificate[peerCertificates.length];
572+
for (int i = 0; i < peerCertificates.length; i++) {
573+
x509PeerCertificates[i] = (X509Certificate) peerCertificates[i];
580574
}
575+
checkServerTrustedMethod.invoke(x509TrustManager, x509PeerCertificates,
576+
"RSA", new SslSocketWrapper((SSLSocket) socket, authority));
577+
authorityVerificationResult = Status.OK;
578+
} catch (SSLPeerUnverifiedException | InvocationTargetException
579+
| IllegalAccessException e) {
580+
authorityVerificationResult = Status.UNAVAILABLE.withCause(e).withDescription(
581+
"Peer verification failed");
581582
}
582-
if (peerVerificationStatus != null && !peerVerificationStatus.isOk()) {
583-
if (enablePerRpcAuthorityCheck) {
584-
clientStream.transportState().transportReportStatus(
585-
peerVerificationStatus, RpcProgress.PROCESSED, true, new Metadata());
586-
return;
587-
} else {
588-
if (peerVerificationStatus.getCause() != null) {
589-
log.log(Level.WARNING, peerVerificationStatus.getDescription()
590-
+ ". This will be an error in the future.",
591-
peerVerificationStatus.getCause());
592-
} else {
593-
log.log(Level.WARNING, peerVerificationStatus.getDescription()
594-
+ ". This will be an error in the future.");
595-
}
596-
}
583+
if (authorityVerificationResult.getCause() != null) {
584+
log.log(Level.WARNING, authorityVerificationResult.getDescription()
585+
+ ". This will be an error in the future.",
586+
authorityVerificationResult.getCause());
587+
} else {
588+
log.log(Level.WARNING, authorityVerificationResult.getDescription()
589+
+ ". This will be an error in the future.");
597590
}
598591
}
599-
startStream(clientStream);
600592
}
593+
return authorityVerificationResult;
601594
}
602595

603596
@SuppressWarnings("GuardedBy")

0 commit comments

Comments
 (0)