From d2c52b0392504aae4b70aefef3644c31b0bc83c4 Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Wed, 1 Jun 2022 09:17:12 -0700 Subject: [PATCH] Allow blocking calls in JdkSslContext class initializer (#12435) Motivation: Classes might be initialized inside the event loop where blocking calls are otherwise forbidden. The JdkSslContext has a blocking call in its class initializer through initializing the Java SSLContext which does IO to deserialize its key store. Modification: Collect the class initialization code in a method, and allow it to have blocking calls in blockhound. Result: No more blockhound warnings about blocking calls in JdkSslContext class initializer. Fixes #12425 Co-authored-by: Norman Maurer --- .../java/io/netty/util/internal/Hidden.java | 4 ++ .../io/netty/handler/ssl/JdkSslContext.java | 61 +++++++++++++------ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/common/src/main/java/io/netty/util/internal/Hidden.java b/common/src/main/java/io/netty/util/internal/Hidden.java index 78c45f715db..5ebf8e780e2 100644 --- a/common/src/main/java/io/netty/util/internal/Hidden.java +++ b/common/src/main/java/io/netty/util/internal/Hidden.java @@ -108,6 +108,10 @@ public void applyTo(BlockHound.Builder builder) { "io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback", "verify"); + builder.allowBlockingCallsInside( + "io.netty.handler.ssl.JdkSslContext$Defaults", + "init"); + // Let's whitelist SSLEngineImpl.unwrap(...) for now as it may fail otherwise for TLS 1.3. // See https://mail.openjdk.java.net/pipermail/security-dev/2020-August/022271.html builder.allowBlockingCallsInside( diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java index a452924829a..516ef660ba9 100644 --- a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java @@ -69,33 +69,54 @@ public class JdkSslContext extends SslContext { private static final Provider DEFAULT_PROVIDER; static { - SSLContext context; - try { - context = SSLContext.getInstance(PROTOCOL); - context.init(null, null, null); - } catch (Exception e) { - throw new Error("failed to initialize the default SSL context", e); + Defaults defaults = new Defaults(); + defaults.init(); + + DEFAULT_PROVIDER = defaults.defaultProvider; + DEFAULT_PROTOCOLS = defaults.defaultProtocols; + SUPPORTED_CIPHERS = defaults.supportedCiphers; + DEFAULT_CIPHERS = defaults.defaultCiphers; + DEFAULT_CIPHERS_NON_TLSV13 = defaults.defaultCiphersNonTLSv13; + SUPPORTED_CIPHERS_NON_TLSV13 = defaults.supportedCiphersNonTLSv13; + + if (logger.isDebugEnabled()) { + logger.debug("Default protocols (JDK): {} ", Arrays.asList(DEFAULT_PROTOCOLS)); + logger.debug("Default cipher suites (JDK): {}", DEFAULT_CIPHERS); } + } - DEFAULT_PROVIDER = context.getProvider(); + private static final class Defaults { + String[] defaultProtocols; + List defaultCiphers; + List defaultCiphersNonTLSv13; + Set supportedCiphers; + Set supportedCiphersNonTLSv13; + Provider defaultProvider; - SSLEngine engine = context.createSSLEngine(); - DEFAULT_PROTOCOLS = defaultProtocols(context, engine); + void init() { + SSLContext context; + try { + context = SSLContext.getInstance(PROTOCOL); + context.init(null, null, null); + } catch (Exception e) { + throw new Error("failed to initialize the default SSL context", e); + } - SUPPORTED_CIPHERS = Collections.unmodifiableSet(supportedCiphers(engine)); - DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers(engine, SUPPORTED_CIPHERS)); + defaultProvider = context.getProvider(); - List ciphersNonTLSv13 = new ArrayList(DEFAULT_CIPHERS); - ciphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES)); - DEFAULT_CIPHERS_NON_TLSV13 = Collections.unmodifiableList(ciphersNonTLSv13); + SSLEngine engine = context.createSSLEngine(); + defaultProtocols = defaultProtocols(context, engine); - Set suppertedCiphersNonTLSv13 = new LinkedHashSet(SUPPORTED_CIPHERS); - suppertedCiphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES)); - SUPPORTED_CIPHERS_NON_TLSV13 = Collections.unmodifiableSet(suppertedCiphersNonTLSv13); + supportedCiphers = Collections.unmodifiableSet(supportedCiphers(engine)); + defaultCiphers = Collections.unmodifiableList(defaultCiphers(engine, supportedCiphers)); - if (logger.isDebugEnabled()) { - logger.debug("Default protocols (JDK): {} ", Arrays.asList(DEFAULT_PROTOCOLS)); - logger.debug("Default cipher suites (JDK): {}", DEFAULT_CIPHERS); + List ciphersNonTLSv13 = new ArrayList(defaultCiphers); + ciphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES)); + defaultCiphersNonTLSv13 = Collections.unmodifiableList(ciphersNonTLSv13); + + Set suppertedCiphersNonTLSv13 = new LinkedHashSet(supportedCiphers); + suppertedCiphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES)); + supportedCiphersNonTLSv13 = Collections.unmodifiableSet(suppertedCiphersNonTLSv13); } }