Path: blob/master/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorer.java
41152 views
/*1* Copyright (c) 2012, 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// SunJSSE does not support dynamic system properties, no way to re-use25// system properties in samevm/agentvm mode.26//2728/**29* @test30* @bug 7068321 819049231* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server32* @library ../templates33* @build SSLCapabilities SSLExplorer34* @run main/othervm SSLSocketExplorer SSLv2Hello,SSLv335* @run main/othervm SSLSocketExplorer SSLv336* @run main/othervm SSLSocketExplorer TLSv137* @run main/othervm SSLSocketExplorer TLSv1.138* @run main/othervm SSLSocketExplorer TLSv1.239*/4041import java.io.*;42import java.nio.*;43import java.nio.channels.*;44import java.util.*;45import java.net.*;46import javax.net.ssl.*;47import java.security.Security;4849public class SSLSocketExplorer {5051/*52* =============================================================53* Set the various variables needed for the tests, then54* specify what tests to run on each side.55*/5657/*58* Should we run the client or server in a separate thread?59* Both sides can throw exceptions, but do you have a preference60* as to which side should be the main thread.61*/62static boolean separateServerThread = true;6364/*65* Where do we find the keystores?66*/67static String pathToStores = "../etc";68static String keyStoreFile = "keystore";69static String trustStoreFile = "truststore";70static String passwd = "passphrase";7172/*73* Is the server ready to serve?74*/75volatile static boolean serverReady = false;7677/*78* Turn on SSL debugging?79*/80static boolean debug = false;8182/*83* If the client or server is doing some kind of object creation84* that the other side depends on, and that thread prematurely85* exits, you may experience a hang. The test harness will86* terminate all hung threads after its timeout has expired,87* currently 3 minutes by default, but you might try to be88* smart about it....89*/9091/*92* Define the server side of the test.93*94* If the server prematurely exits, serverReady will be set to true95* to avoid infinite hangs.96*/97void doServerSide() throws Exception {9899ServerSocket serverSocket = new ServerSocket(serverPort);100101// Signal Client, we're ready for his connect.102serverPort = serverSocket.getLocalPort();103serverReady = true;104105Socket socket = serverSocket.accept();106InputStream ins = socket.getInputStream();107108byte[] buffer = new byte[0xFF];109int position = 0;110SSLCapabilities capabilities = null;111112// Read the header of TLS record113while (position < SSLExplorer.RECORD_HEADER_SIZE) {114int count = SSLExplorer.RECORD_HEADER_SIZE - position;115int n = ins.read(buffer, position, count);116if (n < 0) {117throw new Exception("unexpected end of stream!");118}119position += n;120}121122int recordLength = SSLExplorer.getRequiredSize(buffer, 0, position);123if (buffer.length < recordLength) {124buffer = Arrays.copyOf(buffer, recordLength);125}126127while (position < recordLength) {128int count = recordLength - position;129int n = ins.read(buffer, position, count);130if (n < 0) {131throw new Exception("unexpected end of stream!");132}133position += n;134}135136capabilities = SSLExplorer.explore(buffer, 0, recordLength);;137if (capabilities != null) {138System.out.println("Record version: " +139capabilities.getRecordVersion());140System.out.println("Hello version: " +141capabilities.getHelloVersion());142}143144SSLSocketFactory sslsf =145(SSLSocketFactory) SSLSocketFactory.getDefault();146ByteArrayInputStream bais =147new ByteArrayInputStream(buffer, 0, position);148SSLSocket sslSocket = (SSLSocket)sslsf.createSocket(socket, bais, true);149150// Enable all supported protocols on server side to test SSLv3151sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());152153InputStream sslIS = sslSocket.getInputStream();154OutputStream sslOS = sslSocket.getOutputStream();155156sslIS.read();157sslOS.write(85);158sslOS.flush();159160ExtendedSSLSession session = (ExtendedSSLSession)sslSocket.getSession();161checkCapabilities(capabilities, session);162163sslSocket.close();164serverSocket.close();165}166167168/*169* Define the client side of the test.170*171* If the server prematurely exits, serverReady will be set to true172* to avoid infinite hangs.173*/174void doClientSide() throws Exception {175176/*177* Wait for server to get started.178*/179while (!serverReady) {180Thread.sleep(50);181}182183SSLSocketFactory sslsf =184(SSLSocketFactory) SSLSocketFactory.getDefault();185SSLSocket sslSocket = (SSLSocket)186sslsf.createSocket("localhost", serverPort);187188// enable the specified TLS protocol189sslSocket.setEnabledProtocols(supportedProtocols);190191InputStream sslIS = sslSocket.getInputStream();192OutputStream sslOS = sslSocket.getOutputStream();193194sslOS.write(280);195sslOS.flush();196sslIS.read();197198sslSocket.close();199}200201void checkCapabilities(SSLCapabilities capabilities,202ExtendedSSLSession session) throws Exception {203204List<SNIServerName> sessionSNI = session.getRequestedServerNames();205if (!sessionSNI.equals(capabilities.getServerNames())) {206throw new Exception(207"server name indication does not match capabilities");208}209}210211private static String[] supportedProtocols; // supported protocols212213private static void parseArguments(String[] args) {214supportedProtocols = args[0].split(",");215}216217218/*219* =============================================================220* The remainder is just support stuff221*/222223// use any free port by default224volatile int serverPort = 0;225226volatile Exception serverException = null;227volatile Exception clientException = null;228229public static void main(String[] args) throws Exception {230// reset the security property to make sure that the algorithms231// and keys used in this test are not disabled.232Security.setProperty("jdk.tls.disabledAlgorithms", "");233234String keyFilename =235System.getProperty("test.src", ".") + "/" + pathToStores +236"/" + keyStoreFile;237String trustFilename =238System.getProperty("test.src", ".") + "/" + pathToStores +239"/" + trustStoreFile;240241System.setProperty("javax.net.ssl.keyStore", keyFilename);242System.setProperty("javax.net.ssl.keyStorePassword", passwd);243System.setProperty("javax.net.ssl.trustStore", trustFilename);244System.setProperty("javax.net.ssl.trustStorePassword", passwd);245246if (debug)247System.setProperty("javax.net.debug", "all");248249/*250* Get the customized arguments.251*/252parseArguments(args);253254/*255* Start the tests.256*/257new SSLSocketExplorer();258}259260Thread clientThread = null;261Thread serverThread = null;262263/*264* Primary constructor, used to drive remainder of the test.265*266* Fork off the other side, then do your work.267*/268SSLSocketExplorer() throws Exception {269try {270if (separateServerThread) {271startServer(true);272startClient(false);273} else {274startClient(true);275startServer(false);276}277} catch (Exception e) {278// swallow for now. Show later279}280281/*282* Wait for other side to close down.283*/284if (separateServerThread) {285serverThread.join();286} else {287clientThread.join();288}289290/*291* When we get here, the test is pretty much over.292* Which side threw the error?293*/294Exception local;295Exception remote;296String whichRemote;297298if (separateServerThread) {299remote = serverException;300local = clientException;301whichRemote = "server";302} else {303remote = clientException;304local = serverException;305whichRemote = "client";306}307308/*309* If both failed, return the curthread's exception, but also310* print the remote side Exception311*/312if ((local != null) && (remote != null)) {313System.out.println(whichRemote + " also threw:");314remote.printStackTrace();315System.out.println();316throw local;317}318319if (remote != null) {320throw remote;321}322323if (local != null) {324throw local;325}326}327328void startServer(boolean newThread) throws Exception {329if (newThread) {330serverThread = new Thread() {331public void run() {332try {333doServerSide();334} catch (Exception e) {335/*336* Our server thread just died.337*338* Release the client, if not active already...339*/340System.err.println("Server died...");341serverReady = true;342serverException = e;343}344}345};346serverThread.start();347} else {348try {349doServerSide();350} catch (Exception e) {351serverException = e;352} finally {353serverReady = true;354}355}356}357358void startClient(boolean newThread) throws Exception {359if (newThread) {360clientThread = new Thread() {361public void run() {362try {363doClientSide();364} catch (Exception e) {365/*366* Our client thread just died.367*/368System.err.println("Client died...");369clientException = e;370}371}372};373clientThread.start();374} else {375try {376doClientSide();377} catch (Exception e) {378clientException = e;379}380}381}382}383384385