From 73c29a96d0281fa4c14844bd06296eb6f4bcb80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kohlschu=CC=88tter?= Date: Tue, 26 Sep 2023 17:02:30 +0200 Subject: [PATCH] ssl: Detect known JRE/JDK bug JDK-8202837 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. --- .../net/unix/ssl/SSLContextBuilder.java | 31 ++ .../net/unix/ssl/SNIHostnameCaptureTest.java | 27 +- .../net/unix/ssl/SSLContextBuilderTest.java | 388 +++++++++++----- .../ssl/ValidatingX509TrustManagerTest.java | 431 ++++++++++-------- 4 files changed, 566 insertions(+), 311 deletions(-) diff --git a/junixsocket-ssl/src/main/java/org/newsclub/net/unix/ssl/SSLContextBuilder.java b/junixsocket-ssl/src/main/java/org/newsclub/net/unix/ssl/SSLContextBuilder.java index b1fcd6c2d..08bef47c7 100644 --- a/junixsocket-ssl/src/main/java/org/newsclub/net/unix/ssl/SSLContextBuilder.java +++ b/junixsocket-ssl/src/main/java/org/newsclub/net/unix/ssl/SSLContextBuilder.java @@ -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; @@ -372,6 +373,8 @@ 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); } @@ -379,6 +382,32 @@ private KeyManager[] buildKeyManagers(KeyManagerFactory kmf) throws GeneralSecur 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 { @@ -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); } diff --git a/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SNIHostnameCaptureTest.java b/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SNIHostnameCaptureTest.java index 6f6f0cad0..b4235128c 100644 --- a/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SNIHostnameCaptureTest.java +++ b/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SNIHostnameCaptureTest.java @@ -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; @@ -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 @@ -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 { diff --git a/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SSLContextBuilderTest.java b/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SSLContextBuilderTest.java index dc449263a..895882a06 100644 --- a/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SSLContextBuilderTest.java +++ b/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/SSLContextBuilderTest.java @@ -67,11 +67,14 @@ import org.newsclub.net.unix.AFUNIXSocket; import org.newsclub.net.unix.AFUNIXSocketAddress; import org.newsclub.net.unix.AFUNIXSocketPair; +import org.newsclub.net.unix.KnownJavaBugIOException; import com.kohlschutter.annotations.compiletime.SuppressFBWarnings; import com.kohlschutter.testutil.AssertUtil; import com.kohlschutter.testutil.ExecutionEnvironmentRequirement; import com.kohlschutter.testutil.ExecutionEnvironmentRequirement.Rule; +import com.kohlschutter.testutil.TestAbortedWithImportantMessageException; +import com.kohlschutter.testutil.TestAbortedWithImportantMessageException.MessageType; import com.kohlschutter.testutil.TestResourceUtil; // CPD-OFF @@ -83,19 +86,26 @@ public class SSLContextBuilderTest extends SSLTestBase { public void testNoClientAuth(TestSSLConfiguration configuration) throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - SSLParametersUtil.disableCipherSuites(p, "SOME_REALLY_BAD_CIPHER"); // for code coverage - SSLParametersUtil.disableProtocols(p, "TLSv1.0", "TLSv1.1"); - }) // - .buildAndDestroyBuilder().getSocketFactory(); - - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore"), () -> "clienttrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + SSLParametersUtil.disableCipherSuites(p, "SOME_REALLY_BAD_CIPHER"); // for code coverage + SSLParametersUtil.disableProtocols(p, "TLSv1.0", "TLSv1.1"); + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = 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); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -116,22 +126,30 @@ public void testNoClientAuth(TestSSLConfiguration configuration) throws Exceptio public void testClientAuthRequired(TestSSLConfiguration configuration) throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.truststore"), () -> "servertrustpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - p.setNeedClientAuth(true); - }) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore"), () -> "clienttrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.truststore"), () -> "servertrustpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + p.setNeedClientAuth(true); + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .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); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -155,18 +173,26 @@ public void testClientAuthRequiredButClientIsNotSendingAKey(TestSSLConfiguration throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - p.setNeedClientAuth(true); - }) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore"), () -> "clienttrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + p.setNeedClientAuth(true); + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = 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); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -202,20 +228,28 @@ public void testClientAuthRequiredButClientKeyIsNotTrusted(TestSSLConfiguration throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - p.setNeedClientAuth(true); - }) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .withTrustStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore"), () -> "clienttrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + p.setNeedClientAuth(true); + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .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); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -250,16 +284,24 @@ public void testClientAuthRequiredButClientKeyIsNotTrusted(TestSSLConfiguration public void testClientHasNoTrustStore(TestSSLConfiguration configuration) throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withSecureRandom(null) // just for code coverage - .withDefaultSSLParameters((p) -> { - }) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .buildAndDestroyBuilder().getSocketFactory(); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withSecureRandom(null) // just for code coverage + .withDefaultSSLParameters((p) -> { + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -295,29 +337,44 @@ public void testServerAndClientBlindlyTrustAnything(TestSSLConfiguration configu throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withTrustManagers((tmf) -> { - return new TrustManager[] {IgnorantX509TrustManager.getInstance()}; - }).withDefaultSSLParameters(p -> { - p.setNeedClientAuth(true); - }) // - .withKeyManagers((kmf) -> { - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12").openStream()) { - ks.load(in, "serverpass".toCharArray()); - } - kmf.init(ks, "serverpass".toCharArray()); - return kmf.getKeyManagers(); - }) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .withTrustManagers((tmf) -> { - return new TrustManager[] {IgnorantX509TrustManager.getInstance()}; - }).buildAndDestroyBuilder().getSocketFactory(); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withTrustManagers((tmf) -> { + return new TrustManager[] {IgnorantX509TrustManager.getInstance()}; + }).withDefaultSSLParameters(p -> { + p.setNeedClientAuth(true); + }) // + .withKeyManagers((kmf) -> { + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12").openStream()) { + try { + ks.load(in, "serverpass".toCharArray()); + } catch (IOException e) { + throw SSLContextBuilder.wrapIOExceptionIfJDKBug(e); + } + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + kmf.init(ks, "serverpass".toCharArray()); + return kmf.getKeyManagers(); + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .withTrustManagers((tmf) -> { + return new TrustManager[] {IgnorantX509TrustManager.getInstance()}; + }).buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -428,7 +485,12 @@ public void testDestroyablePasswordSupplier(TestSSLConfiguration configuration) .withDefaultSSLParameters((p) -> { }); // - builder.build(); + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertFalse(dps.isDestroyed()); @@ -449,7 +511,12 @@ public void testDestroyablePasswordSupplierDestroyed(TestSSLConfiguration config .withDefaultSSLParameters((p) -> { }); // - builder.build(); + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertFalse(dps.isDestroyed()); dps.destroy(); // destroy manually @@ -472,7 +539,12 @@ public void testUndestroyablePasswordSupplier(TestSSLConfiguration configuration .withDefaultSSLParameters((p) -> { }); // - builder.build(); + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertFalse(dps.isDestroyed()); @@ -495,7 +567,12 @@ public void testUndestroyablePasswordSuppliers(TestSSLConfiguration configuratio .withDefaultSSLParameters((p) -> { }); // - builder.build(); + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertFalse(dps.isDestroyed()); @@ -525,7 +602,7 @@ public void testKeyStoreNullPasswordSupplied(TestSSLConfiguration configuration) boolean fail = true; try { builder.build(); - } catch (UnrecoverableKeyException | NullPointerException e) { + } catch (UnrecoverableKeyException | NullPointerException | KnownJavaBugIOException e) { fail = false; } if (fail) { @@ -547,7 +624,7 @@ public void testKeyStoreNullPasswordSupplier(TestSSLConfiguration configuration) boolean fail = true; try { builder.build(); - } catch (UnrecoverableKeyException | NullPointerException e) { + } catch (UnrecoverableKeyException | NullPointerException | KnownJavaBugIOException e) { fail = false; } if (fail) { @@ -574,7 +651,14 @@ public void testKeyStoreURLNotFound(TestSSLConfiguration configuration) throws E builder.withKeyStore(f.toURI().toURL(), () -> "serverpass".toCharArray()); - assertThrows(FileNotFoundException.class, builder::build); + assertThrows(FileNotFoundException.class, () -> { + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @ParameterizedTest @@ -587,7 +671,14 @@ public void testKeyStoreFileNotFound(TestSSLConfiguration configuration) throws builder.withKeyStore(f, () -> "serverpass".toCharArray()); - assertThrows(FileNotFoundException.class, builder::build); + assertThrows(FileNotFoundException.class, () -> { + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @ParameterizedTest @@ -600,7 +691,14 @@ public void testTrustStoreNullPasswordSupplied(TestSSLConfiguration configuratio .withDefaultSSLParameters((p) -> { }); // - assertNoExceptionOrNullPointerException(() -> builder.build()); + assertNoExceptionOrNullPointerException(() -> { + try { + return builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @SuppressFBWarnings("DCN_NULLPOINTER_EXCEPTION") @@ -622,7 +720,14 @@ public void testTrustStoreNullPasswordSupplier(TestSSLConfiguration configuratio .withDefaultSSLParameters((p) -> { }); // - assertNoExceptionOrNullPointerException(() -> builder.build()); + assertNoExceptionOrNullPointerException(() -> { + try { + return builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @ParameterizedTest @@ -644,7 +749,14 @@ public void testTrustStoreURLNotFound(TestSSLConfiguration configuration) throws builder.withTrustStore(f.toURI().toURL(), () -> "servertrustpass".toCharArray()); - assertThrows(FileNotFoundException.class, builder::build); + assertThrows(FileNotFoundException.class, () -> { + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @ParameterizedTest @@ -657,7 +769,14 @@ public void testTrustStoreFileNotFound(TestSSLConfiguration configuration) throw builder.withTrustStore(f, () -> "servertrustpass".toCharArray()); - assertThrows(FileNotFoundException.class, builder::build); + assertThrows(FileNotFoundException.class, () -> { + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @ParameterizedTest @@ -666,7 +785,14 @@ public void testBadProtocol(TestSSLConfiguration configuration) throws Exception SSLContextBuilder builder = configuration.configure(SSLContextBuilder.forClient()) // .withProtocol("UnknownProtocol/UnitTesting"); - assertThrows(NoSuchAlgorithmException.class, builder::build); + assertThrows(NoSuchAlgorithmException.class, () -> { + try { + builder.build(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException( + MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, e.getMessage(), e); + } + }); } @ParameterizedTest @@ -799,10 +925,16 @@ public char[] get() throws GeneralSecurityException, IOException { @ParameterizedTest @EnumSource(TestSSLConfiguration.class) public void testSocketFactoryMethods(TestSSLConfiguration configuration) throws Exception { - SSLSocketFactory factory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory factory; + try { + factory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertThrows(SocketException.class, () -> factory.createSocket(), "Creating unconnected sockets is not supported, as they're very difficult to wrap"); @@ -832,10 +964,16 @@ public void testSocketFactoryMethods(TestSSLConfiguration configuration) throws @EnumSource(TestSSLConfiguration.class) public void testSocketFactoryMethodsForCodeCoverageOnly(TestSSLConfiguration configuration) throws Exception { - SSLSocketFactory factory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory factory; + try { + factory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } InetAddress loopback = InetAddress.getLoopbackAddress(); try (ServerSocket ss = new ServerSocket(0, 50, loopback)) { @@ -849,10 +987,16 @@ public void testSocketFactoryMethodsForCodeCoverageOnly(TestSSLConfiguration con @ParameterizedTest @EnumSource(TestSSLConfiguration.class) public void testServerSocketFactoryMethods(TestSSLConfiguration configuration) throws Exception { - SSLServerSocketFactory factory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getServerSocketFactory(); + SSLServerSocketFactory factory; + try { + factory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getServerSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertNotEquals(0, factory.getDefaultCipherSuites().length); assertNotEquals(0, factory.getSupportedCipherSuites().length); @@ -873,10 +1017,16 @@ public void testServerSocketFactoryMethods(TestSSLConfiguration configuration) t @EnumSource(TestSSLConfiguration.class) public void testServerSocketFactoryMethodsForCodeCoverageOnly(TestSSLConfiguration configuration) throws Exception { - SSLServerSocketFactory factory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getServerSocketFactory(); + SSLServerSocketFactory factory; + try { + factory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getServerSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } assertNotNull(factory.createServerSocket(0)); assertNotNull(factory.createServerSocket(0, 0)); @@ -886,10 +1036,16 @@ public void testServerSocketFactoryMethodsForCodeCoverageOnly(TestSSLConfigurati @ParameterizedTest @EnumSource(TestSSLConfiguration.class) public void testSSLEngineMethods(TestSSLConfiguration configuration) throws Exception { - SSLContext context = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder(); + SSLContext context; + try { + context = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } SSLEngine engine; diff --git a/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/ValidatingX509TrustManagerTest.java b/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/ValidatingX509TrustManagerTest.java index bc2befeb4..07fb95e29 100644 --- a/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/ValidatingX509TrustManagerTest.java +++ b/junixsocket-ssl/src/test/java/org/newsclub/net/unix/ssl/ValidatingX509TrustManagerTest.java @@ -52,8 +52,11 @@ 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 com.kohlschutter.testutil.AssertUtil; +import com.kohlschutter.testutil.TestAbortedWithImportantMessageException; +import com.kohlschutter.testutil.TestAbortedWithImportantMessageException.MessageType; import com.kohlschutter.testutil.TestResourceUtil; // CPD-OFF @@ -65,30 +68,38 @@ public void testInspectTrustedCertificateExpired(TestSSLConfiguration configurat throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withTrustManagers((tmf) -> { - - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore").openStream()) { - ks.load(in, "clienttrustpass".toCharArray()); - } - tmf.init(ks); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.truststore").openStream()) { + ks.load(in, "clienttrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - ValidatingX509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + ValidatingX509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); - // we didn't change them here - assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); + // we didn't change them here + assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -122,30 +133,38 @@ public void testInspectTrustedCertificateNotExpired(TestSSLConfiguration configu // NOTE: we simply swap client and server certificates here, since only the server certificate // is expired - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); - - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withTrustManagers((tmf) -> { + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.truststore").openStream()) { - ks.load(in, "servertrustpass".toCharArray()); - } - tmf.init(ks); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.truststore").openStream()) { + ks.load(in, "servertrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - ValidatingX509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + ValidatingX509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); - // we didn't change them here - assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); + // we didn't change them here + assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -168,33 +187,41 @@ public void testInspectTrustedCertificateExpiredNested(TestSSLConfiguration conf throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); - - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withTrustManagers((tmf) -> { + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore").openStream()) { - ks.load(in, "clienttrustpass".toCharArray()); - } - tmf.init(ks); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.truststore").openStream()) { + ks.load(in, "clienttrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - // nesting two ValidatingX509TrustManager, just to cover onCertificateException - ValidatingX509TrustManager tm = new ValidatingX509TrustManager( - new ValidatingX509TrustManager(underlyingTrustManager)); + // nesting two ValidatingX509TrustManager, just to cover onCertificateException + ValidatingX509TrustManager tm = new ValidatingX509TrustManager( + new ValidatingX509TrustManager(underlyingTrustManager)); - // we didn't change them here - assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); + // we didn't change them here + assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -225,47 +252,55 @@ public void testInspectTrustedCertificateExpiredNestedFilter(TestSSLConfiguratio throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); - - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withTrustManagers((tmf) -> { + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore").openStream()) { - ks.load(in, "clienttrustpass".toCharArray()); - } - tmf.init(ks); + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.truststore").openStream()) { + ks.load(in, "clienttrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - // nesting two FilterX509TrustManager, just to cover onCertificateException - X509TrustManager tm = new FilterX509TrustManager(new ValidatingX509TrustManager( - underlyingTrustManager)) { + // nesting two FilterX509TrustManager, just to cover onCertificateException + X509TrustManager tm = new FilterX509TrustManager(new ValidatingX509TrustManager( + underlyingTrustManager)) { - @Override - protected void onCertificateException(boolean checkClient, CertificateException e, - X509Certificate[] chain, String authType) throws CertificateException { - // swallow exception - assertFalse(checkClient); // we're checking the server certificate - } + @Override + protected void onCertificateException(boolean checkClient, CertificateException e, + X509Certificate[] chain, String authType) throws CertificateException { + // swallow exception + assertFalse(checkClient); // we're checking the server certificate + } - @Override - protected void onCertificateTrusted(boolean checkClient, X509Certificate[] chain, - String authType) throws CertificateException { - fail("unexpected"); - } - }; + @Override + protected void onCertificateTrusted(boolean checkClient, X509Certificate[] chain, + String authType) throws CertificateException { + fail("unexpected"); + } + }; - // we didn't change them here - assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); + // we didn't change them here + assertArrayEquals(underlyingTrustManager.getAcceptedIssuers(), tm.getAcceptedIssuers()); - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -285,35 +320,43 @@ public void testInspectTrustedClientCertificate(TestSSLConfiguration configurati throws Exception { AFUNIXSocketAddress addr = AFUNIXSocketAddress.ofNewTempFile(); - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - p.setNeedClientAuth(true); - }) // - .withTrustManagers((tmf) -> { - - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxserver.truststore").openStream()) { - ks.load(in, "servertrustpass".toCharArray()); - } - tmf.init(ks); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + p.setNeedClientAuth(true); + }) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxserver.truststore").openStream()) { + ks.load(in, "servertrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); + X509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .withTrustStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxclient.truststore"), () -> "clienttrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .withTrustStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxclient.truststore"), () -> "clienttrustpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -339,35 +382,43 @@ public void testInspectTrustedClientCertificateExpired(TestSSLConfiguration conf // NOTE: we simply swap client and server certificates here, since only the server certificate // is expired - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - p.setNeedClientAuth(true); - }) // - .withTrustManagers((tmf) -> { - - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore").openStream()) { - ks.load(in, "clienttrustpass".toCharArray()); - } - tmf.init(ks); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + p.setNeedClientAuth(true); + }) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.truststore").openStream()) { + ks.load(in, "clienttrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); + X509TrustManager tm = new ValidatingX509TrustManager(underlyingTrustManager); - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withTrustStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.truststore"), () -> "servertrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withTrustStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.truststore"), () -> "servertrustpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>(); @@ -401,50 +452,58 @@ public void testInspectTrustedClientCertificateExpiredNested(TestSSLConfiguratio // NOTE: we simply swap client and server certificates here, since only the server certificate // is expired - SSLSocketFactory serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxclient.p12"), () -> "clientpass".toCharArray()) // - .withDefaultSSLParameters((p) -> { - p.setNeedClientAuth(true); - }) // - .withTrustManagers((tmf) -> { - - KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); - try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, - "juxclient.truststore").openStream()) { - ks.load(in, "clienttrustpass".toCharArray()); - } - tmf.init(ks); + SSLSocketFactory serverSocketFactory; + SSLSocketFactory clientSocketFactory; - X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; + try { + serverSocketFactory = configuration.configure(SSLContextBuilder.forServer()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxclient.p12"), () -> "clientpass".toCharArray()) // + .withDefaultSSLParameters((p) -> { + p.setNeedClientAuth(true); + }) // + .withTrustManagers((tmf) -> { + + KeyStore ks = SSLContextBuilder.newKeyStorePKCS12(); + try (InputStream in = TestResourceUtil.getRequiredResource(SSLContextBuilderTest.class, + "juxclient.truststore").openStream()) { + ks.load(in, "clienttrustpass".toCharArray()); + } + tmf.init(ks); - X509TrustManager tm = new FilterX509TrustManager(new ValidatingX509TrustManager( - underlyingTrustManager)) { + X509TrustManager underlyingTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; - @Override - protected void onCertificateTrusted(boolean checkClient, X509Certificate[] chain, - String authType) throws CertificateException { - // that's good (but unexpected) - fail("unexpected"); - } + X509TrustManager tm = new FilterX509TrustManager(new ValidatingX509TrustManager( + underlyingTrustManager)) { - @Override - protected void onCertificateException(boolean checkClient, CertificateException e, - X509Certificate[] chain, String authType) throws CertificateException { - // still accept certificate - } - }; - - return new TrustManager[] {tm}; - }) // - .buildAndDestroyBuilder().getSocketFactory(); - - SSLSocketFactory clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // - .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.p12"), () -> "serverpass".toCharArray()) // - .withTrustStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, - "juxserver.truststore"), () -> "servertrustpass".toCharArray()) // - .buildAndDestroyBuilder().getSocketFactory(); + @Override + protected void onCertificateTrusted(boolean checkClient, X509Certificate[] chain, + String authType) throws CertificateException { + // that's good (but unexpected) + fail("unexpected"); + } + + @Override + protected void onCertificateException(boolean checkClient, CertificateException e, + X509Certificate[] chain, String authType) throws CertificateException { + // still accept certificate + } + }; + + return new TrustManager[] {tm}; + }) // + .buildAndDestroyBuilder().getSocketFactory(); + + clientSocketFactory = configuration.configure(SSLContextBuilder.forClient()) // + .withKeyStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.p12"), () -> "serverpass".toCharArray()) // + .withTrustStore(TestResourceUtil.getRequiredResource(ValidatingX509TrustManagerTest.class, + "juxserver.truststore"), () -> "servertrustpass".toCharArray()) // + .buildAndDestroyBuilder().getSocketFactory(); + } catch (KnownJavaBugIOException e) { + throw new TestAbortedWithImportantMessageException(MessageType.TEST_ABORTED_SHORT_WITH_ISSUES, + e.getMessage(), e); + } CompletableFuture serverException = new CompletableFuture<>(); CompletableFuture clientException = new CompletableFuture<>();