|
|
69f63c |
From 7b4c0fa04f5e4469fc8bc442c9f12f975c5e1610 Mon Sep 17 00:00:00 2001
|
|
|
69f63c |
From: Alexander Scheel <ascheel@redhat.com>
|
|
|
69f63c |
Date: Wed, 28 Aug 2019 09:23:41 -0400
|
|
|
69f63c |
Subject: [PATCH 3/3] Add optional test case against badssl.com
|
|
|
69f63c |
|
|
|
69f63c |
badssl.com maintains a number of subdomains with valid and invalid TLS
|
|
|
69f63c |
configurations. A number of these test certificates which fail in
|
|
|
69f63c |
certain scenarios (revoked, expired, etc). Add a test runner which
|
|
|
69f63c |
validates SSLSocket's implementation against badssl.com.
|
|
|
69f63c |
|
|
|
69f63c |
Signed-off-by: Alexander Scheel <ascheel@redhat.com>
|
|
|
69f63c |
---
|
|
|
69f63c |
org/mozilla/jss/tests/BadSSL.java | 208 ++++++++++++++++++++++++++++++
|
|
|
69f63c |
1 file changed, 208 insertions(+)
|
|
|
69f63c |
create mode 100644 org/mozilla/jss/tests/BadSSL.java
|
|
|
69f63c |
|
|
|
69f63c |
diff --git a/org/mozilla/jss/tests/BadSSL.java b/org/mozilla/jss/tests/BadSSL.java
|
|
|
69f63c |
new file mode 100644
|
|
|
69f63c |
index 00000000..60bfe820
|
|
|
69f63c |
--- /dev/null
|
|
|
69f63c |
+++ b/org/mozilla/jss/tests/BadSSL.java
|
|
|
69f63c |
@@ -0,0 +1,208 @@
|
|
|
69f63c |
+package org.mozilla.jss.tests;
|
|
|
69f63c |
+
|
|
|
69f63c |
+import org.mozilla.jss.CryptoManager;
|
|
|
69f63c |
+
|
|
|
69f63c |
+import org.mozilla.jss.ssl.SSLSocket;
|
|
|
69f63c |
+import org.mozilla.jss.ssl.SSLSocketException;
|
|
|
69f63c |
+
|
|
|
69f63c |
+import org.mozilla.jss.util.NativeErrcodes;
|
|
|
69f63c |
+
|
|
|
69f63c |
+/**
|
|
|
69f63c |
+ * The BadSSL test case maintains an internal mapping from badssl.com
|
|
|
69f63c |
+ * subdomains to expected exceptions and validates they occur.
|
|
|
69f63c |
+ *
|
|
|
69f63c |
+ * Since badssl.com offers no guaranteed SLA or availability, we likely
|
|
|
69f63c |
+ * shouldn't add this site to automated tests.
|
|
|
69f63c |
+ */
|
|
|
69f63c |
+
|
|
|
69f63c |
+public class BadSSL {
|
|
|
69f63c |
+ public static void main(String[] args) throws Exception {
|
|
|
69f63c |
+ boolean ocsp = false;
|
|
|
69f63c |
+
|
|
|
69f63c |
+ if (args.length < 1) {
|
|
|
69f63c |
+ System.out.println("Usage: BadSSL nssdb [LEAF_AND_CHAIN]");
|
|
|
69f63c |
+ return;
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ if (args.length >= 2 && args[1].equals("LEAF_AND_CHAIN")) {
|
|
|
69f63c |
+ System.out.println("Enabling leaf and chain policy...");
|
|
|
69f63c |
+ ocsp = true;
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ CryptoManager.initialize(args[0]);
|
|
|
69f63c |
+ CryptoManager cm = CryptoManager.getInstance();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ if (ocsp) {
|
|
|
69f63c |
+ cm.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+
|
|
|
69f63c |
+ // Test cases which should fail due to various certificate errors.
|
|
|
69f63c |
+ testExpired();
|
|
|
69f63c |
+ testWrongHost();
|
|
|
69f63c |
+ testSelfSigned();
|
|
|
69f63c |
+ testUntrustedRoot();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ // The following test cases depend on crypto-policies or local NSS
|
|
|
69f63c |
+ // configuration.
|
|
|
69f63c |
+ testSHA1();
|
|
|
69f63c |
+ testRC4MD5();
|
|
|
69f63c |
+ testRC4();
|
|
|
69f63c |
+ test3DES();
|
|
|
69f63c |
+ testNULL();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ // The following test cases depend on OCSP being enabled.
|
|
|
69f63c |
+ if (ocsp) {
|
|
|
69f63c |
+ testRevoked();
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ // Test cases which should pass given the correct root certs.
|
|
|
69f63c |
+ testSHA256();
|
|
|
69f63c |
+ testSHA384();
|
|
|
69f63c |
+ testSHA512();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ testECC256();
|
|
|
69f63c |
+ testECC384();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ testRSA2048();
|
|
|
69f63c |
+ testRSA4096();
|
|
|
69f63c |
+ testRSA8192();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ testExtendedValidation();
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ /* Test cases whose handshakes should fail below. */
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testExpired() throws Exception {
|
|
|
69f63c |
+ testHelper("expired.badssl.com", 443, new String[]{ "(-8181)", "has expired" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testWrongHost() throws Exception {
|
|
|
69f63c |
+ testHelper("wrong.host.badssl.com", 443, new String[]{ "(-12276)", "domain name does not match" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testSelfSigned() throws Exception {
|
|
|
69f63c |
+ testHelper("self-signed.badssl.com", 443, new String[]{ "(-8101)", "(-8156)", "type not approved", "issuer certificate is invalid" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testUntrustedRoot() throws Exception {
|
|
|
69f63c |
+ testHelper("untrusted-root.badssl.com", 443, new String[]{ "(-8172)", "certificate issuer has been marked as not trusted" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testRevoked() throws Exception {
|
|
|
69f63c |
+ testHelper("revoked.badssl.com", 443, new String[]{ "(-8180)", "has been revoked" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testSHA1() throws Exception {
|
|
|
69f63c |
+ testHelper("sha1-intermediate.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testRC4MD5() throws Exception {
|
|
|
69f63c |
+ testHelper("rc4-md5.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testRC4() throws Exception {
|
|
|
69f63c |
+ testHelper("rc4.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void test3DES() throws Exception {
|
|
|
69f63c |
+ testHelper("3des.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testNULL() throws Exception {
|
|
|
69f63c |
+ testHelper("null.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ /* Test cases which should handshake successfully below. */
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testSHA256() throws Exception {
|
|
|
69f63c |
+ testHelper("sha256.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testSHA384() throws Exception {
|
|
|
69f63c |
+ testHelper("sha384.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testSHA512() throws Exception {
|
|
|
69f63c |
+ testHelper("sha512.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testECC256() throws Exception {
|
|
|
69f63c |
+ testHelper("ecc256.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testECC384() throws Exception {
|
|
|
69f63c |
+ testHelper("ecc384.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testRSA2048() throws Exception {
|
|
|
69f63c |
+ testHelper("rsa2048.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testRSA4096() throws Exception {
|
|
|
69f63c |
+ testHelper("rsa4096.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testRSA8192() throws Exception {
|
|
|
69f63c |
+ testHelper("rsa8192.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testExtendedValidation() throws Exception {
|
|
|
69f63c |
+ testHelper("extended-validation.badssl.com", 443);
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ /* Test case helpers. */
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testHelper(String host, int port) throws Exception {
|
|
|
69f63c |
+ testSite(host, port);
|
|
|
69f63c |
+ System.out.println("\t...ok");
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testHelper(String host, int port, String[] substrs) throws Exception {
|
|
|
69f63c |
+ try {
|
|
|
69f63c |
+ testSite(host, port);
|
|
|
69f63c |
+ } catch (SSLSocketException sse) {
|
|
|
69f63c |
+ String actual = sse.getMessage().toLowerCase();
|
|
|
69f63c |
+
|
|
|
69f63c |
+ for (String expected : substrs) {
|
|
|
69f63c |
+ if (actual.contains(expected.toLowerCase())) {
|
|
|
69f63c |
+ System.out.println("\t...got expected error message.");
|
|
|
69f63c |
+ return;
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ System.err.println("\tUnexpected error message: " + actual);
|
|
|
69f63c |
+ throw sse;
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ throw new RuntimeException("Expected to get an exception, but didn't!");
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testHelper(String host, int port, int[] codes) throws Exception {
|
|
|
69f63c |
+ try {
|
|
|
69f63c |
+ testSite(host, port);
|
|
|
69f63c |
+ } catch (SSLSocketException sse) {
|
|
|
69f63c |
+ int actual = sse.getErrcode();
|
|
|
69f63c |
+ for (int expected : codes) {
|
|
|
69f63c |
+ if (actual == expected) {
|
|
|
69f63c |
+ System.out.println("\t...got expected error code.");
|
|
|
69f63c |
+ return;
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ System.err.println("\tUnexpected error code: " + actual);
|
|
|
69f63c |
+ throw sse;
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ throw new RuntimeException("Expected to get an exception, but didn't!");
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+
|
|
|
69f63c |
+ public static void testSite(String host, int port) throws Exception {
|
|
|
69f63c |
+ System.out.println("Testing connection to " + host + ":" + port);
|
|
|
69f63c |
+ SSLSocket sock = new SSLSocket(host, 443);
|
|
|
69f63c |
+ sock.forceHandshake();
|
|
|
69f63c |
+ sock.shutdownOutput();
|
|
|
69f63c |
+ sock.shutdownInput();
|
|
|
69f63c |
+ sock.close();
|
|
|
69f63c |
+ }
|
|
|
69f63c |
+}
|
|
|
69f63c |
--
|
|
|
69f63c |
2.21.0
|
|
|
69f63c |
|