Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java
38889 views
/*1* Copyright (c) 2016, 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 814456631* @summary Custom HostnameVerifier disables SNI extension32* @run main/othervm ImpactOnSNI33*/3435import java.io.*;36import java.net.*;37import javax.net.ssl.*;3839public class ImpactOnSNI {4041/*42* =============================================================43* Set the various variables needed for the tests, then44* specify what tests to run on each side.45*/4647/*48* Should we run the client or server in a separate thread?49* Both sides can throw exceptions, but do you have a preference50* as to which side should be the main thread.51*/52private static final boolean separateServerThread = true;5354/*55* Where do we find the keystores?56*/57private static final String pathToStores =58"../../../../../../javax/net/ssl/etc";59private static final String keyStoreFile = "keystore";60private static final String trustStoreFile = "truststore";61private static final String passwd = "passphrase";6263/*64* Is the server ready to serve?65*/66private static volatile boolean serverReady = false;6768/*69* Is the connection ready to close?70*/71private static volatile boolean closeReady = false;7273/*74* Turn on SSL debugging?75*/76private static final boolean debug = false;7778/*79* Message posted80*/81private static final String postMsg = "HTTP post on a https server";8283/*84* the fully qualified domain name of localhost85*/86private static String hostname = null;8788/*89* If the client or server is doing some kind of object creation90* that the other side depends on, and that thread prematurely91* exits, you may experience a hang. The test harness will92* terminate all hung threads after its timeout has expired,93* currently 3 minutes by default, but you might try to be94* smart about it....95*/9697/*98* Define the server side of the test.99*100* If the server prematurely exits, serverReady will be set to true101* to avoid infinite hangs.102*/103private void doServerSide() throws Exception {104SSLServerSocketFactory sslssf =105(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();106try (SSLServerSocket sslServerSocket =107(SSLServerSocket)sslssf.createServerSocket(serverPort)) {108109serverPort = sslServerSocket.getLocalPort();110111/*112* Signal Client, we're ready for his connect.113*/114serverReady = true;115116/*117* Accept connections118*/119try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {120InputStream sslIS = sslSocket.getInputStream();121OutputStream sslOS = sslSocket.getOutputStream();122BufferedReader br =123new BufferedReader(new InputStreamReader(sslIS));124PrintStream ps = new PrintStream(sslOS);125126// process HTTP POST request from client127System.out.println("status line: " + br.readLine());128String msg = null;129while ((msg = br.readLine()) != null && msg.length() > 0);130131msg = br.readLine();132if (msg.equals(postMsg)) {133ps.println("HTTP/1.1 200 OK\n\n");134} else {135ps.println("HTTP/1.1 500 Not OK\n\n");136}137ps.flush();138139ExtendedSSLSession session =140(ExtendedSSLSession)sslSocket.getSession();141if (session.getRequestedServerNames().isEmpty()) {142throw new Exception("No expected Server Name Indication");143}144145// close the socket146while (!closeReady) {147Thread.sleep(50);148}149}150}151}152153/*154* Define the client side of the test.155*156* If the server prematurely exits, serverReady will be set to true157* to avoid infinite hangs.158*/159private void doClientSide() throws Exception {160/*161* Wait for server to get started.162*/163while (!serverReady) {164Thread.sleep(50);165}166167// Send HTTP POST request to server168URL url = new URL("https://" + hostname + ":" + serverPort);169170HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());171HttpsURLConnection http = (HttpsURLConnection)url.openConnection();172http.setDoOutput(true);173174http.setRequestMethod("POST");175PrintStream ps = new PrintStream(http.getOutputStream());176try {177ps.println(postMsg);178ps.flush();179if (http.getResponseCode() != 200) {180throw new RuntimeException("test Failed");181}182} finally {183ps.close();184http.disconnect();185closeReady = true;186}187}188189private static class NameVerifier implements HostnameVerifier {190public boolean verify(String hostname, SSLSession session) {191return true;192}193}194195/*196* =============================================================197* The remainder is just support stuff198*/199200// use any free port by default201private volatile int serverPort = 0;202203private volatile Exception serverException = null;204private volatile Exception clientException = null;205206public static void main(String[] args) throws Exception {207String keyFilename =208System.getProperty("test.src", "./") + "/" + pathToStores +209"/" + keyStoreFile;210String trustFilename =211System.getProperty("test.src", "./") + "/" + pathToStores +212"/" + trustStoreFile;213214System.setProperty("javax.net.ssl.keyStore", keyFilename);215System.setProperty("javax.net.ssl.keyStorePassword", passwd);216System.setProperty("javax.net.ssl.trustStore", trustFilename);217System.setProperty("javax.net.ssl.trustStorePassword", passwd);218219if (debug) {220System.setProperty("javax.net.debug", "all");221}222223try {224hostname = InetAddress.getLocalHost().getCanonicalHostName();225} catch (UnknownHostException uhe) {226System.out.println(227"Ignore the test as the local hostname cannot be determined");228229return;230}231232System.out.println(233"The fully qualified domain name of the local host is " +234hostname);235// Ignore the test if the hostname does not sound like a domain name.236if ((hostname == null) || hostname.isEmpty() ||237!hostname.contains(".") || hostname.endsWith(".") ||238hostname.startsWith("localhost") ||239Character.isDigit(hostname.charAt(hostname.length() - 1))) {240241System.out.println("Ignore the test as the local hostname " +242"cannot be determined as fully qualified domain name");243244return;245}246247/*248* Start the tests.249*/250new ImpactOnSNI();251}252253private Thread clientThread = null;254private Thread serverThread = null;255256/*257* Primary constructor, used to drive remainder of the test.258*259* Fork off the other side, then do your work.260*/261ImpactOnSNI() throws Exception {262Exception startException = null;263try {264if (separateServerThread) {265startServer(true);266startClient(false);267} else {268startClient(true);269startServer(false);270}271} catch (Exception e) {272startException = e;273}274275/*276* Wait for other side to close down.277*/278if (separateServerThread) {279if (serverThread != null) {280serverThread.join();281}282} else {283if (clientThread != null) {284clientThread.join();285}286}287288/*289* When we get here, the test is pretty much over.290* Which side threw the error?291*/292Exception local;293Exception remote;294295if (separateServerThread) {296remote = serverException;297local = clientException;298} else {299remote = clientException;300local = serverException;301}302303Exception exception = null;304305/*306* Check various exception conditions.307*/308if ((local != null) && (remote != null)) {309// If both failed, return the curthread's exception.310local.initCause(remote);311exception = local;312} else if (local != null) {313exception = local;314} else if (remote != null) {315exception = remote;316} else if (startException != null) {317exception = startException;318}319320/*321* If there was an exception *AND* a startException,322* output it.323*/324if (exception != null) {325if (exception != startException && startException != null) {326exception.addSuppressed(startException);327}328throw exception;329}330331// Fall-through: no exception to throw!332}333334private void startServer(boolean newThread) throws Exception {335if (newThread) {336serverThread = new Thread() {337@Override338public void run() {339try {340doServerSide();341} catch (Exception e) {342/*343* Our server thread just died.344*345* Release the client, if not active already...346*/347System.err.println("Server died...");348serverReady = true;349serverException = e;350}351}352};353serverThread.start();354} else {355try {356doServerSide();357} catch (Exception e) {358serverException = e;359} finally {360serverReady = true;361}362}363}364365private void startClient(boolean newThread) throws Exception {366if (newThread) {367clientThread = new Thread() {368@Override369public void run() {370try {371doClientSide();372} catch (Exception e) {373/*374* Our client thread just died.375*/376System.err.println("Client died...");377clientException = e;378}379}380};381clientThread.start();382} else {383try {384doClientSide();385} catch (Exception e) {386clientException = e;387}388}389}390}391392393