Skip to content

Commit

Permalink
Allow blocking calls in JdkSslContext class initializer (#12435)
Browse files Browse the repository at this point in the history
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 <norman_maurer@apple.com>
  • Loading branch information
chrisvest and normanmaurer committed Jun 1, 2022
1 parent a2f101a commit 2cd0b4c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 21 deletions.
4 changes: 4 additions & 0 deletions common/src/main/java/io/netty5/util/internal/Hidden.java
Expand Up @@ -103,6 +103,10 @@ public void applyTo(BlockHound.Builder builder) {
"io.netty5.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(
Expand Down
63 changes: 42 additions & 21 deletions handler/src/main/java/io/netty5/handler/ssl/JdkSslContext.java
Expand Up @@ -67,35 +67,56 @@ 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);
}
}

private static final class Defaults {
String[] defaultProtocols;
List<String> defaultCiphers;
List<String> defaultCiphersNonTLSv13;
Set<String> supportedCiphers;
Set<String> supportedCiphersNonTLSv13;
Provider defaultProvider;

DEFAULT_PROVIDER = context.getProvider();
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);
}

SSLEngine engine = context.createSSLEngine();
DEFAULT_PROTOCOLS = defaultProtocols(context, engine);
defaultProvider = context.getProvider();

SUPPORTED_CIPHERS = Collections.unmodifiableSet(supportedCiphers(engine));
DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers(engine, SUPPORTED_CIPHERS));
SSLEngine engine = context.createSSLEngine();
defaultProtocols = defaultProtocols(context, engine);

List<String> ciphersNonTLSv13 = new ArrayList<>(DEFAULT_CIPHERS);
ciphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES));
DEFAULT_CIPHERS_NON_TLSV13 = Collections.unmodifiableList(ciphersNonTLSv13);
supportedCiphers = Collections.unmodifiableSet(supportedCiphers(engine));
defaultCiphers = Collections.unmodifiableList(defaultCiphers(engine, supportedCiphers));

Set<String> suppertedCiphersNonTLSv13 = new LinkedHashSet<>(SUPPORTED_CIPHERS);
for (String defaultTlsv13CipherSuite : SslUtils.DEFAULT_TLSV13_CIPHER_SUITES) {
List<String> ciphersNonTLSv13 = new ArrayList<>(defaultCiphers);
ciphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES));
defaultCiphersNonTLSv13 = Collections.unmodifiableList(ciphersNonTLSv13);

Set<String> suppertedCiphersNonTLSv13 = new LinkedHashSet<>(supportedCiphers);
for (String defaultTlsv13CipherSuite : SslUtils.DEFAULT_TLSV13_CIPHER_SUITES) {
suppertedCiphersNonTLSv13.remove(defaultTlsv13CipherSuite);
}
SUPPORTED_CIPHERS_NON_TLSV13 = Collections.unmodifiableSet(suppertedCiphersNonTLSv13);

if (logger.isDebugEnabled()) {
logger.debug("Default protocols (JDK): {} ", Arrays.asList(DEFAULT_PROTOCOLS));
logger.debug("Default cipher suites (JDK): {}", DEFAULT_CIPHERS);
supportedCiphersNonTLSv13 = Collections.unmodifiableSet(suppertedCiphersNonTLSv13);
}
}

Expand Down

0 comments on commit 2cd0b4c

Please sign in to comment.