1 /*
   2  * @test
   3  * @build TestThread Traffic Handler ServerHandler ServerThread ClientThread
   4  * @run main/othervm/timeout=140 -Djsse.enableCBCProtection=false main
   5  * @summary Make sure that different configurations of SSL sockets work
   6  * @key randomness
   7  */
   8 
   9 /*
  10  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  11  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  12  *
  13  * This code is free software; you can redistribute it and/or modify it
  14  * under the terms of the GNU General Public License version 2 only, as
  15  * published by the Free Software Foundation.
  16  *
  17  * This code is distributed in the hope that it will be useful, but WITHOUT
  18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  20  * version 2 for more details (a copy is included in the LICENSE file that
  21  * accompanied this code).
  22  *
  23  * You should have received a copy of the GNU General Public License version
  24  * 2 along with this work; if not, write to the Free Software Foundation,
  25  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  26  *
  27  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  28  * or visit www.oracle.com if you need additional information or have any
  29  * questions.
  30  */
  31 
  32 import java.io.*;
  33 import java.security.SecureRandom;
  34 import java.security.KeyStore;
  35 import javax.security.cert.*;
  36 import java.util.Date;
  37 import java.util.Vector;
  38 import java.util.ArrayList;
  39 
  40 import javax.net.ssl.*;
  41 
  42 public class main
  43 {
  44     // NOTE:  "prng" doesn't need to be a SecureRandom
  45 
  46     private static final SecureRandom   prng
  47         = new SecureRandom ();
  48     private static SSLContext sslContext;
  49 
  50     private static void usage() {
  51         System.err.println (
  52             "usage: tests.ssl.main default|random|cipher_suite [nthreads]");
  53     }
  54 
  55     /**
  56      * Runs a test ... there are a variety of configurations, and the way
  57      * they're invoked is subject to change.  This program can support
  58      * single and multiple process tests, but by default it's set up for
  59      * single process testing.
  60      *
  61      * <P> The first commandline argument identifies a test configuration.
  62      * Currently identified configurations include "default", "random".
  63      *
  64      * <P> The second commandline argument identifies the number of
  65      * client threads to use.
  66      */
  67     public static void main (String argv [])
  68     {
  69         String          config;
  70         int             NTHREADS;
  71 
  72         initContext();
  73         String          supported [] = sslContext.getSocketFactory()
  74                             .getSupportedCipherSuites();
  75 
  76         // Strip out any Kerberos Suites for now.
  77         ArrayList list = new ArrayList(supported.length);
  78         for (int i = 0; i < supported.length; i++) {
  79             if (!supported[i].startsWith("TLS_KRB5")) {
  80                 list.add(supported[i]);
  81             }
  82         }
  83         supported = (String [])list.toArray(new String [0]);
  84 
  85         if (argv.length == 2) {
  86             config = argv [0];
  87             NTHREADS = Integer.parseInt (argv [1]);
  88         } else if (argv.length == 1) {
  89             config = argv [0];
  90             NTHREADS = 15;
  91         } else {
  92             /* temporaraly changed to make it run under jtreg with
  93              * default configuration, when no input parameters are
  94              * given
  95              */
  96             //usage();
  97             //return;
  98             config = "default";
  99             NTHREADS = supported.length;
 100         }
 101 
 102         // More options ... port #. different clnt/svr configs,
 103         // cipher suites, etc.
 104 
 105         ServerThread    server = new ServerThread (0, NTHREADS, sslContext);
 106         Vector          clients = new Vector (NTHREADS);
 107 
 108         if (!(config.equals("default") || config.equals("random")))
 109             supported = new String[] {config};
 110 
 111         System.out.println("Supported cipher suites are:");
 112         for(int i=0; i < supported.length; i++) {
 113             System.out.println(supported[i]);
 114         }
 115 
 116         setConfig (server, config, supported);
 117 
 118         // if (OS != Win95)
 119             server.setUseMT (true);
 120 
 121         server.start ();
 122         server.waitTillReady ();
 123 
 124         //
 125         // iterate over all cipher suites
 126         //
 127         int             next = 0;
 128         int             passes = 0;
 129 
 130         if (usesRandom (config))
 131             next = nextUnsignedRandom ();
 132 
 133         for (int i = 0; i < NTHREADS; i++, next++) {
 134             ClientThread        client = new ClientThread (server.getServerPort(), sslContext);
 135             String              cipher [] = new String [1];
 136 
 137             setConfig (client, config, supported);
 138             next = next % supported.length;
 139             cipher [0] = supported [next];
 140             client.setBasicCipherSuites (cipher);
 141 
 142             //
 143             // Win95 has been observed to choke if you throw many
 144             // connections at it.  So we make it easy to unthread
 145             // everything; it can be handy outside Win95 too.
 146             //
 147             client.start ();
 148             if (!server.getUseMT ()) {
 149                 waitForClient (client);
 150                 if (client.passed ())
 151                     passes++;
 152             } else
 153                 clients.addElement (client);
 154         }
 155 
 156         while (!clients.isEmpty ()) {
 157             ClientThread        client;
 158 
 159             client = (ClientThread) clients.elementAt (0);
 160             clients.removeElement (client);
 161             waitForClient (client);
 162             if (client.passed ())
 163                 passes++;
 164         }
 165 
 166         System.out.println ("SUMMARY:  threads = " + NTHREADS
 167             + ", passes = " + passes);
 168     }
 169 
 170 
 171     //
 172     // Rather than replicating code, a helper function!
 173     //
 174     private static void waitForClient (Thread client)
 175     {
 176         while (true)
 177             try {
 178                 client.join ();
 179 
 180                 // System.out.println ("Joined:  " + client.getName ());
 181                 break;
 182             } catch (InterruptedException e) {
 183                 continue;
 184             }
 185     }
 186 
 187     private static void initContext()
 188     {
 189         try {
 190             String testRoot = System.getProperty("test.src", ".");
 191             System.setProperty("javax.net.ssl.trustStore", testRoot
 192                                 + "/../../../../javax/net/ssl/etc/truststore");
 193 
 194             KeyStore ks = KeyStore.getInstance("JKS");
 195             ks.load(new FileInputStream(testRoot
 196                                 + "/../../../../javax/net/ssl/etc/truststore"),
 197                     "passphrase".toCharArray());
 198             KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
 199             kmf.init(ks, "passphrase".toCharArray());
 200             TrustManagerFactory tmf =
 201                 TrustManagerFactory.getInstance("SunX509");
 202             tmf.init(ks);
 203             sslContext = SSLContext.getInstance("SSL");
 204             sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 205         } catch (Throwable t) {
 206             // oh well; ignore it, the tester presumably intends this
 207             System.out.println("Failed to read keystore/truststore file... Continuing");
 208             t.printStackTrace();
 209         }
 210     }
 211 
 212     private static int nextUnsignedRandom ()
 213     {
 214         int retval = prng.nextInt ();
 215 
 216         if (retval < 0)
 217             return -retval;
 218         else
 219             return retval;
 220     }
 221 
 222 
 223     //
 224     // Randomness in testing can be good and bad ... covers more
 225     // territory, but not reproducibly.
 226     //
 227     private static boolean usesRandom (String config)
 228     {
 229         return config.equalsIgnoreCase ("random");
 230     }
 231 
 232 
 233     private static void setConfig (
 234         TestThread      test,
 235         String          config,
 236         String          supported []
 237     )
 238     {
 239         test.setBasicCipherSuites (supported);
 240         test.setOutput (System.out);
 241         test.setVerbosity (3);
 242 
 243         if (test instanceof ClientThread) {
 244             test.setListenHandshake (true);
 245             test.setIterations (20);
 246         }
 247 
 248 // XXX role reversals !!!
 249 
 250         //
 251         // We can establish a reasonable degree of variability
 252         // on the test data and configs ... expecting that the
 253         // diagnostics will identify any problems that exist.
 254         // Client and server must agree on these things.
 255         //
 256         // Unless we do this, only the SSL nonces and ephemeral
 257         // keys will be unpredictable in a given test run.  Those
 258         // affect only the utmost innards of SSL, details which
 259         // are not visible to applications.
 260         //
 261         if (usesRandom (config)) {
 262             int rand = nextUnsignedRandom ();
 263 
 264             if (test instanceof ClientThread)
 265                 test.setIterations (rand % 35);
 266 
 267             if ((rand & 0x080) == 0)
 268                 test.setInitiateHandshake (true);
 269 //          if ((rand & 0x040) == 0)
 270 //              test.setDoRenegotiate (true);
 271 
 272             test.setPRNG (new SecureRandom ());
 273         }
 274     }
 275 }