Skip to content

Commit

Permalink
Allow blocking calls in JdkSslContext class initializer (netty#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 netty#12425

Co-authored-by: Norman Maurer <norman_maurer@apple.com>
  • Loading branch information
2 people authored and 夏无影 committed Jul 8, 2022
1 parent 1eaeee0 commit fce9051
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 20 deletions.
4 changes: 4 additions & 0 deletions common/src/main/java/io/netty/util/internal/Hidden.java
Expand Up @@ -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(
Expand Down
61 changes: 41 additions & 20 deletions handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java
Expand Up @@ -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<String> defaultCiphers;
List<String> defaultCiphersNonTLSv13;
Set<String> supportedCiphers;
Set<String> 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<String> ciphersNonTLSv13 = new ArrayList<String>(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<String> suppertedCiphersNonTLSv13 = new LinkedHashSet<String>(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<String> ciphersNonTLSv13 = new ArrayList<String>(defaultCiphers);
ciphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES));
defaultCiphersNonTLSv13 = Collections.unmodifiableList(ciphersNonTLSv13);

Set<String> suppertedCiphersNonTLSv13 = new LinkedHashSet<String>(supportedCiphers);
suppertedCiphersNonTLSv13.removeAll(Arrays.asList(SslUtils.DEFAULT_TLSV13_CIPHER_SUITES));
supportedCiphersNonTLSv13 = Collections.unmodifiableSet(suppertedCiphersNonTLSv13);
}
}

Expand Down

0 comments on commit fce9051

Please sign in to comment.