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