|
77 | 77 | import io.perfmark.PerfMark; |
78 | 78 | import java.io.EOFException; |
79 | 79 | import java.io.IOException; |
| 80 | +import java.lang.reflect.InvocationTargetException; |
| 81 | +import java.lang.reflect.Method; |
80 | 82 | import java.net.InetSocketAddress; |
81 | 83 | import java.net.Socket; |
82 | 84 | import java.net.URI; |
83 | 85 | import java.security.GeneralSecurityException; |
84 | 86 | import java.security.KeyStore; |
85 | 87 | import java.security.cert.Certificate; |
86 | | -import java.security.cert.CertificateException; |
87 | 88 | import java.security.cert.X509Certificate; |
88 | 89 | import java.util.Collections; |
89 | 90 | import java.util.Deque; |
|
116 | 117 | import javax.net.ssl.SSLSocketFactory; |
117 | 118 | import javax.net.ssl.TrustManager; |
118 | 119 | import javax.net.ssl.TrustManagerFactory; |
119 | | -import javax.net.ssl.X509ExtendedTrustManager; |
120 | 120 | import okio.Buffer; |
121 | 121 | import okio.BufferedSink; |
122 | 122 | import okio.BufferedSource; |
@@ -168,6 +168,23 @@ private static Map<ErrorCode, Status> buildErrorCodeToStatusMap() { |
168 | 168 | return Collections.unmodifiableMap(errorToStatus); |
169 | 169 | } |
170 | 170 |
|
| 171 | + private static Class<?> x509ExtendedTrustManagerClass; |
| 172 | + private static Method checkServerTrustedMethod; |
| 173 | + |
| 174 | + static { |
| 175 | + try { |
| 176 | + x509ExtendedTrustManagerClass = Class.forName("javax.net.ssl.X509ExtendedTrustManager"); |
| 177 | + checkServerTrustedMethod = x509ExtendedTrustManagerClass.getMethod("checkServerTrusted", |
| 178 | + X509Certificate[].class, String.class, Socket.class); |
| 179 | + } catch (ClassNotFoundException e) { |
| 180 | + // Per-rpc authority override via call options will be disallowed. |
| 181 | + } catch (NoSuchMethodException e) { |
| 182 | + // Should never happen. |
| 183 | + Logger.getLogger(OkHttpClientTransport.class.getName()).warning("Method checkServerTrusted " |
| 184 | + + "not found in javax.net.ssl.X509ExtendedTrustManager"); |
| 185 | + } |
| 186 | + } |
| 187 | + |
171 | 188 | private final InetSocketAddress address; |
172 | 189 | private final String defaultAuthority; |
173 | 190 | private final String userAgent; |
@@ -453,8 +470,8 @@ public ClientStream newStream( |
453 | 470 | TrustManager x509ExtendedTrustManager = null; |
454 | 471 | boolean warningLogged = false; |
455 | 472 | try { |
456 | | - x509ExtendedTrustManager = getX509ExtendedTrustManager( |
457 | | - (TlsChannelCredentials) channelCredentials); |
| 473 | + x509ExtendedTrustManager = x509ExtendedTrustManagerClass != null |
| 474 | + ? getX509ExtendedTrustManager((TlsChannelCredentials) channelCredentials) : null; |
458 | 475 | } catch (GeneralSecurityException e) { |
459 | 476 | if (GrpcUtil.getFlag(GRPC_ENABLE_PER_RPC_AUTHORITY_CHECK, false)) { |
460 | 477 | return new FailingClientStream(Status.UNAVAILABLE.withDescription( |
@@ -482,11 +499,18 @@ public ClientStream newStream( |
482 | 499 | for (int i = 0; i < peerCertificates.length; i++) { |
483 | 500 | x509PeerCertificates[i] = (X509Certificate) peerCertificates[i]; |
484 | 501 | } |
485 | | - ((X509ExtendedTrustManager) x509ExtendedTrustManager).checkServerTrusted( |
486 | | - x509PeerCertificates, "RSA", |
487 | | - new SslSocketWrapper((SSLSocket) socket, callOptions.getAuthority())); |
488 | | - peerVerificationStatus = Status.OK; |
489 | | - } catch (SSLPeerUnverifiedException | CertificateException e) { |
| 502 | + // Should never happen |
| 503 | + if (checkServerTrustedMethod == null) { |
| 504 | + peerVerificationStatus = Status.UNAVAILABLE.withDescription( |
| 505 | + "Method checkServerTrusted not found in " |
| 506 | + + "javax.net.ssl.X509ExtendedTrustManager"); |
| 507 | + } else { |
| 508 | + checkServerTrustedMethod.invoke(x509ExtendedTrustManager, x509PeerCertificates, |
| 509 | + "RSA", new SslSocketWrapper((SSLSocket) socket, callOptions.getAuthority())); |
| 510 | + peerVerificationStatus = Status.OK; |
| 511 | + } |
| 512 | + } catch (SSLPeerUnverifiedException | InvocationTargetException |
| 513 | + | IllegalAccessException e) { |
490 | 514 | peerVerificationStatus = Status.UNAVAILABLE.withDescription( |
491 | 515 | String.format("Failure in verifying authority '%s' against peer during rpc", |
492 | 516 | callOptions.getAuthority())).withCause(e); |
@@ -533,7 +557,7 @@ private TrustManager getX509ExtendedTrustManager(TlsChannelCredentials tlsCreds) |
533 | 557 | tm = tmf.getTrustManagers(); |
534 | 558 | } |
535 | 559 | for (TrustManager trustManager: tm) { |
536 | | - if (trustManager instanceof X509ExtendedTrustManager) { |
| 560 | + if (x509ExtendedTrustManagerClass.isInstance(trustManager)) { |
537 | 561 | return trustManager; |
538 | 562 | } |
539 | 563 | } |
|
0 commit comments