Path: blob/master/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java
41152 views
/*1* Copyright (c) 2018, 2019, 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/*24* @test25* @bug 8206929 821288526* @summary ensure that client only resumes a session if certain properties27* of the session are compatible with the new connection28* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=false ResumeChecksClient BASIC29* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=false ResumeChecksClient BASIC30* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient BASIC31* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient BASIC32* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient BASIC33* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient BASIC34* @run main/othervm -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient BASIC35* @run main/othervm -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient VERSION_2_TO_336* @run main/othervm -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient VERSION_3_TO_237* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient CIPHER_SUITE38* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=true ResumeChecksClient SIGNATURE_SCHEME39*40*/4142import javax.net.*;43import javax.net.ssl.*;44import java.io.*;45import java.security.*;46import java.net.*;47import java.util.*;4849public class ResumeChecksClient {5051static String pathToStores = "../../../../javax/net/ssl/etc";52static String keyStoreFile = "keystore";53static String trustStoreFile = "truststore";54static String passwd = "passphrase";5556enum TestMode {57BASIC,58VERSION_2_TO_3,59VERSION_3_TO_2,60CIPHER_SUITE,61SIGNATURE_SCHEME62}6364public static void main(String[] args) throws Exception {6566TestMode mode = TestMode.valueOf(args[0]);6768String keyFilename =69System.getProperty("test.src", "./") + "/" + pathToStores +70"/" + keyStoreFile;71String trustFilename =72System.getProperty("test.src", "./") + "/" + pathToStores +73"/" + trustStoreFile;7475System.setProperty("javax.net.ssl.keyStore", keyFilename);76System.setProperty("javax.net.ssl.keyStorePassword", passwd);77System.setProperty("javax.net.ssl.trustStore", trustFilename);78System.setProperty("javax.net.ssl.trustStorePassword", passwd);7980Server server = startServer();81server.signal();82SSLContext sslContext = SSLContext.getDefault();83while (!server.started) {84Thread.yield();85}86SSLSession firstSession = connect(sslContext, server.port, mode, false);8788server.signal();89long secondStartTime = System.currentTimeMillis();90Thread.sleep(10);91SSLSession secondSession = connect(sslContext, server.port, mode, true);9293server.go = false;94server.signal();9596switch (mode) {97case BASIC:98// fail if session is not resumed99checkResumedSession(firstSession, secondSession);100break;101case VERSION_2_TO_3:102case VERSION_3_TO_2:103case CIPHER_SUITE:104case SIGNATURE_SCHEME:105// fail if a new session is not created106if (secondSession.getCreationTime() <= secondStartTime) {107throw new RuntimeException("Existing session was used");108}109break;110default:111throw new RuntimeException("unknown mode: " + mode);112}113}114115private static class NoSig implements AlgorithmConstraints {116117private final String alg;118119NoSig(String alg) {120this.alg = alg;121}122123124private boolean test(String a) {125return !a.toLowerCase().contains(alg.toLowerCase());126}127128@Override129public boolean permits(Set<CryptoPrimitive> primitives, Key key) {130return true;131}132@Override133public boolean permits(Set<CryptoPrimitive> primitives,134String algorithm, AlgorithmParameters parameters) {135136return test(algorithm);137}138@Override139public boolean permits(Set<CryptoPrimitive> primitives,140String algorithm, Key key, AlgorithmParameters parameters) {141142return test(algorithm);143}144}145146private static SSLSession connect(SSLContext sslContext, int port,147TestMode mode, boolean second) {148149try {150SSLSocket sock = (SSLSocket)151sslContext.getSocketFactory().createSocket();152SSLParameters params = sock.getSSLParameters();153154switch (mode) {155case BASIC:156// do nothing to ensure resumption works157break;158case VERSION_2_TO_3:159if (second) {160params.setProtocols(new String[] {"TLSv1.3"});161} else {162params.setProtocols(new String[] {"TLSv1.2"});163}164break;165case VERSION_3_TO_2:166if (second) {167params.setProtocols(new String[] {"TLSv1.2"});168} else {169params.setProtocols(new String[] {"TLSv1.3"});170}171break;172case CIPHER_SUITE:173if (second) {174params.setCipherSuites(175new String[] {"TLS_AES_256_GCM_SHA384"});176} else {177params.setCipherSuites(178new String[] {"TLS_AES_128_GCM_SHA256"});179}180break;181case SIGNATURE_SCHEME:182AlgorithmConstraints constraints =183params.getAlgorithmConstraints();184if (second) {185params.setAlgorithmConstraints(new NoSig("ecdsa"));186} else {187params.setAlgorithmConstraints(new NoSig("rsa"));188}189break;190default:191throw new RuntimeException("unknown mode: " + mode);192}193sock.setSSLParameters(params);194sock.connect(new InetSocketAddress("localhost", port));195PrintWriter out = new PrintWriter(196new OutputStreamWriter(sock.getOutputStream()));197out.println("message");198out.flush();199BufferedReader reader = new BufferedReader(200new InputStreamReader(sock.getInputStream()));201String inMsg = reader.readLine();202System.out.println("Client received: " + inMsg);203SSLSession result = sock.getSession();204sock.close();205return result;206} catch (Exception ex) {207// unexpected exception208throw new RuntimeException(ex);209}210}211212private static void checkResumedSession(SSLSession initSession,213SSLSession resSession) throws Exception {214StringBuilder diffLog = new StringBuilder();215216// Initial and resumed SSLSessions should have the same creation217// times so they get invalidated together.218long initCt = initSession.getCreationTime();219long resumeCt = resSession.getCreationTime();220if (initCt != resumeCt) {221diffLog.append("Session creation time is different. Initial: ").222append(initCt).append(", Resumed: ").append(resumeCt).223append("\n");224}225226// Ensure that peer and local certificate lists are preserved227if (!Arrays.equals(initSession.getLocalCertificates(),228resSession.getLocalCertificates())) {229diffLog.append("Local certificate mismatch between initial " +230"and resumed sessions\n");231}232233if (!Arrays.equals(initSession.getPeerCertificates(),234resSession.getPeerCertificates())) {235diffLog.append("Peer certificate mismatch between initial " +236"and resumed sessions\n");237}238239// Buffer sizes should also be the same240if (initSession.getApplicationBufferSize() !=241resSession.getApplicationBufferSize()) {242diffLog.append(String.format(243"App Buffer sizes differ: Init: %d, Res: %d\n",244initSession.getApplicationBufferSize(),245resSession.getApplicationBufferSize()));246}247248if (initSession.getPacketBufferSize() !=249resSession.getPacketBufferSize()) {250diffLog.append(String.format(251"Packet Buffer sizes differ: Init: %d, Res: %d\n",252initSession.getPacketBufferSize(),253resSession.getPacketBufferSize()));254}255256// Cipher suite should match257if (!initSession.getCipherSuite().equals(258resSession.getCipherSuite())) {259diffLog.append(String.format(260"CipherSuite does not match - Init: %s, Res: %s\n",261initSession.getCipherSuite(), resSession.getCipherSuite()));262}263264// Peer host/port should match265if (!initSession.getPeerHost().equals(resSession.getPeerHost()) ||266initSession.getPeerPort() != resSession.getPeerPort()) {267diffLog.append(String.format(268"Host/Port mismatch - Init: %s/%d, Res: %s/%d\n",269initSession.getPeerHost(), initSession.getPeerPort(),270resSession.getPeerHost(), resSession.getPeerPort()));271}272273// Check protocol274if (!initSession.getProtocol().equals(resSession.getProtocol())) {275diffLog.append(String.format(276"Protocol mismatch - Init: %s, Res: %s\n",277initSession.getProtocol(), resSession.getProtocol()));278}279280// If the StringBuilder has any data in it then one of the checks281// above failed and we should throw an exception.282if (diffLog.length() > 0) {283throw new RuntimeException(diffLog.toString());284}285}286287private static Server startServer() {288Server server = new Server();289new Thread(server).start();290return server;291}292293private static class Server implements Runnable {294295public volatile boolean go = true;296private boolean signal = false;297public volatile int port = 0;298public volatile boolean started = false;299300private synchronized void waitForSignal() {301while (!signal) {302try {303wait();304} catch (InterruptedException ex) {305// do nothing306}307}308signal = false;309}310public synchronized void signal() {311signal = true;312notify();313}314315@Override316public void run() {317try {318319SSLContext sc = SSLContext.getDefault();320ServerSocketFactory fac = sc.getServerSocketFactory();321SSLServerSocket ssock = (SSLServerSocket)322fac.createServerSocket(0);323this.port = ssock.getLocalPort();324325waitForSignal();326started = true;327while (go) {328try {329System.out.println("Waiting for connection");330Socket sock = ssock.accept();331BufferedReader reader = new BufferedReader(332new InputStreamReader(sock.getInputStream()));333String line = reader.readLine();334System.out.println("server read: " + line);335PrintWriter out = new PrintWriter(336new OutputStreamWriter(sock.getOutputStream()));337out.println(line);338out.flush();339waitForSignal();340} catch (Exception ex) {341ex.printStackTrace();342}343}344} catch (Exception ex) {345throw new RuntimeException(ex);346}347}348}349}350351352