Path: blob/master/test/jdk/javax/net/ssl/ServerName/SSLSocketConsistentSNI.java
41152 views
/*1* Copyright (c) 2012, 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 706832131* @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server32* @run main/othervm SSLSocketConsistentSNI33*/3435import java.io.*;36import java.nio.*;37import java.nio.channels.*;38import java.util.*;39import java.net.*;40import javax.net.ssl.*;4142public class SSLSocketConsistentSNI {4344/*45* =============================================================46* Set the various variables needed for the tests, then47* specify what tests to run on each side.48*/4950/*51* Should we run the client or server in a separate thread?52* Both sides can throw exceptions, but do you have a preference53* as to which side should be the main thread.54*/55static boolean separateServerThread = true;5657/*58* Where do we find the keystores?59*/60static String pathToStores = "../etc";61static String keyStoreFile = "keystore";62static String trustStoreFile = "truststore";63static String passwd = "passphrase";6465/*66* Is the server ready to serve?67*/68volatile static boolean serverReady = false;6970/*71* Turn on SSL debugging?72*/73static boolean debug = false;7475/*76* If the client or server is doing some kind of object creation77* that the other side depends on, and that thread prematurely78* exits, you may experience a hang. The test harness will79* terminate all hung threads after its timeout has expired,80* currently 3 minutes by default, but you might try to be81* smart about it....82*/8384/*85* Define the server side of the test.86*87* If the server prematurely exits, serverReady will be set to true88* to avoid infinite hangs.89*/90void doServerSide() throws Exception {91SSLServerSocketFactory sslssf =92(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();93SSLServerSocket sslServerSocket =94(SSLServerSocket) sslssf.createServerSocket(serverPort);9596SNIMatcher matcher = SNIHostName.createSNIMatcher(97serverAcceptableHostname);98Collection<SNIMatcher> matchers = new ArrayList<>(1);99matchers.add(matcher);100SSLParameters params = sslServerSocket.getSSLParameters();101params.setSNIMatchers(matchers);102sslServerSocket.setSSLParameters(params);103104serverPort = sslServerSocket.getLocalPort();105106/*107* Signal Client, we're ready for his connect.108*/109serverReady = true;110111SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();112try {113InputStream sslIS = sslSocket.getInputStream();114OutputStream sslOS = sslSocket.getOutputStream();115116sslIS.read();117sslOS.write(85);118sslOS.flush();119120ExtendedSSLSession session =121(ExtendedSSLSession)sslSocket.getSession();122checkSNIInSession(session);123} finally {124sslSocket.close();125sslServerSocket.close();126}127}128129130/*131* Define the client side of the test.132*133* If the server prematurely exits, serverReady will be set to true134* to avoid infinite hangs.135*/136void doClientSide() throws Exception {137138/*139* Wait for server to get started.140*/141while (!serverReady) {142Thread.sleep(50);143}144145SSLSocketFactory sslsf =146(SSLSocketFactory) SSLSocketFactory.getDefault();147SSLSocket sslSocket = (SSLSocket)148sslsf.createSocket("localhost", serverPort);149150SNIHostName serverName = new SNIHostName(clientRequestedHostname);151List<SNIServerName> serverNames = new ArrayList<>(1);152serverNames.add(serverName);153SSLParameters params = sslSocket.getSSLParameters();154params.setServerNames(serverNames);155sslSocket.setSSLParameters(params);156157try {158InputStream sslIS = sslSocket.getInputStream();159OutputStream sslOS = sslSocket.getOutputStream();160161sslOS.write(280);162sslOS.flush();163sslIS.read();164165ExtendedSSLSession session =166(ExtendedSSLSession)sslSocket.getSession();167checkSNIInSession(session);168} finally {169sslSocket.close();170}171}172173private static String clientRequestedHostname = "www.example.com";174private static String serverAcceptableHostname = "www\\.example\\.com";175176void checkSNIInSession(ExtendedSSLSession session) throws Exception {177List<SNIServerName> sessionSNI = session.getRequestedServerNames();178if (sessionSNI.isEmpty()) {179throw new Exception(180"unexpected empty request server name indication");181}182183if (sessionSNI.size() != 1) {184throw new Exception(185"unexpected request server name indication");186}187188SNIServerName serverName = sessionSNI.get(0);189if (!(serverName instanceof SNIHostName)) {190throw new Exception(191"unexpected instance of request server name indication");192}193194String hostname = ((SNIHostName)serverName).getAsciiName();195if (!clientRequestedHostname.equalsIgnoreCase(hostname)) {196throw new Exception(197"unexpected request server name indication value");198}199}200201/*202* =============================================================203* The remainder is just support stuff204*/205206// use any free port by default207volatile int serverPort = 0;208209volatile Exception serverException = null;210volatile Exception clientException = null;211212public static void main(String[] args) throws Exception {213String keyFilename =214System.getProperty("test.src", ".") + "/" + pathToStores +215"/" + keyStoreFile;216String trustFilename =217System.getProperty("test.src", ".") + "/" + pathToStores +218"/" + trustStoreFile;219220System.setProperty("javax.net.ssl.keyStore", keyFilename);221System.setProperty("javax.net.ssl.keyStorePassword", passwd);222System.setProperty("javax.net.ssl.trustStore", trustFilename);223System.setProperty("javax.net.ssl.trustStorePassword", passwd);224225if (debug)226System.setProperty("javax.net.debug", "all");227228/*229* Start the tests.230*/231new SSLSocketConsistentSNI();232}233234Thread clientThread = null;235Thread serverThread = null;236237/*238* Primary constructor, used to drive remainder of the test.239*240* Fork off the other side, then do your work.241*/242SSLSocketConsistentSNI() throws Exception {243try {244if (separateServerThread) {245startServer(true);246startClient(false);247} else {248startClient(true);249startServer(false);250}251} catch (Exception e) {252// swallow for now. Show later253}254255/*256* Wait for other side to close down.257*/258if (separateServerThread) {259serverThread.join();260} else {261clientThread.join();262}263264/*265* When we get here, the test is pretty much over.266* Which side threw the error?267*/268Exception local;269Exception remote;270String whichRemote;271272if (separateServerThread) {273remote = serverException;274local = clientException;275whichRemote = "server";276} else {277remote = clientException;278local = serverException;279whichRemote = "client";280}281282/*283* If both failed, return the curthread's exception, but also284* print the remote side Exception285*/286if ((local != null) && (remote != null)) {287System.out.println(whichRemote + " also threw:");288remote.printStackTrace();289System.out.println();290throw local;291}292293if (remote != null) {294throw remote;295}296297if (local != null) {298throw local;299}300}301302void startServer(boolean newThread) throws Exception {303if (newThread) {304serverThread = new Thread() {305public void run() {306try {307doServerSide();308} catch (Exception e) {309/*310* Our server thread just died.311*312* Release the client, if not active already...313*/314System.err.println("Server died...");315serverReady = true;316serverException = e;317}318}319};320serverThread.start();321} else {322try {323doServerSide();324} catch (Exception e) {325serverException = e;326} finally {327serverReady = true;328}329}330}331332void startClient(boolean newThread) throws Exception {333if (newThread) {334clientThread = new Thread() {335public void run() {336try {337doClientSide();338} catch (Exception e) {339/*340* Our client thread just died.341*/342System.err.println("Client died...");343clientException = e;344}345}346};347clientThread.start();348} else {349try {350doClientSide();351} catch (Exception e) {352clientException = e;353}354}355}356}357358359