test/jdk/sun/net/www/protocol/https/NewImpl/ComHostnameVerifier.java
branchmetal-prototype-branch
changeset 57247 48f2dc62ba77
parent 57243 8c3a74033daf
parent 54029 4ff6c8365b69
child 57251 86ed45a9dedb
equal deleted inserted replaced
57243:8c3a74033daf 57247:48f2dc62ba77
     1 /*
       
     2  * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 // SunJSSE does not support dynamic system properties, no way to re-use
       
    25 // system properties in samevm/agentvm mode.
       
    26 
       
    27 /*
       
    28  * @test
       
    29  * @bug 4474255 4484246
       
    30  * @summary When an application enables anonymous SSL cipher suite,
       
    31  *        Hostname verification is not required
       
    32  * @modules java.base/com.sun.net.ssl
       
    33  *          java.base/com.sun.net.ssl.internal.www.protocol.https
       
    34  * @run main/othervm ComHostnameVerifier
       
    35  */
       
    36 
       
    37 import java.io.*;
       
    38 import java.net.*;
       
    39 import java.security.Security;
       
    40 import javax.net.ssl.*;
       
    41 import javax.security.cert.*;
       
    42 import com.sun.net.ssl.HostnameVerifier;
       
    43 import com.sun.net.ssl.HttpsURLConnection;
       
    44 
       
    45 /**
       
    46  * Use com.net.net.ssl.HostnameVerifier
       
    47  */
       
    48 public class ComHostnameVerifier {
       
    49 
       
    50     /*
       
    51      * =============================================================
       
    52      * Set the various variables needed for the tests, then
       
    53      * specify what tests to run on each side.
       
    54      */
       
    55 
       
    56     /*
       
    57      * Should we run the client or server in a separate thread?
       
    58      * Both sides can throw exceptions, but do you have a preference
       
    59      * as to which side should be the main thread.
       
    60      */
       
    61     static boolean separateServerThread = true;
       
    62 
       
    63     /*
       
    64      * Is the server ready to serve?
       
    65      */
       
    66     volatile static boolean serverReady = false;
       
    67 
       
    68     /*
       
    69      * Turn on SSL debugging?
       
    70      */
       
    71     static boolean debug = false;
       
    72 
       
    73     /*
       
    74      * If the client or server is doing some kind of object creation
       
    75      * that the other side depends on, and that thread prematurely
       
    76      * exits, you may experience a hang.  The test harness will
       
    77      * terminate all hung threads after its timeout has expired,
       
    78      * currently 3 minutes by default, but you might try to be
       
    79      * smart about it....
       
    80      */
       
    81 
       
    82     /**
       
    83      * Returns the path to the file obtained from
       
    84      * parsing the HTML header.
       
    85      */
       
    86     private static String getPath(DataInputStream in)
       
    87         throws IOException
       
    88     {
       
    89         String line = in.readLine();
       
    90         if (line == null)
       
    91                 return null;
       
    92         String path = "";
       
    93         // extract class from GET line
       
    94         if (line.startsWith("GET /")) {
       
    95             line = line.substring(5, line.length()-1).trim();
       
    96             int index = line.indexOf(' ');
       
    97             if (index != -1) {
       
    98                 path = line.substring(0, index);
       
    99             }
       
   100         }
       
   101 
       
   102         // eat the rest of header
       
   103         do {
       
   104             line = in.readLine();
       
   105         } while ((line.length() != 0) &&
       
   106                  (line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
       
   107 
       
   108         if (path.length() != 0) {
       
   109             return path;
       
   110         } else {
       
   111             throw new IOException("Malformed Header");
       
   112         }
       
   113     }
       
   114 
       
   115     /**
       
   116      * Returns an array of bytes containing the bytes for
       
   117      * the file represented by the argument <b>path</b>.
       
   118      *
       
   119      * In our case, we just pretend to send something back.
       
   120      *
       
   121      * @return the bytes for the file
       
   122      * @exception FileNotFoundException if the file corresponding
       
   123      * to <b>path</b> could not be loaded.
       
   124      */
       
   125     private byte[] getBytes(String path)
       
   126         throws IOException
       
   127     {
       
   128         return "Hello world, I am here".getBytes();
       
   129     }
       
   130 
       
   131     /*
       
   132      * Define the server side of the test.
       
   133      *
       
   134      * If the server prematurely exits, serverReady will be set to true
       
   135      * to avoid infinite hangs.
       
   136      */
       
   137     void doServerSide() throws Exception {
       
   138 
       
   139         SSLServerSocketFactory sslssf =
       
   140           (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
       
   141         SSLServerSocket sslServerSocket =
       
   142             (SSLServerSocket) sslssf.createServerSocket(serverPort);
       
   143         serverPort = sslServerSocket.getLocalPort();
       
   144 
       
   145         String ciphers[]= { "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA" };
       
   146         sslServerSocket.setEnabledCipherSuites(ciphers);
       
   147 
       
   148         /*
       
   149          * Signal Client, we're ready for his connect.
       
   150          */
       
   151         serverReady = true;
       
   152 
       
   153         SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
       
   154         DataOutputStream out =
       
   155                 new DataOutputStream(sslSocket.getOutputStream());
       
   156 
       
   157         try {
       
   158              // get path to class file from header
       
   159              DataInputStream in =
       
   160                         new DataInputStream(sslSocket.getInputStream());
       
   161              String path = getPath(in);
       
   162              // retrieve bytecodes
       
   163              byte[] bytecodes = getBytes(path);
       
   164              // send bytecodes in response (assumes HTTP/1.0 or later)
       
   165              try {
       
   166                 out.writeBytes("HTTP/1.0 200 OK\r\n");
       
   167                 out.writeBytes("Content-Length: " + bytecodes.length + "\r\n");
       
   168                 out.writeBytes("Content-Type: text/html\r\n\r\n");
       
   169                 out.write(bytecodes);
       
   170                 out.flush();
       
   171              } catch (IOException ie) {
       
   172                 ie.printStackTrace();
       
   173                 return;
       
   174              }
       
   175 
       
   176         } catch (Exception e) {
       
   177              e.printStackTrace();
       
   178              // write out error response
       
   179              out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
       
   180              out.writeBytes("Content-Type: text/html\r\n\r\n");
       
   181              out.flush();
       
   182         } finally {
       
   183              // close the socket
       
   184              System.out.println("Server closing socket");
       
   185              sslSocket.close();
       
   186              serverReady = false;
       
   187         }
       
   188     }
       
   189 
       
   190     private static class ComSunHTTPSHandlerFactory implements URLStreamHandlerFactory {
       
   191         private static String SUPPORTED_PROTOCOL = "https";
       
   192 
       
   193         public URLStreamHandler createURLStreamHandler(String protocol) {
       
   194             if (!protocol.equalsIgnoreCase(SUPPORTED_PROTOCOL))
       
   195                 return null;
       
   196 
       
   197             return new com.sun.net.ssl.internal.www.protocol.https.Handler();
       
   198         }
       
   199     }
       
   200 
       
   201     /*
       
   202      * Define the client side of the test.
       
   203      *
       
   204      * If the server prematurely exits, serverReady will be set to true
       
   205      * to avoid infinite hangs.
       
   206      */
       
   207     void doClientSide() throws Exception {
       
   208         /*
       
   209          * Wait for server to get started.
       
   210          */
       
   211         while (!serverReady) {
       
   212             Thread.sleep(50);
       
   213         }
       
   214 
       
   215         URL.setURLStreamHandlerFactory(new ComSunHTTPSHandlerFactory());
       
   216 
       
   217         System.setProperty("https.cipherSuites",
       
   218                 "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA");
       
   219 
       
   220         // use the default hostname verifier
       
   221 
       
   222         URL url = new URL("https://" + "localhost:" + serverPort +
       
   223                                 "/etc/hosts");
       
   224         URLConnection urlc = url.openConnection();
       
   225 
       
   226         if (!(urlc instanceof com.sun.net.ssl.HttpsURLConnection)) {
       
   227             throw new Exception(
       
   228                 "URLConnection ! instanceof " +
       
   229                 "com.sun.net.ssl.HttpsURLConnection");
       
   230         }
       
   231 
       
   232         BufferedReader in = null;
       
   233         try {
       
   234             in = new BufferedReader(new InputStreamReader(
       
   235                                urlc.getInputStream()));
       
   236             String inputLine;
       
   237             System.out.print("Client reading... ");
       
   238             while ((inputLine = in.readLine()) != null)
       
   239                 System.out.println(inputLine);
       
   240             System.out.println("Cipher Suite: " +
       
   241                 ((HttpsURLConnection)urlc).getCipherSuite());
       
   242             in.close();
       
   243         } catch (SSLException e) {
       
   244             if (in != null)
       
   245                 in.close();
       
   246             throw e;
       
   247         }
       
   248         System.out.println("Client reports:  SUCCESS");
       
   249     }
       
   250 
       
   251     /*
       
   252      * =============================================================
       
   253      * The remainder is just support stuff
       
   254      */
       
   255 
       
   256     // use any free port by default
       
   257     volatile int serverPort = 0;
       
   258 
       
   259     volatile Exception serverException = null;
       
   260     volatile Exception clientException = null;
       
   261 
       
   262     public static void main(String[] args) throws Exception {
       
   263         // re-enable 3DES
       
   264         Security.setProperty("jdk.tls.disabledAlgorithms", "");
       
   265 
       
   266         if (debug)
       
   267             System.setProperty("javax.net.debug", "all");
       
   268 
       
   269         /*
       
   270          * Start the tests.
       
   271          */
       
   272         new ComHostnameVerifier();
       
   273     }
       
   274 
       
   275     Thread clientThread = null;
       
   276     Thread serverThread = null;
       
   277 
       
   278     /*
       
   279      * Primary constructor, used to drive remainder of the test.
       
   280      *
       
   281      * Fork off the other side, then do your work.
       
   282      */
       
   283     ComHostnameVerifier() throws Exception {
       
   284         if (separateServerThread) {
       
   285             startServer(true);
       
   286             startClient(false);
       
   287         } else {
       
   288             startClient(true);
       
   289             startServer(false);
       
   290         }
       
   291 
       
   292         /*
       
   293          * Wait for other side to close down.
       
   294          */
       
   295         if (separateServerThread) {
       
   296             serverThread.join();
       
   297         } else {
       
   298             clientThread.join();
       
   299         }
       
   300 
       
   301         /*
       
   302          * When we get here, the test is pretty much over.
       
   303          *
       
   304          * If the main thread excepted, that propagates back
       
   305          * immediately.  If the other thread threw an exception, we
       
   306          * should report back.
       
   307          */
       
   308         if (serverException != null) {
       
   309             System.out.print("Server Exception:");
       
   310             throw serverException;
       
   311         }
       
   312         if (clientException != null) {
       
   313             System.out.print("Client Exception:");
       
   314             throw clientException;
       
   315         }
       
   316     }
       
   317 
       
   318     void startServer(boolean newThread) throws Exception {
       
   319         if (newThread) {
       
   320             serverThread = new Thread() {
       
   321                 public void run() {
       
   322                     try {
       
   323                         doServerSide();
       
   324                     } catch (Exception e) {
       
   325                         /*
       
   326                          * Our server thread just died.
       
   327                          *
       
   328                          * Release the client, if not active already...
       
   329                          */
       
   330                         System.err.println("Server died...");
       
   331                         serverReady = true;
       
   332                         serverException = e;
       
   333                     }
       
   334                 }
       
   335             };
       
   336             serverThread.start();
       
   337         } else {
       
   338             doServerSide();
       
   339         }
       
   340     }
       
   341 
       
   342     void startClient(boolean newThread) throws Exception {
       
   343         if (newThread) {
       
   344             clientThread = new Thread() {
       
   345                 public void run() {
       
   346                     try {
       
   347                         doClientSide();
       
   348                     } catch (Exception e) {
       
   349                         /*
       
   350                          * Our client thread just died.
       
   351                          */
       
   352                         System.err.println("Client died...");
       
   353                         clientException = e;
       
   354                     }
       
   355                 }
       
   356             };
       
   357             clientThread.start();
       
   358         } else {
       
   359             doClientSide();
       
   360         }
       
   361     }
       
   362 }