diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8d0656a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/jss-4.4.7.tar.gz
diff --git a/.jss.metadata b/.jss.metadata
new file mode 100644
index 0000000..9b6805b
--- /dev/null
+++ b/.jss.metadata
@@ -0,0 +1 @@
+73cfcfdf2eefc39351b4b1dd9ee6f517faa64f19 SOURCES/jss-4.4.7.tar.gz
diff --git a/SOURCES/0001-JSS-CVE-2019-14823-fix.patch b/SOURCES/0001-JSS-CVE-2019-14823-fix.patch
new file mode 100644
index 0000000..46d1e4e
--- /dev/null
+++ b/SOURCES/0001-JSS-CVE-2019-14823-fix.patch
@@ -0,0 +1,346 @@
+From 4c44f138e67db9c583baf78c7aa0460a941e9842 Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Wed, 4 Sep 2019 08:33:14 -0400
+Subject: [PATCH] Fix root certificate validation
+
+When the Leaf and Chain OCSP checking policy is enabled in
+CryptoManager, JSS will switch to alternative certificate verification
+logic in JSSL_DefaultCertAuthCallback. In this method, the root
+certificate was incorrectly trusted without being verified to exist in
+the trust store.
+
+This patch cleans up the logic in JSSL_verifyCertPKIX and makes it
+more explicit in addition to fixing the error.
+
+Fixes CVE-2019-14823
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ org/mozilla/jss/ssl/common.c | 239 ++++++++++++++++++++---------------
+ 1 file changed, 136 insertions(+), 103 deletions(-)
+
+diff --git a/org/mozilla/jss/ssl/common.c b/org/mozilla/jss/ssl/common.c
+index cd4d4425..3a448c54 100644
+--- a/org/mozilla/jss/ssl/common.c
++++ b/org/mozilla/jss/ssl/common.c
+@@ -901,7 +901,6 @@ finish:
+ }
+ 
+ /* Get the trusted anchor for pkix */
+-
+ CERTCertificate *getRoot(CERTCertificate *cert,
+     SECCertUsage certUsage) 
+ {
+@@ -935,79 +934,84 @@ finish:
+     return root; 
+ }
+ 
+-/* Verify a cert using explicit PKIX call.
+- * For now only used in OCSP AIA context.
+- * The result of this call will be a full chain
+- * and leaf network AIA ocsp validation.
+- * The policy param will be used in the future to
+- * handle more scenarios.
+- */
+-
+-SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert,
+-      SECCertificateUsage certificateUsage,secuPWData *pwdata, int ocspPolicy,
+-      CERTVerifyLog *log, SECCertificateUsage *usage) 
++/* Internal helper for the below call. */
++static SECStatus
++JSSL_verifyCertPKIXInternal(CERTCertificate *cert,
++    SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy,
++    CERTVerifyLog *log, SECCertificateUsage *usage,
++    CERTCertList *trustedCertList)
+ {
+-
+-    /* put the first set of possible flags internally here first */
+-    /* later there could be a more complete list to choose from */
+-    /* support our hard core fetch aia ocsp policy for now */
+-
+-    static PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
++    /* Put the first set of possible flags internally here first. Later
++     * there could be a more complete list to choose from; for now we only
++     * support our hard core fetch AIA OCSP policy. Note that we disable
++     * CRL fetching as Dogtag doesn't support it. Additionally, enable OCSP
++     * checking on the chained CA certificates. Since NSS/PKIX's
++     * CERT_GetClassicOCSPEnabledHardFailurePolicy doesn't do what we want,
++     * we construct the policy ourselves. */
++    PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
+         /* crl */
+-        0,
++        CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD,
+         /* ocsp */
+         CERT_REV_M_TEST_USING_THIS_METHOD |
+-        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
++            CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
+     };
+ 
+-    static PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
++    PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
+         /* crl */
+-        0,
++        CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD,
+         /* ocsp */
+         CERT_REV_M_TEST_USING_THIS_METHOD |
+-        CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
++            CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
+     };
+ 
+-    static CERTRevocationMethodIndex
+-        ocsp_Enabled_Hard_Policy_Method_Preference = {
+-            cert_revocation_method_ocsp
+-        };
+-
+-    static CERTRevocationFlags ocsp_Enabled_Hard_Policy = {
+-    { /* leafTests */
+-      2,
+-      ocsp_Enabled_Hard_Policy_LeafFlags,
+-      1,
+-      &ocsp_Enabled_Hard_Policy_Method_Preference,
+-      0 },
+-    { /* chainTests */
+-      2,
+-      ocsp_Enabled_Hard_Policy_ChainFlags,
+-      1,
+-      &ocsp_Enabled_Hard_Policy_Method_Preference,
+-      0 }
++    CERTRevocationMethodIndex ocsp_Enabled_Hard_Policy_Method_Preference[1] = {
++        cert_revocation_method_ocsp
+     };
+ 
+-    /* for future expansion */
++    CERTRevocationFlags ocsp_Enabled_Hard_Policy = {
++        /* CERTRevocationTests - leafTests */
++        {
++            /* number_of_defined_methods */
++            2,
++            /* cert_rev_flags_per_method */
++            ocsp_Enabled_Hard_Policy_LeafFlags,
++            /* number_of_preferred_methods */
++            1,
++            /* preferred_methods */
++            ocsp_Enabled_Hard_Policy_Method_Preference,
++            /* cert_rev_method_independent_flags */
++            0
++        },
++        /* CERTRevocationTests - chainTests */
++        {
++            /* number_of_defined_methods */
++            2,
++            /* cert_rev_flags_per_method */
++            ocsp_Enabled_Hard_Policy_ChainFlags,
++            /* number_of_preferred_methods */
++            1,
++            /* preferred_methods */
++            ocsp_Enabled_Hard_Policy_Method_Preference,
++            /* cert_rev_method_independent_flags */
++            0
++        }
++    };
+ 
+-    CERTValOutParam cvout[20] = {0};
+-    CERTValInParam cvin[20] = {0};
++    /* The size of these objects are defined here based upon maximum possible
++     * inputs. A dynamic allocation could reallocate based upon actual usage,
++     * however this would affect the size by at most one or two. Note that,
++     * due to the required usage of cert_pi_end/cert_po_end, these sizes are
++     * inflated by one. */
++    CERTValOutParam cvout[3] = {{0}};
++    CERTValInParam cvin[6] = {{0}};
+ 
++    int usageIndex = -1;
+     int inParamIndex = 0;
+     int outParamIndex = 0;
+-    CERTRevocationFlags *rev = NULL;
+-
+-    CERTCertList *trustedCertList = NULL;
+-
+-    PRBool fetchCerts = PR_FALSE;
+ 
+-    SECCertUsage certUsage = certUsageSSLClient /* 0 */;
+-    
+     SECStatus res =  SECFailure;
+ 
+-    CERTCertificate *root = NULL;
+-
+-    if(cert == NULL) {
++    if (cert == NULL) {
+         goto finish;
+     }
+ 
+@@ -1015,93 +1019,122 @@ SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert,
+         goto finish;
+     }
+ 
+-    /* Force the strict ocsp network check on chain
+-       and leaf.
+-    */
+-
+-    fetchCerts = PR_TRUE;   
+-    rev = &ocsp_Enabled_Hard_Policy;
+-
+-    /* fetch aia over net */
+- 
++    /* Enable live AIA fetching over the network. */
+     cvin[inParamIndex].type = cert_pi_useAIACertFetch;
+-    cvin[inParamIndex].value.scalar.b = fetchCerts;
+-    inParamIndex++; 
+-
+-    /* time */
++    cvin[inParamIndex].value.scalar.b = PR_TRUE;
++    inParamIndex++;
+ 
++    /* By setting the time to zero, we choose the current time when the
++     * check is performed. */
+     cvin[inParamIndex].type = cert_pi_date;
+-    cvin[inParamIndex].value.scalar.time = PR_Now();
++    cvin[inParamIndex].value.scalar.time = 0;
+     inParamIndex++;
+ 
+-    /* flags */
+-
++    /* Force the strict OCSP check on both the leaf and its chain. */
+     cvin[inParamIndex].type = cert_pi_revocationFlags;
+-    cvin[inParamIndex].value.pointer.revocation = rev;
++    cvin[inParamIndex].value.pointer.revocation = &ocsp_Enabled_Hard_Policy;
+     inParamIndex++;
+ 
+-    /* establish trust anchor */
+-
+-    /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain
+-     * the root.
+-    */
+-
+-    SECCertificateUsage testUsage = certificateUsage;
+-    while (0 != (testUsage = testUsage >> 1)) { certUsage++; }
+-
+-    root = getRoot(cert,certUsage);
+-
+-    /* Try to add the root as the trust anchor so all the
+-       other memebers of the ca chain will get validated.
+-    */
+-
+-    if( root != NULL ) {
+-        trustedCertList = CERT_NewCertList();
+-        CERT_AddCertToListTail(trustedCertList, root);        
+-
++    /* Establish a trust anchor if it is passed to us. NOTE: this trust anchor
++     * must previously be validated before it is passed to us here. */
++    if (trustedCertList != NULL) {
+         cvin[inParamIndex].type = cert_pi_trustAnchors;
+         cvin[inParamIndex].value.pointer.chain = trustedCertList;
+-
+         inParamIndex++;
+     }
+ 
++    /* Done establishing input parameters. */
+     cvin[inParamIndex].type = cert_pi_end;
+ 
+-    if(log != NULL) {
++    /* When we need to log rationale for failure, pass it as an output
++     * parameter. */
++    if (log != NULL) {
+         cvout[outParamIndex].type = cert_po_errorLog;
+         cvout[outParamIndex].value.pointer.log = log;
+         outParamIndex ++;
+     }
+ 
+-    int usageIndex = 0;
+-    if(usage != NULL) {
++    /* When we need to inquire about the resulting certificate usage, pass it
++     * here. */
++    if (usage != NULL) {
+         usageIndex = outParamIndex;
+         cvout[outParamIndex].type = cert_po_usages;
+         cvout[outParamIndex].value.scalar.usages = 0;
+         outParamIndex ++;
+     }
+ 
++    /* Done establishing output parameters. */
+     cvout[outParamIndex].type = cert_po_end;
+ 
++    /* Call into NSS's PKIX library to validate our certificate. */
+     res = CERT_PKIXVerifyCert(cert, certificateUsage, cvin, cvout, &pwdata);
+ 
+ finish:
+-    /* clean up any trusted cert list */
+-
++    /* Clean up any certificates in the trusted certificate list. This was
++     * a passed input parameter, but by taking ownership of it and clearing it,
++     * we enable tail calls to this function. */
+     if (trustedCertList) {
++        /* CERT_DestroyCertList destroys interior certs for us. */
+         CERT_DestroyCertList(trustedCertList);
+         trustedCertList = NULL;
+     }
+ 
+-    /* CERT_DestroyCertList destroys interior certs for us. */
+-
+-    if(root) {
+-       root = NULL;
+-    }
+-
+-    if(res == SECSuccess && usage) {
++    if (res == SECSuccess && usage && usageIndex != -1) {
+         *usage = cvout[usageIndex].value.scalar.usages;
+     }
+ 
+     return res;
+ }
++
++/* Verify a cert using an explicit PKIX call. For now only perform this call
++ * when the OCSP policy is set to leaf and chain. Performs a blocking, online
++ * OCSP status refresh. The result of this call will be a full-chain OCSP
++ * validation.
++ *
++ * In the future, we'll use ocspPolicy to condition around additional policies
++ * and handle them all with this method (and a call to PKIX).
++ *
++ * Note that this currently requires the certificate to be added directly
++ * to the NSS DB. We can't otherwise validate against root certificates in
++ * the default NSS DB.
++ */
++SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert,
++      SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy,
++      CERTVerifyLog *log, SECCertificateUsage *usage)
++{
++    SECCertUsage certUsage = certUsageSSLClient /* 0 */;
++
++    /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain
++     * the root.
++     */
++
++    SECCertificateUsage testUsage = certificateUsage;
++    while (0 != (testUsage = testUsage >> 1)) { certUsage++; }
++
++    CERTCertificate *root = getRoot(cert, certUsage);
++
++    // Two cases: either the root is present, or it isn't.
++    if (root == NULL) {
++        /* In this case, we've had a hard time finding the root. In all
++         * likelihood, the following call will fail to validate the end cert
++         * as well and thus fail to validate. I don't believe there's a risk
++         * in trying it however. */
++        return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata,
++                                           ocspPolicy, log, usage, NULL);
++    } else {
++        /* In this case, we've found the root certificate. Before passing it
++         * to the leaf, explicitly validate it with strict OCSP checking. Then
++         * validate the leaf certificate with a known and trusted root
++         * certificate. */
++        SECStatus ret = JSSL_verifyCertPKIXInternal(root, certificateUsageSSLCA,
++            pwdata, ocspPolicy, log, usage, NULL);
++        if (ret != SECSuccess) {
++            return ret;
++        }
++
++        CERTCertList *rootList = CERT_NewCertList();
++        CERT_AddCertToListTail(rootList, root);
++        return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata,
++                                           ocspPolicy, log, usage, rootList);
++    }
++}
+-- 
+2.21.0
+
diff --git a/SOURCES/0002-Add-script-to-add-common-root-CAs.patch b/SOURCES/0002-Add-script-to-add-common-root-CAs.patch
new file mode 100644
index 0000000..cde61fe
--- /dev/null
+++ b/SOURCES/0002-Add-script-to-add-common-root-CAs.patch
@@ -0,0 +1,59 @@
+From 61985f642b0b5cc75fc3f254ef6c99aeb56acbe2 Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Thu, 29 Aug 2019 16:14:08 -0400
+Subject: [PATCH 2/3] Add script to add common root CAs
+
+When given an NSS DB, common_roots.sh uses the trust command to extract
+the root CAs trusted by the local system and add them to said NSS DB.
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ tools/common_roots.sh | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+ create mode 100755 tools/common_roots.sh
+
+diff --git a/tools/common_roots.sh b/tools/common_roots.sh
+new file mode 100755
+index 00000000..97341c4c
+--- /dev/null
++++ b/tools/common_roots.sh
+@@ -0,0 +1,36 @@
++#!/bin/bash
++
++# This script reads the contents of the OS CA bundle store,
++#   /usr/share/pki/ca-trust-source/ca-bundle.trust.p11-kit
++# and places the contained CAs into the specified NSS DB.
++#
++# This NSS DB is used by various JSS tests that aren't enabled
++# by default because they require an active internet connection.
++
++nssdb="$1"
++
++if [ -z "$nssdb" ] && [ -e "build" ]; then
++    nssdb="build/results/cadb"
++elif [ -z "$nssdb" ] && [ -e "../build" ]; then
++    nssdb="../build/results/cadb"
++else
++    echo "Must provide path to NSS DB!" 1>&2
++    exit 1
++fi
++
++if [ -e "$nssdb" ]; then
++    rm -rf "$nssdb"
++fi
++
++mkdir -p "$nssdb"
++echo "" > "$nssdb/password.txt"
++certutil -N -d "$nssdb" -f "$nssdb/password.txt"
++
++trust extract --format=pem-bundle  --filter=ca-anchors "$nssdb/complete.pem"
++
++# From: https://serverfault.com/questions/391396/how-to-split-a-pem-file
++csplit -f "$nssdb/individual-" "$nssdb/complete.pem" '/-----BEGIN CERTIFICATE-----/' '{*}'
++
++for cert in "$nssdb"/individual*; do
++    certutil -A -a -i "$cert" -n "$cert" -t CT,C,C -d "$nssdb" -f "$nssdb/password.txt"
++done
+-- 
+2.21.0
+
diff --git a/SOURCES/0003-Add-optional-test-case-against-badssl.com.patch b/SOURCES/0003-Add-optional-test-case-against-badssl.com.patch
new file mode 100644
index 0000000..ba155f1
--- /dev/null
+++ b/SOURCES/0003-Add-optional-test-case-against-badssl.com.patch
@@ -0,0 +1,233 @@
+From 7b4c0fa04f5e4469fc8bc442c9f12f975c5e1610 Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Wed, 28 Aug 2019 09:23:41 -0400
+Subject: [PATCH 3/3] Add optional test case against badssl.com
+
+badssl.com maintains a number of subdomains with valid and invalid TLS
+configurations. A number of these test certificates which fail in
+certain scenarios (revoked, expired, etc). Add a test runner which
+validates SSLSocket's implementation against badssl.com.
+
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+---
+ org/mozilla/jss/tests/BadSSL.java | 208 ++++++++++++++++++++++++++++++
+ 1 file changed, 208 insertions(+)
+ create mode 100644 org/mozilla/jss/tests/BadSSL.java
+
+diff --git a/org/mozilla/jss/tests/BadSSL.java b/org/mozilla/jss/tests/BadSSL.java
+new file mode 100644
+index 00000000..60bfe820
+--- /dev/null
++++ b/org/mozilla/jss/tests/BadSSL.java
+@@ -0,0 +1,208 @@
++package org.mozilla.jss.tests;
++
++import org.mozilla.jss.CryptoManager;
++
++import org.mozilla.jss.ssl.SSLSocket;
++import org.mozilla.jss.ssl.SSLSocketException;
++
++import org.mozilla.jss.util.NativeErrcodes;
++
++/**
++ * The BadSSL test case maintains an internal mapping from badssl.com
++ * subdomains to expected exceptions and validates they occur.
++ *
++ * Since badssl.com offers no guaranteed SLA or availability, we likely
++ * shouldn't add this site to automated tests.
++ */
++
++public class BadSSL {
++    public static void main(String[] args) throws Exception {
++        boolean ocsp = false;
++
++        if (args.length < 1) {
++            System.out.println("Usage: BadSSL nssdb [LEAF_AND_CHAIN]");
++            return;
++        }
++
++        if (args.length >= 2 && args[1].equals("LEAF_AND_CHAIN")) {
++            System.out.println("Enabling leaf and chain policy...");
++            ocsp = true;
++        }
++
++        CryptoManager.initialize(args[0]);
++        CryptoManager cm = CryptoManager.getInstance();
++
++        if (ocsp) {
++            cm.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN);
++        }
++
++
++        // Test cases which should fail due to various certificate errors.
++        testExpired();
++        testWrongHost();
++        testSelfSigned();
++        testUntrustedRoot();
++
++        // The following test cases depend on crypto-policies or local NSS
++        // configuration.
++        testSHA1();
++        testRC4MD5();
++        testRC4();
++        test3DES();
++        testNULL();
++
++        // The following test cases depend on OCSP being enabled.
++        if (ocsp) {
++            testRevoked();
++        }
++
++        // Test cases which should pass given the correct root certs.
++        testSHA256();
++        testSHA384();
++        testSHA512();
++
++        testECC256();
++        testECC384();
++
++        testRSA2048();
++        testRSA4096();
++        testRSA8192();
++
++        testExtendedValidation();
++    }
++
++    /* Test cases whose handshakes should fail below. */
++
++    public static void testExpired() throws Exception {
++        testHelper("expired.badssl.com", 443, new String[]{ "(-8181)", "has expired" });
++    }
++
++    public static void testWrongHost() throws Exception {
++        testHelper("wrong.host.badssl.com", 443, new String[]{ "(-12276)", "domain name does not match" });
++    }
++
++    public static void testSelfSigned() throws Exception {
++        testHelper("self-signed.badssl.com", 443, new String[]{ "(-8101)", "(-8156)", "type not approved", "issuer certificate is invalid" });
++    }
++
++    public static void testUntrustedRoot() throws Exception {
++        testHelper("untrusted-root.badssl.com", 443, new String[]{ "(-8172)", "certificate issuer has been marked as not trusted" });
++    }
++
++    public static void testRevoked() throws Exception {
++        testHelper("revoked.badssl.com", 443, new String[]{ "(-8180)", "has been revoked" });
++    }
++
++    public static void testSHA1() throws Exception {
++        testHelper("sha1-intermediate.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
++    }
++
++    public static void testRC4MD5() throws Exception {
++        testHelper("rc4-md5.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
++    }
++
++    public static void testRC4() throws Exception {
++        testHelper("rc4.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
++    }
++
++    public static void test3DES() throws Exception {
++        testHelper("3des.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
++    }
++
++    public static void testNULL() throws Exception {
++        testHelper("null.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" });
++    }
++
++    /* Test cases which should handshake successfully below. */
++
++    public static void testSHA256() throws Exception {
++        testHelper("sha256.badssl.com", 443);
++    }
++
++    public static void testSHA384() throws Exception {
++        testHelper("sha384.badssl.com", 443);
++    }
++
++    public static void testSHA512() throws Exception {
++        testHelper("sha512.badssl.com", 443);
++    }
++
++    public static void testECC256() throws Exception {
++        testHelper("ecc256.badssl.com", 443);
++    }
++
++    public static void testECC384() throws Exception {
++        testHelper("ecc384.badssl.com", 443);
++    }
++
++    public static void testRSA2048() throws Exception {
++        testHelper("rsa2048.badssl.com", 443);
++    }
++
++    public static void testRSA4096() throws Exception {
++        testHelper("rsa4096.badssl.com", 443);
++    }
++
++    public static void testRSA8192() throws Exception {
++        testHelper("rsa8192.badssl.com", 443);
++    }
++
++    public static void testExtendedValidation() throws Exception {
++        testHelper("extended-validation.badssl.com", 443);
++    }
++
++    /* Test case helpers. */
++
++    public static void testHelper(String host, int port) throws Exception {
++        testSite(host, port);
++        System.out.println("\t...ok");
++    }
++
++    public static void testHelper(String host, int port, String[] substrs) throws Exception {
++        try {
++            testSite(host, port);
++        } catch (SSLSocketException sse) {
++            String actual = sse.getMessage().toLowerCase();
++
++            for (String expected : substrs) {
++                if (actual.contains(expected.toLowerCase())) {
++                    System.out.println("\t...got expected error message.");
++                    return;
++                }
++            }
++
++            System.err.println("\tUnexpected error message: " + actual);
++            throw sse;
++        }
++
++        throw new RuntimeException("Expected to get an exception, but didn't!");
++    }
++
++    public static void testHelper(String host, int port, int[] codes) throws Exception {
++        try {
++            testSite(host, port);
++        } catch (SSLSocketException sse) {
++            int actual = sse.getErrcode();
++            for (int expected : codes) {
++                if (actual == expected) {
++                    System.out.println("\t...got expected error code.");
++                    return;
++                }
++            }
++
++            System.err.println("\tUnexpected error code: " + actual);
++            throw sse;
++        }
++
++        throw new RuntimeException("Expected to get an exception, but didn't!");
++    }
++
++    public static void testSite(String host, int port) throws Exception {
++        System.out.println("Testing connection to " + host + ":" + port);
++        SSLSocket sock = new SSLSocket(host, 443);
++        sock.forceHandshake();
++        sock.shutdownOutput();
++        sock.shutdownInput();
++        sock.close();
++    }
++}
+-- 
+2.21.0
+
diff --git a/SPECS/jss.spec b/SPECS/jss.spec
new file mode 100644
index 0000000..59edb0f
--- /dev/null
+++ b/SPECS/jss.spec
@@ -0,0 +1,206 @@
+################################################################################
+Name:           jss
+################################################################################
+
+Summary:        Java Security Services (JSS)
+URL:            http://www.dogtagpki.org/wiki/JSS
+License:        MPLv1.1 or GPLv2+ or LGPLv2+
+
+Version:        4.4.7
+Release:        2%{?dist}
+
+# To generate the source tarball:
+# $ git clone https://github.com/dogtagpki/jss.git
+# $ cd jss
+# $ git tag v4.4.<z>
+# $ git push origin v4.4.<z>
+# Then go to https://github.com/dogtagpki/jss/releases and download the source
+# tarball.
+Source:         https://github.com/dogtagpki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
+
+# To create a patch for all changes since a version tag:
+# $ git format-patch \
+#     --stdout \
+#     <version tag> \
+#     > jss-VERSION-RELEASE.patch
+Patch1: 0001-JSS-CVE-2019-14823-fix.patch
+Patch2: 0002-Add-script-to-add-common-root-CAs.patch
+Patch3: 0003-Add-optional-test-case-against-badssl.com.patch
+
+Conflicts:      idm-console-framework < 1.1.17-4
+Conflicts:      pki-base < 10.4.0
+Conflicts:      tomcatjss < 7.2.1
+
+# autosetup
+BuildRequires:  git
+
+BuildRequires:  nss-devel >= 3.28.4-6
+BuildRequires:  nspr-devel >= 4.13.1
+BuildRequires:  java-1.8.0-openjdk-devel
+BuildRequires:  jpackage-utils
+%if 0%{?fedora} >= 25 || 0%{?rhel} > 7
+BuildRequires:  perl-interpreter
+%endif
+BuildRequires:  apache-commons-lang
+BuildRequires:  apache-commons-codec
+
+Requires:       nss >= 3.28.4-6
+Requires:       java-1.8.0-openjdk-headless
+Requires:       jpackage-utils
+Requires:       apache-commons-lang
+Requires:       apache-commons-codec
+
+%description
+Java Security Services (JSS) is a java native interface which provides a bridge
+for java-based applications to use native Network Security Services (NSS).
+This only works with gcj. Other JREs require that JCE providers be signed.
+
+################################################################################
+%package javadoc
+################################################################################
+
+Summary:        Java Security Services (JSS) Javadocs
+Group:          Documentation
+Requires:       jss = %{version}-%{release}
+
+%description javadoc
+This package contains the API documentation for JSS.
+
+################################################################################
+%prep
+
+%autosetup -n %{name}-%{version} -p 1 -S git
+
+# Prior to version 4.4.5, the source code were stored under "jss-<version>/jss"
+# path in the source tarball. Starting from version 4.4.5, the files will be
+# stored under "jss-<version>" path. However, since the build system is still
+# using the old path (introduced via sandboxing), the unpacked source code has
+# to be moved to the old path with the following commands. Otherwise, even
+# though we're linking against system libraries, the build will complain about
+# a missing sandbox.
+
+cd ..
+mv %{name}-%{version} jss
+mkdir %{name}-%{version}
+mv jss %{name}-%{version}
+
+################################################################################
+%build
+
+%if 0%{?fedora} >= 27
+%set_build_flags
+%endif
+
+[ -z "$JAVA_HOME" ] && export JAVA_HOME=%{_jvmdir}/java
+[ -z "$USE_INSTALLED_NSPR" ] && export USE_INSTALLED_NSPR=1
+[ -z "$USE_INSTALLED_NSS" ] && export USE_INSTALLED_NSS=1
+
+# Enable compiler optimizations and disable debugging code
+# NOTE: If you ever need to create a debug build with optimizations disabled
+# just comment out this line and change in the %%install section below the
+# line that copies jars xpclass.jar to be xpclass_dbg.jar
+export BUILD_OPT=1
+
+# Generate symbolic info for debuggers
+XCFLAGS="-g $RPM_OPT_FLAGS"
+export XCFLAGS
+
+PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
+PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1
+
+export PKG_CONFIG_ALLOW_SYSTEM_LIBS
+export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS
+
+NSPR_INCLUDE_DIR=`/usr/bin/pkg-config --cflags-only-I nspr | sed 's/-I//'`
+NSPR_LIB_DIR=`/usr/bin/pkg-config --libs-only-L nspr | sed 's/-L//'`
+
+NSS_INCLUDE_DIR=`/usr/bin/pkg-config --cflags-only-I nss | sed 's/-I//'`
+NSS_LIB_DIR=`/usr/bin/pkg-config --libs-only-L nss | sed 's/-L//'`
+
+export NSPR_INCLUDE_DIR
+export NSPR_LIB_DIR
+export NSS_INCLUDE_DIR
+export NSS_LIB_DIR
+
+%if 0%{?__isa_bits} == 64
+USE_64=1
+export USE_64
+%endif
+
+# The Makefile is not thread-safe
+make -C jss/coreconf
+make -C jss
+make -C jss javadoc
+
+################################################################################
+%install
+
+# Copy the license files here so we can include them in %%doc
+cp -p jss/MPL-1.1.txt .
+cp -p jss/gpl.txt .
+cp -p jss/lgpl.txt .
+
+# There is no install target so we'll do it by hand
+
+# jars
+install -d -m 0755 $RPM_BUILD_ROOT%{_jnidir}
+# NOTE: if doing a debug no opt build change xpclass.jar to xpclass_dbg.jar
+install -m 644 dist/xpclass.jar ${RPM_BUILD_ROOT}%{_jnidir}/jss4.jar
+
+# We have to use the name libjss4.so because this is dynamically
+# loaded by the jar file.
+install -d -m 0755 $RPM_BUILD_ROOT%{_libdir}/jss
+install -m 0755 dist/Linux*.OBJ/lib/libjss4.so ${RPM_BUILD_ROOT}%{_libdir}/jss/
+pushd  ${RPM_BUILD_ROOT}%{_libdir}/jss
+    ln -fs %{_jnidir}/jss4.jar jss4.jar
+popd
+
+# javadoc
+install -d -m 0755 $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version}
+cp -rp dist/jssdoc/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version}
+cp -p jss/jss.html $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version}
+cp -p jss/*.txt $RPM_BUILD_ROOT%{_javadocdir}/%{name}-%{version}
+
+# No ldconfig is required since this library is loaded by Java itself.
+################################################################################
+%files
+
+%defattr(-,root,root,-)
+%doc jss/jss.html jss/MPL-1.1.txt jss/gpl.txt jss/lgpl.txt
+%{_libdir}/jss/*
+%{_jnidir}/*
+%{_libdir}/jss/lib*.so
+
+################################################################################
+%files javadoc
+
+%defattr(-,root,root,-)
+%dir %{_javadocdir}/%{name}-%{version}
+%{_javadocdir}/%{name}-%{version}/*
+
+################################################################################
+%changelog
+* Wed Sep 11 2019 Dogtag PKI Team <pki-devel@redhat.com> 4.4.7-2
+- Bugzilla #1747967 - CVE 2019-14823 jss: OCSP policy "Leaf and Chain" implicitly trusts the root certificate
+
+* Mon Aug  5 2019 Dogtag PKI Team <pki-devel@redhat.com> 4.4.7-1
+- Bugzilla #1733590 - Rebase JSS in RHEL 7.8 (ascheel)
+
+* Fri Mar 15 2019 Dogtag PKI Team <pki-devel@redhat.com> 4.4.6-1
+- Bugzilla #1659527 - Rebase JSS in RHEL 7.7 (ascheel)
+
+* Thu Jul  5 2018 Dogtag PKI Team <pki-devel@redhat.com> 4.4.4-3
+- Bugzilla #1534772 - org.mozilla.jss.pkix.primitive.AlgorithmIdentifier
+  decode/encode process alters original data (cfu)
+- Bugzilla #1554056 - JSS: Add support for TLS_*_SHA384 ciphers (cfu)
+
+* Thu Jun 21 2018 Dogtag PKI Team <pki-devel@redhat.com> 4.4.4-2
+- Red Hat Bugzilla #1560682 - (RFE) Migrate RHCS x509 cert and crl
+  functionality to JSS (jmagne)
+
+* Tue May 29 2018 Dogtag PKI Team <pki-devel@redhat.com> 4.4.4-1
+- Rebased to JSS 4.4.4
+
+* Thu Apr 05 2018 Dogtag PKI Team <pki-devel@redhat.com> 4.4.3-1
+- Rebased to JSS 4.4.3
+#- Red Hat Bugzilla #1548548 - Partial Fedora build flags injection