Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/ssl/SSLSessionImpl/ResumeChecksClient.java
38853 views
/*1* Copyright (c) 2018, 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 ResumeChecksClient BASIC29* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksClient BASIC30* @run main/othervm ResumeChecksClient BASIC31* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 ResumeChecksClient VERSION_2_TO_332* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 ResumeChecksClient VERSION_3_TO_233* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksClient CIPHER_SUITE34* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksClient SIGNATURE_SCHEME35*36*/3738import javax.net.*;39import javax.net.ssl.*;40import java.io.*;41import java.security.*;42import java.net.*;43import java.util.*;4445public class ResumeChecksClient {4647static String pathToStores = "../../../../javax/net/ssl/etc";48static String keyStoreFile = "keystore";49static String trustStoreFile = "truststore";50static String passwd = "passphrase";5152enum TestMode {53BASIC,54VERSION_2_TO_3,55VERSION_3_TO_2,56CIPHER_SUITE,57SIGNATURE_SCHEME58}5960public static void main(String[] args) throws Exception {6162TestMode mode = TestMode.valueOf(args[0]);6364String keyFilename =65System.getProperty("test.src", "./") + "/" + pathToStores +66"/" + keyStoreFile;67String trustFilename =68System.getProperty("test.src", "./") + "/" + pathToStores +69"/" + trustStoreFile;7071System.setProperty("javax.net.ssl.keyStore", keyFilename);72System.setProperty("javax.net.ssl.keyStorePassword", passwd);73System.setProperty("javax.net.ssl.trustStore", trustFilename);74System.setProperty("javax.net.ssl.trustStorePassword", passwd);7576Server server = startServer();77server.signal();78SSLContext sslContext = SSLContext.getDefault();79while (!server.started) {80Thread.yield();81}82SSLSession firstSession = connect(sslContext, server.port, mode, false);8384server.signal();85long secondStartTime = System.currentTimeMillis();86Thread.sleep(10);87SSLSession secondSession = connect(sslContext, server.port, mode, true);8889server.go = false;90server.signal();9192switch (mode) {93case BASIC:94// fail if session is not resumed95checkResumedSession(firstSession, secondSession);96break;97case VERSION_2_TO_3:98case VERSION_3_TO_2:99case CIPHER_SUITE:100case SIGNATURE_SCHEME:101// fail if a new session is not created102if (secondSession.getCreationTime() <= secondStartTime) {103throw new RuntimeException("Existing session was used");104}105break;106default:107throw new RuntimeException("unknown mode: " + mode);108}109}110111private static class NoSig implements AlgorithmConstraints {112113private final String alg;114115NoSig(String alg) {116this.alg = alg;117}118119120private boolean test(String a) {121return !a.toLowerCase().contains(alg.toLowerCase());122}123124@Override125public boolean permits(Set<CryptoPrimitive> primitives, Key key) {126return true;127}128@Override129public boolean permits(Set<CryptoPrimitive> primitives,130String algorithm, AlgorithmParameters parameters) {131132return test(algorithm);133}134@Override135public boolean permits(Set<CryptoPrimitive> primitives,136String algorithm, Key key, AlgorithmParameters parameters) {137138return test(algorithm);139}140}141142private static SSLSession connect(SSLContext sslContext, int port,143TestMode mode, boolean second) {144145try {146SSLSocket sock = (SSLSocket)147sslContext.getSocketFactory().createSocket();148SSLParameters params = sock.getSSLParameters();149150switch (mode) {151case BASIC:152// do nothing to ensure resumption works153break;154case VERSION_2_TO_3:155if (second) {156params.setProtocols(new String[] {"TLSv1.3"});157} else {158params.setProtocols(new String[] {"TLSv1.2"});159}160break;161case VERSION_3_TO_2:162if (second) {163params.setProtocols(new String[] {"TLSv1.2"});164} else {165params.setProtocols(new String[] {"TLSv1.3"});166}167break;168case CIPHER_SUITE:169if (second) {170params.setCipherSuites(171new String[] {"TLS_AES_256_GCM_SHA384"});172} else {173params.setCipherSuites(174new String[] {"TLS_AES_128_GCM_SHA256"});175}176break;177case SIGNATURE_SCHEME:178AlgorithmConstraints constraints =179params.getAlgorithmConstraints();180if (second) {181params.setAlgorithmConstraints(new NoSig("ecdsa"));182} else {183params.setAlgorithmConstraints(new NoSig("rsa"));184}185break;186default:187throw new RuntimeException("unknown mode: " + mode);188}189sock.setSSLParameters(params);190sock.connect(new InetSocketAddress("localhost", port));191PrintWriter out = new PrintWriter(192new OutputStreamWriter(sock.getOutputStream()));193out.println("message");194out.flush();195BufferedReader reader = new BufferedReader(196new InputStreamReader(sock.getInputStream()));197String inMsg = reader.readLine();198System.out.println("Client received: " + inMsg);199SSLSession result = sock.getSession();200sock.close();201return result;202} catch (Exception ex) {203// unexpected exception204throw new RuntimeException(ex);205}206}207208private static void checkResumedSession(SSLSession initSession,209SSLSession resSession) throws Exception {210StringBuilder diffLog = new StringBuilder();211212// Initial and resumed SSLSessions should have the same creation213// times so they get invalidated together.214long initCt = initSession.getCreationTime();215long resumeCt = resSession.getCreationTime();216if (initCt != resumeCt) {217diffLog.append("Session creation time is different. Initial: ").218append(initCt).append(", Resumed: ").append(resumeCt).219append("\n");220}221222// Ensure that peer and local certificate lists are preserved223if (!Arrays.equals(initSession.getLocalCertificates(),224resSession.getLocalCertificates())) {225diffLog.append("Local certificate mismatch between initial " +226"and resumed sessions\n");227}228229if (!Arrays.equals(initSession.getPeerCertificates(),230resSession.getPeerCertificates())) {231diffLog.append("Peer certificate mismatch between initial " +232"and resumed sessions\n");233}234235// Buffer sizes should also be the same236if (initSession.getApplicationBufferSize() !=237resSession.getApplicationBufferSize()) {238diffLog.append(String.format(239"App Buffer sizes differ: Init: %d, Res: %d\n",240initSession.getApplicationBufferSize(),241resSession.getApplicationBufferSize()));242}243244if (initSession.getPacketBufferSize() !=245resSession.getPacketBufferSize()) {246diffLog.append(String.format(247"Packet Buffer sizes differ: Init: %d, Res: %d\n",248initSession.getPacketBufferSize(),249resSession.getPacketBufferSize()));250}251252// Cipher suite should match253if (!initSession.getCipherSuite().equals(254resSession.getCipherSuite())) {255diffLog.append(String.format(256"CipherSuite does not match - Init: %s, Res: %s\n",257initSession.getCipherSuite(), resSession.getCipherSuite()));258}259260// Peer host/port should match261if (!initSession.getPeerHost().equals(resSession.getPeerHost()) ||262initSession.getPeerPort() != resSession.getPeerPort()) {263diffLog.append(String.format(264"Host/Port mismatch - Init: %s/%d, Res: %s/%d\n",265initSession.getPeerHost(), initSession.getPeerPort(),266resSession.getPeerHost(), resSession.getPeerPort()));267}268269// Check protocol270if (!initSession.getProtocol().equals(resSession.getProtocol())) {271diffLog.append(String.format(272"Protocol mismatch - Init: %s, Res: %s\n",273initSession.getProtocol(), resSession.getProtocol()));274}275276// If the StringBuilder has any data in it then one of the checks277// above failed and we should throw an exception.278if (diffLog.length() > 0) {279throw new RuntimeException(diffLog.toString());280}281}282283private static Server startServer() {284Server server = new Server();285new Thread(server).start();286return server;287}288289private static class Server implements Runnable {290291public volatile boolean go = true;292private boolean signal = false;293public volatile int port = 0;294public volatile boolean started = false;295296private synchronized void waitForSignal() {297while (!signal) {298try {299wait();300} catch (InterruptedException ex) {301// do nothing302}303}304signal = false;305}306public synchronized void signal() {307signal = true;308notify();309}310311@Override312public void run() {313try {314315SSLContext sc = SSLContext.getDefault();316ServerSocketFactory fac = sc.getServerSocketFactory();317SSLServerSocket ssock = (SSLServerSocket)318fac.createServerSocket(0);319this.port = ssock.getLocalPort();320321waitForSignal();322started = true;323while (go) {324try {325System.out.println("Waiting for connection");326Socket sock = ssock.accept();327BufferedReader reader = new BufferedReader(328new InputStreamReader(sock.getInputStream()));329String line = reader.readLine();330System.out.println("server read: " + line);331PrintWriter out = new PrintWriter(332new OutputStreamWriter(sock.getOutputStream()));333out.println(line);334out.flush();335waitForSignal();336} catch (Exception ex) {337ex.printStackTrace();338}339}340} catch (Exception ex) {341throw new RuntimeException(ex);342}343}344}345}346347348