Path: blob/master/test/jdk/javax/net/ssl/Stapling/SSLSocketWithStapling.java
41152 views
/*1* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223// SunJSSE does not support dynamic system properties, no way to re-use24// system properties in samevm/agentvm mode.2526/*27* @test28* @bug 8046321 815382929* @summary OCSP Stapling for TLS30* @library ../../../../java/security/testlibrary31* @build CertificateBuilder SimpleOCSPServer32* @run main/othervm SSLSocketWithStapling33*/3435import java.io.*;36import java.math.BigInteger;37import java.net.InetAddress;38import java.net.Socket;39import java.net.ServerSocket;40import java.security.GeneralSecurityException;41import java.security.KeyPair;42import java.security.KeyPairGenerator;43import javax.net.ssl.*;44import java.security.KeyStore;45import java.security.PublicKey;46import java.security.Security;47import java.security.cert.CertPathValidator;48import java.security.cert.CertPathValidatorException;49import java.security.cert.CertPathValidatorException.BasicReason;50import java.security.cert.Certificate;51import java.security.cert.PKIXBuilderParameters;52import java.security.cert.X509CertSelector;53import java.security.cert.X509Certificate;54import java.security.cert.PKIXRevocationChecker;55import java.security.cert.PKIXRevocationChecker.Option;56import java.util.ArrayList;57import java.util.Collections;58import java.util.Date;59import java.util.EnumSet;60import java.util.List;61import java.util.Map;62import java.util.HashMap;63import java.util.concurrent.TimeUnit;6465import sun.security.testlibrary.SimpleOCSPServer;66import sun.security.testlibrary.CertificateBuilder;6768public class SSLSocketWithStapling {6970/*71* =============================================================72* Set the various variables needed for the tests, then73* specify what tests to run on each side.74*/7576// Turn on TLS debugging77static final boolean debug = false;7879/*80* Should we run the client or server in a separate thread?81* Both sides can throw exceptions, but do you have a preference82* as to which side should be the main thread.83*/84static boolean separateServerThread = true;85Thread clientThread = null;86Thread serverThread = null;8788static String passwd = "passphrase";89static String ROOT_ALIAS = "root";90static String INT_ALIAS = "intermediate";91static String SSL_ALIAS = "ssl";9293/*94* Is the server ready to serve?95*/96volatile static boolean serverReady = false;97volatile int serverPort = 0;9899volatile Exception serverException = null;100volatile Exception clientException = null;101102// PKI components we will need for this test103static KeyStore rootKeystore; // Root CA Keystore104static KeyStore intKeystore; // Intermediate CA Keystore105static KeyStore serverKeystore; // SSL Server Keystore106static KeyStore trustStore; // SSL Client trust store107static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder108static int rootOcspPort; // Port number for root OCSP109static SimpleOCSPServer intOcsp; // Intermediate CA OCSP Responder110static int intOcspPort; // Port number for intermed. OCSP111112// Extra configuration parameters and constants113static final String[] TLS13ONLY = new String[] { "TLSv1.3" };114static final String[] TLS12MAX =115new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" };116117/*118* If the client or server is doing some kind of object creation119* that the other side depends on, and that thread prematurely120* exits, you may experience a hang. The test harness will121* terminate all hung threads after its timeout has expired,122* currently 3 minutes by default, but you might try to be123* smart about it....124*/125public static void main(String[] args) throws Exception {126if (debug) {127System.setProperty("javax.net.debug", "ssl:handshake");128}129130try {131// Create the PKI we will use for the test and start the OCSP servers132createPKI();133134testAllDefault(false);135testAllDefault(true);136testPKIXParametersRevEnabled(false);137testPKIXParametersRevEnabled(true);138testRevokedCertificate(false);139testRevokedCertificate(true);140testRevokedIntermediate(false);141testRevokedIntermediate(true);142testMissingIntermediate(false);143testMissingIntermediate(true);144testHardFailFallback(false);145testHardFailFallback(true);146testSoftFailFallback(false);147testSoftFailFallback(true);148testLatencyNoStaple(false, false);149testLatencyNoStaple(false, true);150testLatencyNoStaple(true, false);151testLatencyNoStaple(true, true);152} finally {153// shut down the OCSP responders before finishing the test154intOcsp.stop();155rootOcsp.stop();156}157}158159/**160* Default test using no externally-configured PKIXBuilderParameters161*/162static void testAllDefault(boolean isTls13) throws Exception {163ClientParameters cliParams = new ClientParameters();164ServerParameters servParams = new ServerParameters();165if (isTls13) {166cliParams.protocols = TLS13ONLY;167servParams.protocols = TLS13ONLY;168} else {169cliParams.protocols = TLS12MAX;170servParams.protocols = TLS12MAX;171}172serverReady = false;173Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =174new HashMap<>();175176// We will prove revocation checking is disabled by marking the SSL177// certificate as revoked. The test would only pass if revocation178// checking did not happen.179X509Certificate sslCert =180(X509Certificate)serverKeystore.getCertificate(SSL_ALIAS);181Date fiveMinsAgo = new Date(System.currentTimeMillis() -182TimeUnit.MINUTES.toMillis(5));183revInfo.put(sslCert.getSerialNumber(),184new SimpleOCSPServer.CertStatusInfo(185SimpleOCSPServer.CertStatus.CERT_STATUS_REVOKED,186fiveMinsAgo));187intOcsp.updateStatusDb(revInfo);188189System.out.println("=======================================");190System.out.println("Stapling enabled, default configuration");191System.out.println("=======================================");192193SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,194servParams);195TestResult tr = sslTest.getResult();196if (tr.clientExc != null) {197throw tr.clientExc;198} else if (tr.serverExc != null) {199throw tr.serverExc;200}201202// Return the ssl certificate to non-revoked status203revInfo.put(sslCert.getSerialNumber(),204new SimpleOCSPServer.CertStatusInfo(205SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));206intOcsp.updateStatusDb(revInfo);207208System.out.println(" PASS");209System.out.println("=======================================\n");210}211212/**213* Do a basic connection using PKIXParameters with revocation checking214* enabled and client-side OCSP disabled. It will only pass if all215* stapled responses are present, valid and have a GOOD status.216*/217static void testPKIXParametersRevEnabled(boolean isTls13) throws Exception {218ClientParameters cliParams = new ClientParameters();219ServerParameters servParams = new ServerParameters();220if (isTls13) {221cliParams.protocols = TLS13ONLY;222servParams.protocols = TLS13ONLY;223} else {224cliParams.protocols = TLS12MAX;225servParams.protocols = TLS12MAX;226}227serverReady = false;228229System.out.println("=====================================");230System.out.println("Stapling enabled, PKIXParameters with");231System.out.println("Revocation checking enabled ");232System.out.println("=====================================");233234cliParams.pkixParams = new PKIXBuilderParameters(trustStore,235new X509CertSelector());236cliParams.pkixParams.setRevocationEnabled(true);237Security.setProperty("ocsp.enable", "false");238239SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,240servParams);241TestResult tr = sslTest.getResult();242if (tr.clientExc != null) {243throw tr.clientExc;244} else if (tr.serverExc != null) {245throw tr.serverExc;246}247248System.out.println(" PASS");249System.out.println("=====================================\n");250}251252/**253* Perform a test where the certificate is revoked and placed in the254* TLS handshake. Client-side OCSP is disabled, so this test will only255* pass if the OCSP response is found, since we will check the256* CertPathValidatorException reason for revoked status.257*/258static void testRevokedCertificate(boolean isTls13) throws Exception {259ClientParameters cliParams = new ClientParameters();260ServerParameters servParams = new ServerParameters();261if (isTls13) {262cliParams.protocols = TLS13ONLY;263servParams.protocols = TLS13ONLY;264} else {265cliParams.protocols = TLS12MAX;266servParams.protocols = TLS12MAX;267}268serverReady = false;269Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =270new HashMap<>();271272// We will prove revocation checking is disabled by marking the SSL273// certificate as revoked. The test would only pass if revocation274// checking did not happen.275X509Certificate sslCert =276(X509Certificate)serverKeystore.getCertificate(SSL_ALIAS);277Date fiveMinsAgo = new Date(System.currentTimeMillis() -278TimeUnit.MINUTES.toMillis(5));279revInfo.put(sslCert.getSerialNumber(),280new SimpleOCSPServer.CertStatusInfo(281SimpleOCSPServer.CertStatus.CERT_STATUS_REVOKED,282fiveMinsAgo));283intOcsp.updateStatusDb(revInfo);284285System.out.println("============================================");286System.out.println("Stapling enabled, detect revoked certificate");287System.out.println("============================================");288289cliParams.pkixParams = new PKIXBuilderParameters(trustStore,290new X509CertSelector());291cliParams.pkixParams.setRevocationEnabled(true);292Security.setProperty("ocsp.enable", "false");293294SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,295servParams);296TestResult tr = sslTest.getResult();297if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) {298if (tr.clientExc != null) {299throw tr.clientExc;300} else {301throw new RuntimeException(302"Expected client failure, but the client succeeded");303}304}305306// Return the ssl certificate to non-revoked status307revInfo.put(sslCert.getSerialNumber(),308new SimpleOCSPServer.CertStatusInfo(309SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));310intOcsp.updateStatusDb(revInfo);311312System.out.println(" PASS");313System.out.println("=======================================\n");314}315316/**317* Perform a test where the intermediate CA certificate is revoked and318* placed in the TLS handshake. Client-side OCSP is disabled, so this319* test will only pass if the OCSP response for the intermediate CA is320* found and placed into the CertificateStatus or Certificate message321* (depending on the protocol version) since we will check322* the CertPathValidatorException reason for revoked status.323*/324static void testRevokedIntermediate(boolean isTls13) throws Exception {325ClientParameters cliParams = new ClientParameters();326ServerParameters servParams = new ServerParameters();327if (isTls13) {328cliParams.protocols = TLS13ONLY;329servParams.protocols = TLS13ONLY;330} else {331cliParams.protocols = TLS12MAX;332servParams.protocols = TLS12MAX;333}334serverReady = false;335Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =336new HashMap<>();337338// We will prove revocation checking is disabled by marking the SSL339// certificate as revoked. The test would only pass if revocation340// checking did not happen.341X509Certificate intCACert =342(X509Certificate)intKeystore.getCertificate(INT_ALIAS);343Date fiveMinsAgo = new Date(System.currentTimeMillis() -344TimeUnit.MINUTES.toMillis(5));345revInfo.put(intCACert.getSerialNumber(),346new SimpleOCSPServer.CertStatusInfo(347SimpleOCSPServer.CertStatus.CERT_STATUS_REVOKED,348fiveMinsAgo));349rootOcsp.updateStatusDb(revInfo);350351System.out.println("===============================================");352System.out.println("Stapling enabled, detect revoked CA certificate");353System.out.println("===============================================");354355cliParams.pkixParams = new PKIXBuilderParameters(trustStore,356new X509CertSelector());357cliParams.pkixParams.setRevocationEnabled(true);358Security.setProperty("ocsp.enable", "false");359360SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,361servParams);362TestResult tr = sslTest.getResult();363if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) {364if (tr.clientExc != null) {365throw tr.clientExc;366} else {367throw new RuntimeException(368"Expected client failure, but the client succeeded");369}370}371372// Return the ssl certificate to non-revoked status373revInfo.put(intCACert.getSerialNumber(),374new SimpleOCSPServer.CertStatusInfo(375SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));376rootOcsp.updateStatusDb(revInfo);377378System.out.println(" PASS");379System.out.println("=======================================\n");380}381382/**383* Test a case where OCSP stapling is attempted, but partially occurs384* because the root OCSP responder is unreachable. This should use a385* default hard-fail behavior.386*/387static void testMissingIntermediate(boolean isTls13) throws Exception {388ClientParameters cliParams = new ClientParameters();389ServerParameters servParams = new ServerParameters();390if (isTls13) {391cliParams.protocols = TLS13ONLY;392servParams.protocols = TLS13ONLY;393} else {394cliParams.protocols = TLS12MAX;395servParams.protocols = TLS12MAX;396}397serverReady = false;398399// Make the OCSP responder reject connections400rootOcsp.rejectConnections();401402System.out.println("=======================================");403System.out.println("Stapling enbled in client and server,");404System.out.println("but root OCSP responder disabled.");405System.out.println("PKIXParameters with Revocation checking");406System.out.println("enabled.");407System.out.println("=======================================");408409Security.setProperty("ocsp.enable", "false");410cliParams.pkixParams = new PKIXBuilderParameters(trustStore,411new X509CertSelector());412cliParams.pkixParams.setRevocationEnabled(true);413414SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,415servParams);416TestResult tr = sslTest.getResult();417if (!checkClientValidationFailure(tr.clientExc,418BasicReason.UNDETERMINED_REVOCATION_STATUS)) {419if (tr.clientExc != null) {420throw tr.clientExc;421} else {422throw new RuntimeException(423"Expected client failure, but the client succeeded");424}425}426427System.out.println(" PASS");428System.out.println("=======================================\n");429430// Make root OCSP responder accept connections431rootOcsp.acceptConnections();432433// Wait 5 seconds for server ready434for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {435Thread.sleep(50);436}437if (!rootOcsp.isServerReady()) {438throw new RuntimeException("Root OCSP responder not ready yet");439}440}441442/**443* Test a case where client-side stapling is attempted, but does not444* occur because OCSP responders are unreachable. This should use a445* default hard-fail behavior.446*/447static void testHardFailFallback(boolean isTls13) throws Exception {448ClientParameters cliParams = new ClientParameters();449ServerParameters servParams = new ServerParameters();450if (isTls13) {451cliParams.protocols = TLS13ONLY;452servParams.protocols = TLS13ONLY;453} else {454cliParams.protocols = TLS12MAX;455servParams.protocols = TLS12MAX;456}457serverReady = false;458459// make OCSP responders reject connections460intOcsp.rejectConnections();461rootOcsp.rejectConnections();462463System.out.println("=======================================");464System.out.println("Stapling enbled in client and server,");465System.out.println("but OCSP responders disabled.");466System.out.println("PKIXParameters with Revocation checking");467System.out.println("enabled.");468System.out.println("=======================================");469470Security.setProperty("ocsp.enable", "true");471cliParams.pkixParams = new PKIXBuilderParameters(trustStore,472new X509CertSelector());473cliParams.pkixParams.setRevocationEnabled(true);474475SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,476servParams);477TestResult tr = sslTest.getResult();478if (!checkClientValidationFailure(tr.clientExc,479BasicReason.UNDETERMINED_REVOCATION_STATUS)) {480if (tr.clientExc != null) {481throw tr.clientExc;482} else {483throw new RuntimeException(484"Expected client failure, but the client succeeded");485}486}487488System.out.println(" PASS");489System.out.println("=======================================\n");490491// Make OCSP responders accept connections492intOcsp.acceptConnections();493rootOcsp.acceptConnections();494495// Wait 5 seconds for server ready496for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||497!rootOcsp.isServerReady())); i++) {498Thread.sleep(50);499}500if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {501throw new RuntimeException("Server not ready yet");502}503}504505/**506* Test a case where client-side stapling is attempted, but does not507* occur because OCSP responders are unreachable. Client-side OCSP508* checking is enabled for this, with SOFT_FAIL.509*/510static void testSoftFailFallback(boolean isTls13) throws Exception {511ClientParameters cliParams = new ClientParameters();512ServerParameters servParams = new ServerParameters();513if (isTls13) {514cliParams.protocols = TLS13ONLY;515servParams.protocols = TLS13ONLY;516} else {517cliParams.protocols = TLS12MAX;518servParams.protocols = TLS12MAX;519}520serverReady = false;521522// make OCSP responders reject connections523intOcsp.rejectConnections();524rootOcsp.rejectConnections();525526System.out.println("=======================================");527System.out.println("Stapling enbled in client and server,");528System.out.println("but OCSP responders disabled.");529System.out.println("PKIXParameters with Revocation checking");530System.out.println("enabled and SOFT_FAIL.");531System.out.println("=======================================");532533Security.setProperty("ocsp.enable", "true");534cliParams.pkixParams = new PKIXBuilderParameters(trustStore,535new X509CertSelector());536cliParams.pkixParams.setRevocationEnabled(true);537CertPathValidator cpv = CertPathValidator.getInstance("PKIX");538cliParams.revChecker =539(PKIXRevocationChecker)cpv.getRevocationChecker();540cliParams.revChecker.setOptions(EnumSet.of(Option.SOFT_FAIL));541542SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,543servParams);544TestResult tr = sslTest.getResult();545if (tr.clientExc != null) {546throw tr.clientExc;547} else if (tr.serverExc != null) {548throw tr.serverExc;549}550551// make sure getSoftFailExceptions is not empty552if (cliParams.revChecker.getSoftFailExceptions().isEmpty()) {553throw new Exception("No soft fail exceptions");554}555556System.out.println(" PASS");557System.out.println("=======================================\n");558559560// Make OCSP responders accept connections561intOcsp.acceptConnections();562rootOcsp.acceptConnections();563564// Wait 5 seconds for server ready565for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||566!rootOcsp.isServerReady())); i++) {567Thread.sleep(50);568}569if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {570throw new RuntimeException("Server not ready yet");571}572}573574/**575* This test initiates stapling from the client, but the server does not576* support OCSP stapling for this connection. In this case it happens577* because the latency of the OCSP responders is longer than the server578* is willing to wait. To keep the test streamlined, we will set the server579* latency to a 1 second wait, and set the responder latency to 3 seconds.580*581* @param fallback if we allow client-side OCSP fallback, which582* will change the result from the client failing with CPVE (no fallback)583* to a pass (fallback active).584*/585static void testLatencyNoStaple(Boolean fallback, boolean isTls13)586throws Exception {587ClientParameters cliParams = new ClientParameters();588ServerParameters servParams = new ServerParameters();589if (isTls13) {590cliParams.protocols = TLS13ONLY;591servParams.protocols = TLS13ONLY;592} else {593cliParams.protocols = TLS12MAX;594servParams.protocols = TLS12MAX;595}596serverReady = false;597598// Give a 1 second delay before running the test.599intOcsp.setDelay(3000);600rootOcsp.setDelay(3000);601Thread.sleep(1000);602603// Wait 5 seconds for server ready604for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||605!rootOcsp.isServerReady())); i++) {606Thread.sleep(50);607}608if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {609throw new RuntimeException("Server not ready yet");610}611612System.out.println("========================================");613System.out.println("Stapling enbled in client. Server does");614System.out.println("not support stapling due to OCSP latency.");615System.out.println("PKIXParameters with Revocation checking");616System.out.println("enabled, client-side OCSP checking is.");617System.out.println(fallback ? "enabled" : "disabled");618System.out.println("========================================");619620Security.setProperty("ocsp.enable", fallback.toString());621cliParams.pkixParams = new PKIXBuilderParameters(trustStore,622new X509CertSelector());623cliParams.pkixParams.setRevocationEnabled(true);624servParams.respTimeout = 1000;625626SSLSocketWithStapling sslTest = new SSLSocketWithStapling(cliParams,627servParams);628TestResult tr = sslTest.getResult();629630if (fallback) {631if (tr.clientExc != null) {632throw tr.clientExc;633} else if (tr.serverExc != null) {634throw tr.serverExc;635}636} else {637if (!checkClientValidationFailure(tr.clientExc,638BasicReason.UNDETERMINED_REVOCATION_STATUS)) {639if (tr.clientExc != null) {640throw tr.clientExc;641} else {642throw new RuntimeException(643"Expected client failure, but the client succeeded");644}645}646}647System.out.println(" PASS");648System.out.println("========================================\n");649650// Remove the OCSP responder latency651intOcsp.setDelay(0);652rootOcsp.setDelay(0);653Thread.sleep(1000);654655// Wait 5 seconds for server ready656for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||657!rootOcsp.isServerReady())); i++) {658Thread.sleep(50);659}660if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {661throw new RuntimeException("Server not ready yet");662}663}664665/*666* Define the server side of the test.667*668* If the server prematurely exits, serverReady will be set to true669* to avoid infinite hangs.670*/671void doServerSide(ServerParameters servParams) throws Exception {672673// Selectively enable or disable the feature674System.setProperty("jdk.tls.server.enableStatusRequestExtension",675Boolean.toString(servParams.enabled));676677// Set all the other operating parameters678System.setProperty("jdk.tls.stapling.cacheSize",679Integer.toString(servParams.cacheSize));680System.setProperty("jdk.tls.stapling.cacheLifetime",681Integer.toString(servParams.cacheLifetime));682System.setProperty("jdk.tls.stapling.responseTimeout",683Integer.toString(servParams.respTimeout));684System.setProperty("jdk.tls.stapling.responderURI", servParams.respUri);685System.setProperty("jdk.tls.stapling.responderOverride",686Boolean.toString(servParams.respOverride));687System.setProperty("jdk.tls.stapling.ignoreExtensions",688Boolean.toString(servParams.ignoreExts));689690// Set keystores and trust stores for the server691KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");692kmf.init(serverKeystore, passwd.toCharArray());693TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");694tmf.init(trustStore);695696SSLContext sslc = SSLContext.getInstance("TLS");697sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);698699SSLServerSocketFactory sslssf = new CustomizedServerSocketFactory(sslc,700servParams.protocols, servParams.ciphers);701702try (SSLServerSocket sslServerSocket =703(SSLServerSocket) sslssf.createServerSocket(serverPort)) {704705serverPort = sslServerSocket.getLocalPort();706707/*708* Signal Client, we're ready for his connect.709*/710serverReady = true;711712try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();713InputStream sslIS = sslSocket.getInputStream();714OutputStream sslOS = sslSocket.getOutputStream()) {715int numberIn = sslIS.read();716int numberSent = 85;717log("Server received number: " + numberIn);718sslOS.write(numberSent);719sslOS.flush();720log("Server sent number: " + numberSent);721}722}723}724725/*726* Define the client side of the test.727*728* If the server prematurely exits, serverReady will be set to true729* to avoid infinite hangs.730*/731void doClientSide(ClientParameters cliParams) throws Exception {732733// Wait 5 seconds for server ready734for (int i = 0; (i < 100 && !serverReady); i++) {735Thread.sleep(50);736}737if (!serverReady) {738throw new RuntimeException("Server not ready yet");739}740741// Selectively enable or disable the feature742System.setProperty("jdk.tls.client.enableStatusRequestExtension",743Boolean.toString(cliParams.enabled));744745// Create the Trust Manager Factory using the PKIX variant746TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");747748// If we have a customized pkixParameters then use it749if (cliParams.pkixParams != null) {750// LIf we have a customized PKIXRevocationChecker, add751// it to the PKIXBuilderParameters.752if (cliParams.revChecker != null) {753cliParams.pkixParams.addCertPathChecker(cliParams.revChecker);754}755756ManagerFactoryParameters trustParams =757new CertPathTrustManagerParameters(cliParams.pkixParams);758tmf.init(trustParams);759} else {760tmf.init(trustStore);761}762763SSLContext sslc = SSLContext.getInstance("TLS");764sslc.init(null, tmf.getTrustManagers(), null);765766SSLSocketFactory sslsf = new CustomizedSocketFactory(sslc,767cliParams.protocols, cliParams.ciphers);768try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket("localhost",769serverPort);770InputStream sslIS = sslSocket.getInputStream();771OutputStream sslOS = sslSocket.getOutputStream()) {772int numberSent = 80;773sslOS.write(numberSent);774sslOS.flush();775log("Client sent number: " + numberSent);776int numberIn = sslIS.read();777log("Client received number:" + numberIn);778}779}780781/*782* Primary constructor, used to drive remainder of the test.783*784* Fork off the other side, then do your work.785*/786SSLSocketWithStapling(ClientParameters cliParams,787ServerParameters servParams) throws Exception {788Exception startException = null;789try {790if (separateServerThread) {791startServer(servParams, true);792startClient(cliParams, false);793} else {794startClient(cliParams, true);795startServer(servParams, false);796}797} catch (Exception e) {798startException = e;799}800801/*802* Wait for other side to close down.803*/804if (separateServerThread) {805if (serverThread != null) {806serverThread.join();807}808} else {809if (clientThread != null) {810clientThread.join();811}812}813}814815/**816* Checks a validation failure to see if it failed for the reason we think817* it should. This comes in as an SSLException of some sort, but it818* encapsulates a ValidatorException which in turn encapsulates the819* CertPathValidatorException we are interested in.820*821* @param e the exception thrown at the top level822* @param reason the underlying CertPathValidatorException BasicReason823* we are expecting it to have.824*825* @return true if the reason matches up, false otherwise.826*/827static boolean checkClientValidationFailure(Exception e,828BasicReason reason) {829boolean result = false;830831if (e instanceof SSLException) {832Throwable valExc = e.getCause();833if (valExc instanceof sun.security.validator.ValidatorException) {834Throwable cause = valExc.getCause();835if (cause instanceof CertPathValidatorException) {836CertPathValidatorException cpve =837(CertPathValidatorException)cause;838if (cpve.getReason() == reason) {839result = true;840}841}842}843}844return result;845}846847TestResult getResult() {848TestResult tr = new TestResult();849tr.clientExc = clientException;850tr.serverExc = serverException;851return tr;852}853854void startServer(ServerParameters servParams, boolean newThread)855throws Exception {856if (newThread) {857serverThread = new Thread() {858public void run() {859try {860doServerSide(servParams);861} catch (Exception e) {862/*863* Our server thread just died.864*865* Release the client, if not active already...866*/867System.err.println("Server died...");868e.printStackTrace(System.err);869serverReady = true;870serverException = e;871}872}873};874serverThread.start();875} else {876try {877doServerSide(servParams);878} catch (Exception e) {879serverException = e;880} finally {881serverReady = true;882}883}884}885886void startClient(ClientParameters cliParams, boolean newThread)887throws Exception {888if (newThread) {889clientThread = new Thread() {890public void run() {891try {892doClientSide(cliParams);893} catch (Exception e) {894/*895* Our client thread just died.896*/897System.err.println("Client died...");898clientException = e;899}900}901};902clientThread.start();903} else {904try {905doClientSide(cliParams);906} catch (Exception e) {907clientException = e;908}909}910}911912/**913* Creates the PKI components necessary for this test, including914* Root CA, Intermediate CA and SSL server certificates, the keystores915* for each entity, a client trust store, and starts the OCSP responders.916*/917private static void createPKI() throws Exception {918CertificateBuilder cbld = new CertificateBuilder();919KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");920keyGen.initialize(2048);921KeyStore.Builder keyStoreBuilder =922KeyStore.Builder.newInstance("PKCS12", null,923new KeyStore.PasswordProtection(passwd.toCharArray()));924925// Generate Root, IntCA, EE keys926KeyPair rootCaKP = keyGen.genKeyPair();927log("Generated Root CA KeyPair");928KeyPair intCaKP = keyGen.genKeyPair();929log("Generated Intermediate CA KeyPair");930KeyPair sslKP = keyGen.genKeyPair();931log("Generated SSL Cert KeyPair");932933// Set up the Root CA Cert934cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany");935cbld.setPublicKey(rootCaKP.getPublic());936cbld.setSerialNumber(new BigInteger("1"));937// Make a 3 year validity starting from 60 days ago938long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);939long end = start + TimeUnit.DAYS.toMillis(1085);940cbld.setValidity(new Date(start), new Date(end));941addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic());942addCommonCAExts(cbld);943// Make our Root CA Cert!944X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(),945"SHA256withRSA");946log("Root CA Created:\n" + certInfo(rootCert));947948// Now build a keystore and add the keys and cert949rootKeystore = keyStoreBuilder.getKeyStore();950Certificate[] rootChain = {rootCert};951rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(),952passwd.toCharArray(), rootChain);953954// Now fire up the OCSP responder955rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null);956rootOcsp.enableLog(debug);957rootOcsp.setNextUpdateInterval(3600);958rootOcsp.start();959960// Wait 5 seconds for server ready961for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {962Thread.sleep(50);963}964if (!rootOcsp.isServerReady()) {965throw new RuntimeException("Server not ready yet");966}967968rootOcspPort = rootOcsp.getPort();969String rootRespURI = "http://localhost:" + rootOcspPort;970log("Root OCSP Responder URI is " + rootRespURI);971972// Now that we have the root keystore and OCSP responder we can973// create our intermediate CA.974cbld.reset();975cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany");976cbld.setPublicKey(intCaKP.getPublic());977cbld.setSerialNumber(new BigInteger("100"));978// Make a 2 year validity starting from 30 days ago979start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30);980end = start + TimeUnit.DAYS.toMillis(730);981cbld.setValidity(new Date(start), new Date(end));982addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic());983addCommonCAExts(cbld);984cbld.addAIAExt(Collections.singletonList(rootRespURI));985// Make our Intermediate CA Cert!986X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(),987"SHA256withRSA");988log("Intermediate CA Created:\n" + certInfo(intCaCert));989990// Provide intermediate CA cert revocation info to the Root CA991// OCSP responder.992Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =993new HashMap<>();994revInfo.put(intCaCert.getSerialNumber(),995new SimpleOCSPServer.CertStatusInfo(996SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));997rootOcsp.updateStatusDb(revInfo);998999// Now build a keystore and add the keys, chain and root cert as a TA1000intKeystore = keyStoreBuilder.getKeyStore();1001Certificate[] intChain = {intCaCert, rootCert};1002intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(),1003passwd.toCharArray(), intChain);1004intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);10051006// Now fire up the Intermediate CA OCSP responder1007intOcsp = new SimpleOCSPServer(intKeystore, passwd,1008INT_ALIAS, null);1009intOcsp.enableLog(debug);1010intOcsp.setNextUpdateInterval(3600);1011intOcsp.start();10121013// Wait 5 seconds for server ready1014for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {1015Thread.sleep(50);1016}1017if (!intOcsp.isServerReady()) {1018throw new RuntimeException("Server not ready yet");1019}10201021intOcspPort = intOcsp.getPort();1022String intCaRespURI = "http://localhost:" + intOcspPort;1023log("Intermediate CA OCSP Responder URI is " + intCaRespURI);10241025// Last but not least, let's make our SSLCert and add it to its own1026// Keystore1027cbld.reset();1028cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany");1029cbld.setPublicKey(sslKP.getPublic());1030cbld.setSerialNumber(new BigInteger("4096"));1031// Make a 1 year validity starting from 7 days ago1032start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7);1033end = start + TimeUnit.DAYS.toMillis(365);1034cbld.setValidity(new Date(start), new Date(end));10351036// Add extensions1037addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic());1038boolean[] kuBits = {true, false, true, false, false, false,1039false, false, false};1040cbld.addKeyUsageExt(kuBits);1041List<String> ekuOids = new ArrayList<>();1042ekuOids.add("1.3.6.1.5.5.7.3.1");1043ekuOids.add("1.3.6.1.5.5.7.3.2");1044cbld.addExtendedKeyUsageExt(ekuOids);1045cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost"));1046cbld.addAIAExt(Collections.singletonList(intCaRespURI));1047// Make our SSL Server Cert!1048X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(),1049"SHA256withRSA");1050log("SSL Certificate Created:\n" + certInfo(sslCert));10511052// Provide SSL server cert revocation info to the Intermeidate CA1053// OCSP responder.1054revInfo = new HashMap<>();1055revInfo.put(sslCert.getSerialNumber(),1056new SimpleOCSPServer.CertStatusInfo(1057SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));1058intOcsp.updateStatusDb(revInfo);10591060// Now build a keystore and add the keys, chain and root cert as a TA1061serverKeystore = keyStoreBuilder.getKeyStore();1062Certificate[] sslChain = {sslCert, intCaCert, rootCert};1063serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(),1064passwd.toCharArray(), sslChain);1065serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);10661067// And finally a Trust Store for the client1068trustStore = keyStoreBuilder.getKeyStore();1069trustStore.setCertificateEntry(ROOT_ALIAS, rootCert);1070}10711072private static void addCommonExts(CertificateBuilder cbld,1073PublicKey subjKey, PublicKey authKey) throws IOException {1074cbld.addSubjectKeyIdExt(subjKey);1075cbld.addAuthorityKeyIdExt(authKey);1076}10771078private static void addCommonCAExts(CertificateBuilder cbld)1079throws IOException {1080cbld.addBasicConstraintsExt(true, true, -1);1081// Set key usage bits for digitalSignature, keyCertSign and cRLSign1082boolean[] kuBitSettings = {true, false, false, false, false, true,1083true, false, false};1084cbld.addKeyUsageExt(kuBitSettings);1085}10861087/**1088* Helper routine that dumps only a few cert fields rather than1089* the whole toString() output.1090*1091* @param cert an X509Certificate to be displayed1092*1093* @return the String output of the issuer, subject and1094* serial number1095*/1096private static String certInfo(X509Certificate cert) {1097StringBuilder sb = new StringBuilder();1098sb.append("Issuer: ").append(cert.getIssuerX500Principal()).1099append("\n");1100sb.append("Subject: ").append(cert.getSubjectX500Principal()).1101append("\n");1102sb.append("Serial: ").append(cert.getSerialNumber()).append("\n");1103return sb.toString();1104}11051106/**1107* Log a message on stdout1108*1109* @param message The message to log1110*/1111private static void log(String message) {1112if (debug) {1113System.out.println(message);1114}1115}11161117// The following two classes are Simple nested class to group a handful1118// of configuration parameters used before starting a client or server.1119// We'll just access the data members directly for convenience.1120static class ClientParameters {1121boolean enabled = true;1122PKIXBuilderParameters pkixParams = null;1123PKIXRevocationChecker revChecker = null;1124String[] protocols = null;1125String[] ciphers = null;11261127ClientParameters() { }1128}11291130static class ServerParameters {1131boolean enabled = true;1132int cacheSize = 256;1133int cacheLifetime = 3600;1134int respTimeout = 5000;1135String respUri = "";1136boolean respOverride = false;1137boolean ignoreExts = false;1138String[] protocols = null;1139String[] ciphers = null;11401141ServerParameters() { }1142}11431144static class CustomizedSocketFactory extends SSLSocketFactory {1145final SSLContext sslc;1146final String[] protocols;1147final String[] cipherSuites;11481149CustomizedSocketFactory(SSLContext ctx, String[] prots, String[] suites)1150throws GeneralSecurityException {1151super();1152sslc = (ctx != null) ? ctx : SSLContext.getDefault();1153protocols = prots;1154cipherSuites = suites;11551156// Create the Trust Manager Factory using the PKIX variant1157TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");1158}11591160@Override1161public Socket createSocket(Socket s, String host, int port,1162boolean autoClose) throws IOException {1163Socket sock = sslc.getSocketFactory().createSocket(s, host, port,1164autoClose);1165customizeSocket(sock);1166return sock;1167}11681169@Override1170public Socket createSocket(InetAddress host, int port)1171throws IOException {1172Socket sock = sslc.getSocketFactory().createSocket(host, port);1173customizeSocket(sock);1174return sock;1175}11761177@Override1178public Socket createSocket(InetAddress host, int port,1179InetAddress localAddress, int localPort) throws IOException {1180Socket sock = sslc.getSocketFactory().createSocket(host, port,1181localAddress, localPort);1182customizeSocket(sock);1183return sock;1184}11851186@Override1187public Socket createSocket(String host, int port)1188throws IOException {1189Socket sock = sslc.getSocketFactory().createSocket(host, port);1190customizeSocket(sock);1191return sock;1192}11931194@Override1195public Socket createSocket(String host, int port,1196InetAddress localAddress, int localPort)1197throws IOException {1198Socket sock = sslc.getSocketFactory().createSocket(host, port,1199localAddress, localPort);1200customizeSocket(sock);1201return sock;1202}12031204@Override1205public String[] getDefaultCipherSuites() {1206return sslc.getDefaultSSLParameters().getCipherSuites();1207}12081209@Override1210public String[] getSupportedCipherSuites() {1211return sslc.getSupportedSSLParameters().getCipherSuites();1212}12131214private void customizeSocket(Socket sock) {1215if (sock instanceof SSLSocket) {1216if (protocols != null) {1217((SSLSocket)sock).setEnabledProtocols(protocols);1218}1219if (cipherSuites != null) {1220((SSLSocket)sock).setEnabledCipherSuites(cipherSuites);1221}1222}1223}1224}12251226static class CustomizedServerSocketFactory extends SSLServerSocketFactory {1227final SSLContext sslc;1228final String[] protocols;1229final String[] cipherSuites;12301231CustomizedServerSocketFactory(SSLContext ctx, String[] prots, String[] suites)1232throws GeneralSecurityException {1233super();1234sslc = (ctx != null) ? ctx : SSLContext.getDefault();1235protocols = prots;1236cipherSuites = suites;12371238// Create the Trust Manager Factory using the PKIX variant1239TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");1240}12411242@Override1243public ServerSocket createServerSocket(int port) throws IOException {1244ServerSocket sock =1245sslc.getServerSocketFactory().createServerSocket(port);1246customizeSocket(sock);1247return sock;1248}12491250@Override1251public ServerSocket createServerSocket(int port, int backlog)1252throws IOException {1253ServerSocket sock =1254sslc.getServerSocketFactory().createServerSocket(port,1255backlog);1256customizeSocket(sock);1257return sock;1258}12591260@Override1261public ServerSocket createServerSocket(int port, int backlog,1262InetAddress ifAddress) throws IOException {1263ServerSocket sock =1264sslc.getServerSocketFactory().createServerSocket(port,1265backlog, ifAddress);1266customizeSocket(sock);1267return sock;1268}12691270@Override1271public String[] getDefaultCipherSuites() {1272return sslc.getDefaultSSLParameters().getCipherSuites();1273}12741275@Override1276public String[] getSupportedCipherSuites() {1277return sslc.getSupportedSSLParameters().getCipherSuites();1278}12791280private void customizeSocket(ServerSocket sock) {1281if (sock instanceof SSLServerSocket) {1282if (protocols != null) {1283((SSLServerSocket)sock).setEnabledProtocols(protocols);1284}1285if (cipherSuites != null) {1286((SSLServerSocket)sock).setEnabledCipherSuites(cipherSuites);1287}1288}1289}1290}129112921293static class TestResult {1294Exception serverExc = null;1295Exception clientExc = null;1296}12971298}129913001301