Skip to content

Commit

Permalink
ssl: Detect known JRE/JDK bug JDK-8202837
Browse files Browse the repository at this point in the history
Older versions of Java 8-11 are unable to parse the key data we may use
in our ssl tests.

Detect/handle this bug, and do not fail selftest but log a corresponding
message.
  • Loading branch information
kohlschuetter committed Sep 26, 2023
1 parent 4cabdac commit 73c29a9
Show file tree
Hide file tree
Showing 4 changed files with 566 additions and 311 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import javax.security.auth.Destroyable;

import org.newsclub.net.unix.AFSocket;
import org.newsclub.net.unix.KnownJavaBugIOException;

import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;

Expand Down Expand Up @@ -372,13 +373,41 @@ private KeyManager[] buildKeyManagers(KeyManagerFactory kmf) throws GeneralSecur
try (InputStream in = keyStoreUrl.openStream()) {
ks.load(in, password);
kmf.init(ks, password);
} catch (IOException e) {
throw wrapIOExceptionIfJDKBug(e);
} finally {
clear(password);
}

return kmf.getKeyManagers();
}

/**
* For a given {@link IOException} thrown from within {@link SSLContextBuilder}, check if it is
* due to a known JDK bug, and if so, wrap that exception in a {@link KnownJavaBugIOException}
* with a proper explanation.
*
* @param e The exception to check/wrap.
* @return The exception, or a {@link KnownJavaBugIOException}.
*/
public static IOException wrapIOExceptionIfJDKBug(IOException e) {
String msg = e.getMessage();
if (msg != null && msg.contains("data isn't an object ID (tag = 48)")) {
String specVersion = System.getProperty("java.specification.version", "");
if (specVersion.startsWith("1.")) {
return new KnownJavaBugIOException(
"Bug JDK-8202837 detected -- please upgrade to Java 8u312 or newer", e);
} else if ("9".equals(specVersion) || "10".equals(specVersion) || "11".equals(specVersion)) {
return new KnownJavaBugIOException(
"Bug JDK-8202837 detected -- please upgrade to Java 11.0.3 or newer", e);
} else {
return new KnownJavaBugIOException(
"Bug JDK-8202837 detected -- please upgrade your Java release", e);
}
}
return e;
}

private TrustManager[] buildTrustManagers(TrustManagerFactory tmf) throws IOException,
GeneralSecurityException {

Expand All @@ -392,6 +421,8 @@ private TrustManager[] buildTrustManagers(TrustManagerFactory tmf) throws IOExce
char[] password = trustManagerPassword == null ? null : trustManagerPassword.get();
try (InputStream in = trustManagerUrl.openStream()) {
ks.load(in, password);
} catch (IOException e) {
throw wrapIOExceptionIfJDKBug(e);
} finally {
clear(password);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.newsclub.net.unix.AFSocket;
import org.newsclub.net.unix.AFUNIXSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;
import org.newsclub.net.unix.KnownJavaBugIOException;
import org.opentest4j.AssertionFailedError;

import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
Expand All @@ -62,10 +63,15 @@
public class SNIHostnameCaptureTest extends SSLTestBase {
private static SSLSocketFactory initClientSocketFactory(TestSSLConfiguration configuration)
throws Exception {
return configuration.configure(SSLContextBuilder.forClient()) //
.withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class,
"juxclient.truststore"), () -> "clienttrustpass".toCharArray()) //
.buildAndDestroyBuilder().getSocketFactory();
try {
return configuration.configure(SSLContextBuilder.forClient()) //
.withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class,
"juxclient.truststore"), () -> "clienttrustpass".toCharArray()) //
.buildAndDestroyBuilder().getSocketFactory();
} catch (KnownJavaBugIOException e) {
throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES,
e.getMessage(), e);
}
}

@ParameterizedTest
Expand Down Expand Up @@ -136,16 +142,19 @@ private void testSNISuccess(TestSSLConfiguration configuration, boolean expectDe
boolean serverNullDefaultHostname, boolean clientEmptyDefaultHostname) throws Exception {
AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile();

SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) //
.withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class,
"juxserver.p12"), () -> "serverpass".toCharArray()) //
.buildAndDestroyBuilder().getSocketFactory();

try {
SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) //
.withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class,
"juxserver.p12"), () -> "serverpass".toCharArray()) //
.buildAndDestroyBuilder().getSocketFactory();

assertTimeoutPreemptively(Duration.ofSeconds(5), () -> {
runServerAndClient(configuration, addr, serverSocketFactory, expectDefault,
serverNullDefaultHostname, clientEmptyDefaultHostname);
});
} catch (KnownJavaBugIOException e) {
throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES,
e.getMessage(), e);
} catch (Exception | Error e) {
throw configuration.handleException(e);
} finally {
Expand Down
Loading

0 comments on commit 73c29a9

Please sign in to comment.