Skip to content

Commit b828098

Browse files
committed
Pass extended trust manager to protocol negotiator.
1 parent 011a9ea commit b828098

File tree

15 files changed

+176
-116
lines changed

15 files changed

+176
-116
lines changed

core/src/main/java/io/grpc/internal/CertificateUtils.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.security.cert.CertificateFactory;
2727
import java.security.cert.X509Certificate;
2828
import java.util.Collection;
29+
import java.util.List;
2930
import javax.net.ssl.TrustManager;
3031
import javax.net.ssl.TrustManagerFactory;
3132
import javax.security.auth.x500.X500Principal;
@@ -34,6 +35,16 @@
3435
* Contains certificate/key PEM file utility method(s) for internal usage.
3536
*/
3637
public final class CertificateUtils {
38+
private static Class<?> x509ExtendedTrustManagerClass;
39+
40+
static {
41+
try {
42+
x509ExtendedTrustManagerClass = Class.forName("javax.net.ssl.X509ExtendedTrustManager");
43+
} catch (ClassNotFoundException e) {
44+
// Will disallow per-rpc authority override via call option.
45+
}
46+
}
47+
3748
/**
3849
* Creates X509TrustManagers using the provided CA certs.
3950
*/
@@ -71,6 +82,17 @@ public static TrustManager[] createTrustManager(InputStream rootCerts)
7182
return trustManagerFactory.getTrustManagers();
7283
}
7384

85+
public static TrustManager getX509ExtendedTrustManager(List<TrustManager> trustManagers) {
86+
if (x509ExtendedTrustManagerClass != null) {
87+
for (TrustManager trustManager : trustManagers) {
88+
if (x509ExtendedTrustManagerClass.isInstance(trustManager)) {
89+
return trustManager;
90+
}
91+
}
92+
}
93+
return null;
94+
}
95+
7496
private static X509Certificate[] getX509Certificates(InputStream inputStream)
7597
throws CertificateException {
7698
CertificateFactory factory = CertificateFactory.getInstance("X.509");

netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import io.netty.channel.ChannelHandler;
2626
import io.netty.handler.ssl.SslContext;
2727
import io.netty.util.AsciiString;
28+
29+
import javax.net.ssl.TrustManager;
30+
import javax.net.ssl.X509TrustManager;
2831
import java.util.concurrent.Executor;
2932

3033
/**
@@ -39,15 +42,16 @@ private InternalProtocolNegotiators() {}
3942
* be negotiated, the {@code handler} is added and writes to the {@link io.netty.channel.Channel}
4043
* may happen immediately, even before the TLS Handshake is complete.
4144
*
42-
* @param executorPool a dedicated {@link Executor} pool for time-consuming TLS tasks
43-
* @param isXdsTarget
45+
* @param executorPool a dedicated {@link Executor} pool for time-consuming TLS tasks
4446
*/
4547
public static InternalProtocolNegotiator.ProtocolNegotiator tls(SslContext sslContext,
4648
ObjectPool<? extends Executor> executorPool,
4749
Optional<Runnable> handshakeCompleteRunnable,
50+
TrustManager extendedX509TrustManager,
4851
String sni, boolean isXdsTarget) {
4952
final io.grpc.netty.ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext,
50-
executorPool, handshakeCompleteRunnable, null, sni, isXdsTarget);
53+
executorPool, handshakeCompleteRunnable, (X509TrustManager) extendedX509TrustManager, sni,
54+
isXdsTarget);
5155
final class TlsNegotiator implements InternalProtocolNegotiator.ProtocolNegotiator {
5256

5357
@Override
@@ -75,8 +79,8 @@ public void close() {
7579
* may happen immediately, even before the TLS Handshake is complete.
7680
*/
7781
public static InternalProtocolNegotiator.ProtocolNegotiator tls(
78-
SslContext sslContext, String sni, boolean isXdsTarget) {
79-
return tls(sslContext, null, Optional.absent(), sni, isXdsTarget);
82+
SslContext sslContext, String sni, boolean isXdsTarget, TrustManager extendedX509TrustManager) {
83+
return tls(sslContext, null, Optional.absent(), extendedX509TrustManager, sni, isXdsTarget);
8084
}
8185

8286
/**

netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,6 @@ final class ProtocolNegotiators {
104104
private static final EnumSet<TlsServerCredentials.Feature> understoodServerTlsFeatures =
105105
EnumSet.of(
106106
TlsServerCredentials.Feature.MTLS, TlsServerCredentials.Feature.CUSTOM_MANAGERS);
107-
private static Class<?> x509ExtendedTrustManagerClass;
108-
109-
static {
110-
try {
111-
x509ExtendedTrustManagerClass = Class.forName("javax.net.ssl.X509ExtendedTrustManager");
112-
} catch (ClassNotFoundException e) {
113-
// Will disallow per-rpc authority override via call option.
114-
}
115-
}
116107

117108
private ProtocolNegotiators() {
118109
}
@@ -149,15 +140,8 @@ public static FromChannelCredentialsResult from(ChannelCredentials creds) {
149140
trustManagers = Arrays.asList(tmf.getTrustManagers());
150141
}
151142
builder.trustManager(new FixedTrustManagerFactory(trustManagers));
152-
TrustManager x509ExtendedTrustManager = null;
153-
if (x509ExtendedTrustManagerClass != null) {
154-
for (TrustManager trustManager : trustManagers) {
155-
if (x509ExtendedTrustManagerClass.isInstance(trustManager)) {
156-
x509ExtendedTrustManager = trustManager;
157-
break;
158-
}
159-
}
160-
}
143+
TrustManager x509ExtendedTrustManager =
144+
CertificateUtils.getX509ExtendedTrustManager(trustManagers);
161145
return FromChannelCredentialsResult.negotiator(tlsClientFactory(builder.build(),
162146
(X509TrustManager) x509ExtendedTrustManager));
163147
} catch (SSLException | GeneralSecurityException ex) {

s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2AProtocolNegotiatorFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public void run() {
259259
s2aStub.close();
260260
}
261261
}),
262-
null, false)
262+
null, null, false)
263263
.newHandler(grpcHandler);
264264

265265
// Delegate the rest of the handshake to the TLS handler. and remove the

xds/src/main/java/io/grpc/xds/internal/security/DynamicSslContextProvider.java

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,20 @@
3030
import java.io.IOException;
3131
import java.security.cert.CertStoreException;
3232
import java.security.cert.CertificateException;
33+
import java.util.AbstractMap;
3334
import java.util.ArrayList;
3435
import java.util.List;
3536
import javax.annotation.Nullable;
37+
import javax.net.ssl.TrustManager;
3638

3739
/** Base class for dynamic {@link SslContextProvider}s. */
3840
@Internal
3941
public abstract class DynamicSslContextProvider extends SslContextProvider {
4042

4143
protected final List<Callback> pendingCallbacks = new ArrayList<>();
4244
@Nullable protected final CertificateValidationContext staticCertificateValidationContext;
43-
@Nullable protected SslContext sslContext;
45+
@Nullable protected AbstractMap.SimpleImmutableEntry<SslContext, TrustManager>
46+
sslContextAndExtendedX509TrustManager;
4447

4548
protected DynamicSslContextProvider(
4649
BaseTlsContext tlsContext, CertificateValidationContext staticCertValidationContext) {
@@ -49,14 +52,16 @@ protected DynamicSslContextProvider(
4952
}
5053

5154
@Nullable
52-
public SslContext getSslContext() {
53-
return sslContext;
55+
public AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> getSslContextAndExtendedX509TrustManager() {
56+
return sslContextAndExtendedX509TrustManager;
5457
}
5558

5659
protected abstract CertificateValidationContext generateCertificateValidationContext();
5760

58-
/** Gets a server or client side SslContextBuilder. */
59-
protected abstract SslContextBuilder getSslContextBuilder(
61+
/**
62+
* Gets a server or client side SslContextBuilder.
63+
*/
64+
protected abstract AbstractMap.SimpleImmutableEntry<SslContextBuilder, TrustManager> getSslContextBuilderAndExtendedX509TrustManager(
6065
CertificateValidationContext certificateValidationContext)
6166
throws CertificateException, IOException, CertStoreException;
6267

@@ -65,7 +70,8 @@ protected final void updateSslContext() {
6570
try {
6671
CertificateValidationContext localCertValidationContext =
6772
generateCertificateValidationContext();
68-
SslContextBuilder sslContextBuilder = getSslContextBuilder(localCertValidationContext);
73+
AbstractMap.SimpleImmutableEntry<SslContextBuilder, TrustManager> sslContextBuilderAndTm =
74+
getSslContextBuilderAndExtendedX509TrustManager(localCertValidationContext);
6975
CommonTlsContext commonTlsContext = getCommonTlsContext();
7076
if (commonTlsContext != null && commonTlsContext.getAlpnProtocolsCount() > 0) {
7177
List<String> alpnList = commonTlsContext.getAlpnProtocolsList();
@@ -75,29 +81,30 @@ protected final void updateSslContext() {
7581
ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,
7682
ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT,
7783
alpnList);
78-
sslContextBuilder.applicationProtocolConfig(apn);
84+
sslContextBuilderAndTm.getKey().applicationProtocolConfig(apn);
7985
}
8086
List<Callback> pendingCallbacksCopy;
81-
SslContext sslContextCopy;
87+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextAndExtendedX09TrustManagerCopy;
8288
synchronized (pendingCallbacks) {
83-
sslContext = sslContextBuilder.build();
84-
sslContextCopy = sslContext;
89+
sslContextAndExtendedX509TrustManager = new AbstractMap.SimpleImmutableEntry<>(
90+
sslContextBuilderAndTm.getKey().build(), sslContextBuilderAndTm.getValue());
91+
sslContextAndExtendedX09TrustManagerCopy = sslContextAndExtendedX509TrustManager;
8592
pendingCallbacksCopy = clonePendingCallbacksAndClear();
8693
}
87-
makePendingCallbacks(sslContextCopy, pendingCallbacksCopy);
94+
makePendingCallbacks(sslContextAndExtendedX09TrustManagerCopy, pendingCallbacksCopy);
8895
} catch (Exception e) {
8996
onError(Status.fromThrowable(e));
9097
throw new RuntimeException(e);
9198
}
9299
}
93100

94101
protected final void callPerformCallback(
95-
Callback callback, final SslContext sslContextCopy) {
102+
Callback callback, final AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextAndTmCopy) {
96103
performCallback(
97104
new SslContextGetter() {
98105
@Override
99-
public SslContext get() {
100-
return sslContextCopy;
106+
public AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> get() {
107+
return sslContextAndTmCopy;
101108
}
102109
},
103110
callback
@@ -108,10 +115,10 @@ public SslContext get() {
108115
public final void addCallback(Callback callback) {
109116
checkNotNull(callback, "callback");
110117
// if there is a computed sslContext just send it
111-
SslContext sslContextCopy = null;
118+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextCopy = null;
112119
synchronized (pendingCallbacks) {
113-
if (sslContext != null) {
114-
sslContextCopy = sslContext;
120+
if (sslContextAndExtendedX509TrustManager != null) {
121+
sslContextCopy = sslContextAndExtendedX509TrustManager;
115122
} else {
116123
pendingCallbacks.add(callback);
117124
}
@@ -122,9 +129,11 @@ public final void addCallback(Callback callback) {
122129
}
123130

124131
private final void makePendingCallbacks(
125-
SslContext sslContextCopy, List<Callback> pendingCallbacksCopy) {
132+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager>
133+
sslContextAndExtendedX509TrustManagerCopy,
134+
List<Callback> pendingCallbacksCopy) {
126135
for (Callback callback : pendingCallbacksCopy) {
127-
callPerformCallback(callback, sslContextCopy);
136+
callPerformCallback(callback, sslContextAndExtendedX509TrustManagerCopy);
128137
}
129138
}
130139

xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@
4141
import io.netty.handler.ssl.SslContext;
4242
import io.netty.util.AsciiString;
4343
import java.security.cert.CertStoreException;
44+
import java.util.AbstractMap;
4445
import java.util.ArrayList;
4546
import java.util.List;
4647
import java.util.concurrent.Executor;
4748
import java.util.logging.Level;
4849
import java.util.logging.Logger;
4950
import javax.annotation.Nullable;
51+
import javax.net.ssl.TrustManager;
5052

5153
/**
5254
* Provides client and server side gRPC {@link ProtocolNegotiator}s to provide the SSL
@@ -240,7 +242,8 @@ protected void handlerAdded0(final ChannelHandlerContext ctx) {
240242
new SslContextProvider.Callback(ctx.executor()) {
241243

242244
@Override
243-
public void updateSslContext(SslContext sslContext) {
245+
public void updateSslContextAndExtendedX509TrustManager(
246+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextAndTm) {
244247
if (ctx.isRemoved()) {
245248
return;
246249
}
@@ -249,7 +252,9 @@ public void updateSslContext(SslContext sslContext) {
249252
"ClientSecurityHandler.updateSslContext authority={0}, ctx.name={1}",
250253
new Object[]{grpcHandler.getAuthority(), ctx.name()});
251254
ChannelHandler handler =
252-
InternalProtocolNegotiators.tls(sslContext, sni, true).newHandler(grpcHandler);
255+
InternalProtocolNegotiators.tls(
256+
sslContextAndTm.getKey(), sni, true, sslContextAndTm.getValue())
257+
.newHandler(grpcHandler);
253258

254259
// Delegate rest of handshake to TLS handler
255260
ctx.pipeline().addAfter(ctx.name(), null, handler);
@@ -383,9 +388,10 @@ protected void handlerAdded0(final ChannelHandlerContext ctx) {
383388
new SslContextProvider.Callback(ctx.executor()) {
384389

385390
@Override
386-
public void updateSslContext(SslContext sslContext) {
391+
public void updateSslContextAndExtendedX509TrustManager(
392+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextAndTm) {
387393
ChannelHandler handler =
388-
InternalProtocolNegotiators.serverTls(sslContext).newHandler(grpcHandler);
394+
InternalProtocolNegotiators.serverTls(sslContextAndTm.getKey()).newHandler(grpcHandler);
389395

390396
// Delegate rest of handshake to TLS handler
391397
if (!ctx.isRemoved()) {

xds/src/main/java/io/grpc/xds/internal/security/SslContextProvider.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@
2929
import io.netty.handler.ssl.ClientAuth;
3030
import io.netty.handler.ssl.SslContext;
3131
import io.netty.handler.ssl.SslContextBuilder;
32+
33+
import javax.net.ssl.TrustManager;
3234
import java.io.IOException;
3335
import java.security.cert.CertStoreException;
3436
import java.security.cert.CertificateException;
37+
import java.util.AbstractMap;
3538
import java.util.concurrent.Executor;
3639

3740
/**
@@ -59,7 +62,8 @@ protected Callback(Executor executor) {
5962
}
6063

6164
/** Informs callee of new/updated SslContext. */
62-
@VisibleForTesting public abstract void updateSslContext(SslContext sslContext);
65+
@VisibleForTesting public abstract void updateSslContextAndExtendedX509TrustManager(
66+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContext);
6367

6468
/** Informs callee of an exception that was generated. */
6569
@VisibleForTesting protected abstract void onException(Throwable throwable);
@@ -121,8 +125,9 @@ protected final void performCallback(
121125
@Override
122126
public void run() {
123127
try {
124-
SslContext sslContext = sslContextGetter.get();
125-
callback.updateSslContext(sslContext);
128+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextAndTm =
129+
sslContextGetter.get();
130+
callback.updateSslContextAndExtendedX509TrustManager(sslContextAndTm);
126131
} catch (Throwable e) {
127132
callback.onException(e);
128133
}
@@ -132,6 +137,6 @@ public void run() {
132137

133138
/** Allows implementations to compute or get SslContext. */
134139
protected interface SslContextGetter {
135-
SslContext get() throws Exception;
140+
AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> get() throws Exception;
136141
}
137142
}

xds/src/main/java/io/grpc/xds/internal/security/SslContextProviderSupplier.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io.grpc.xds.TlsContextManager;
2525
import io.netty.handler.ssl.SslContext;
2626

27+
import javax.net.ssl.TrustManager;
28+
import java.util.AbstractMap;
2729
import java.util.HashSet;
2830
import java.util.Objects;
2931
import java.util.Set;
@@ -70,8 +72,8 @@ public synchronized void updateSslContext(final SslContextProvider.Callback call
7072
new SslContextProvider.Callback(callback.getExecutor()) {
7173

7274
@Override
73-
public void updateSslContext(SslContext sslContext) {
74-
callback.updateSslContext(sslContext);
75+
public void updateSslContextAndExtendedX509TrustManager(AbstractMap.SimpleImmutableEntry<SslContext, TrustManager> sslContextAndTm) {
76+
callback.updateSslContextAndExtendedX509TrustManager(sslContextAndTm);
7577
releaseSslContextProvider(toRelease, sni);
7678
}
7779

0 commit comments

Comments
 (0)