1 /*
   2  * Copyright (c) 2001, 2011, 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 //
  25 // SunJSSE does not support dynamic system properties, no way to re-use
  26 // system properties in samevm/agentvm mode.
  27 //
  28 
  29 /*
  30  * @test
  31  * @bug 4403428
  32  * @summary Invalidating JSSE session on server causes SSLProtocolException
  33  * @run main/othervm InvalidateServerSessionRenegotiate SSLv3
  34  * @run main/othervm InvalidateServerSessionRenegotiate TLSv1
  35  * @run main/othervm InvalidateServerSessionRenegotiate TLSv1.1
  36  * @run main/othervm InvalidateServerSessionRenegotiate TLSv1.2
  37  * @author Brad Wetmore
  38  */
  39 
  40 import java.io.*;
  41 import java.net.*;
  42 import java.security.Security;
  43 import javax.net.ssl.*;
  44 
  45 public class InvalidateServerSessionRenegotiate implements
  46         HandshakeCompletedListener {
  47 
  48     static byte handshakesCompleted = 0;
  49 
  50     /*
  51      * Define what happens when handshaking is completed
  52      */
  53     public void handshakeCompleted(HandshakeCompletedEvent event) {
  54         synchronized (this) {
  55             handshakesCompleted++;
  56             System.out.println("Session: " + event.getSession().toString());
  57             System.out.println("Seen handshake completed #" +
  58                 handshakesCompleted);
  59         }
  60     }
  61 
  62     /*
  63      * =============================================================
  64      * Set the various variables needed for the tests, then
  65      * specify what tests to run on each side.
  66      */
  67 
  68     /*
  69      * Should we run the client or server in a separate thread?
  70      * Both sides can throw exceptions, but do you have a preference
  71      * as to which side should be the main thread.
  72      */
  73     static boolean separateServerThread = false;
  74 
  75     /*
  76      * Where do we find the keystores?
  77      */
  78     static String pathToStores = "../../../../javax/net/ssl/etc";
  79     static String keyStoreFile = "keystore";
  80     static String trustStoreFile = "truststore";
  81     static String passwd = "passphrase";
  82 
  83     /*
  84      * Is the server ready to serve?
  85      */
  86     volatile static boolean serverReady = false;
  87 
  88     /*
  89      * Turn on SSL debugging?
  90      */
  91     static boolean debug = false;
  92 
  93     /*
  94      * If the client or server is doing some kind of object creation
  95      * that the other side depends on, and that thread prematurely
  96      * exits, you may experience a hang.  The test harness will
  97      * terminate all hung threads after its timeout has expired,
  98      * currently 3 minutes by default, but you might try to be
  99      * smart about it....
 100      */
 101 
 102     /*
 103      * Define the server side of the test.
 104      *
 105      * If the server prematurely exits, serverReady will be set to true
 106      * to avoid infinite hangs.
 107      */
 108     void doServerSide() throws Exception {
 109         SSLServerSocketFactory sslssf =
 110             (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
 111         SSLServerSocket sslServerSocket =
 112             (SSLServerSocket) sslssf.createServerSocket(serverPort);
 113 
 114         serverPort = sslServerSocket.getLocalPort();
 115 
 116         /*
 117          * Signal Client, we're ready for his connect.
 118          */
 119         serverReady = true;
 120 
 121         SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
 122         sslSocket.addHandshakeCompletedListener(this);
 123         InputStream sslIS = sslSocket.getInputStream();
 124         OutputStream sslOS = sslSocket.getOutputStream();
 125 
 126         for (int i = 0; i < 10; i++) {
 127             sslIS.read();
 128             sslOS.write(85);
 129             sslOS.flush();
 130         }
 131 
 132         System.out.println("invalidating");
 133         sslSocket.getSession().invalidate();
 134         System.out.println("starting new handshake");
 135         sslSocket.startHandshake();
 136 
 137         for (int i = 0; i < 10; i++) {
 138             System.out.println("sending/receiving data, iteration: " + i);
 139             sslIS.read();
 140             sslOS.write(85);
 141             sslOS.flush();
 142         }
 143 
 144         sslSocket.close();
 145     }
 146 
 147     /*
 148      * Define the client side of the test.
 149      *
 150      * If the server prematurely exits, serverReady will be set to true
 151      * to avoid infinite hangs.
 152      */
 153     void doClientSide() throws Exception {
 154 
 155         /*
 156          * Wait for server to get started.
 157          */
 158         while (!serverReady) {
 159             Thread.sleep(50);
 160         }
 161 
 162         SSLSocketFactory sslsf =
 163             (SSLSocketFactory) SSLSocketFactory.getDefault();
 164         SSLSocket sslSocket = (SSLSocket)
 165             sslsf.createSocket("localhost", serverPort);
 166         sslSocket.setEnabledProtocols(new String[] { tlsProtocol });
 167 
 168         InputStream sslIS = sslSocket.getInputStream();
 169         OutputStream sslOS = sslSocket.getOutputStream();
 170 
 171         for (int i = 0; i < 10; i++) {
 172             sslOS.write(280);
 173             sslOS.flush();
 174             sslIS.read();
 175         }
 176 
 177         for (int i = 0; i < 10; i++) {
 178             sslOS.write(280);
 179             sslOS.flush();
 180             sslIS.read();
 181         }
 182 
 183         sslSocket.close();
 184     }
 185 
 186     /*
 187      * =============================================================
 188      * The remainder is just support stuff
 189      */
 190 
 191     // use any free port by default
 192     volatile int serverPort = 0;
 193 
 194     volatile Exception serverException = null;
 195     volatile Exception clientException = null;
 196 
 197     // the specified protocol
 198     private static String tlsProtocol;
 199 
 200     public static void main(String[] args) throws Exception {
 201         String keyFilename =
 202             System.getProperty("test.src", "./") + "/" + pathToStores +
 203                 "/" + keyStoreFile;
 204         String trustFilename =
 205             System.getProperty("test.src", "./") + "/" + pathToStores +
 206                 "/" + trustStoreFile;
 207 
 208         System.setProperty("javax.net.ssl.keyStore", keyFilename);
 209         System.setProperty("javax.net.ssl.keyStorePassword", passwd);
 210         System.setProperty("javax.net.ssl.trustStore", trustFilename);
 211         System.setProperty("javax.net.ssl.trustStorePassword", passwd);
 212 
 213         if (debug) {
 214             System.setProperty("javax.net.debug", "all");
 215         }
 216 
 217         Security.setProperty("jdk.tls.disabledAlgorithms", "");
 218 
 219         tlsProtocol = args[0];
 220 
 221         /*
 222          * Start the tests.
 223          */
 224         new InvalidateServerSessionRenegotiate();
 225     }
 226 
 227     Thread clientThread = null;
 228     Thread serverThread = null;
 229 
 230     /*
 231      * Primary constructor, used to drive remainder of the test.
 232      *
 233      * Fork off the other side, then do your work.
 234      */
 235     InvalidateServerSessionRenegotiate() throws Exception {
 236         if (separateServerThread) {
 237             startServer(true);
 238             startClient(false);
 239         } else {
 240             startClient(true);
 241             startServer(false);
 242         }
 243 
 244         /*
 245          * Wait for other side to close down.
 246          */
 247         if (separateServerThread) {
 248             serverThread.join();
 249         } else {
 250             clientThread.join();
 251         }
 252 
 253         /*
 254          * When we get here, the test is pretty much over.
 255          *
 256          * If the main thread excepted, that propagates back
 257          * immediately.  If the other thread threw an exception, we
 258          * should report back.
 259          */
 260         if (serverException != null) {
 261             System.out.print("Server Exception:");
 262             throw serverException;
 263         }
 264         if (clientException != null) {
 265             System.out.print("Client Exception:");
 266             throw clientException;
 267         }
 268 
 269         /*
 270          * Give the Handshaker Thread a chance to run
 271          */
 272         Thread.sleep(1000);
 273 
 274         synchronized (this) {
 275             if (handshakesCompleted != 2) {
 276                 throw new Exception("Didn't see 2 handshake completed events.");
 277             }
 278         }
 279     }
 280 
 281     void startServer(boolean newThread) throws Exception {
 282         if (newThread) {
 283             serverThread = new Thread() {
 284                 public void run() {
 285                     try {
 286                         doServerSide();
 287                     } catch (Exception e) {
 288                         /*
 289                          * Our server thread just died.
 290                          *
 291                          * Release the client, if not active already...
 292                          */
 293                         System.err.println("Server died...");
 294                         serverReady = true;
 295                         serverException = e;
 296                     }
 297                 }
 298             };
 299             serverThread.start();
 300         } else {
 301             doServerSide();
 302         }
 303     }
 304 
 305     void startClient(boolean newThread) throws Exception {
 306         if (newThread) {
 307             clientThread = new Thread() {
 308                 public void run() {
 309                     try {
 310                         doClientSide();
 311                     } catch (Exception e) {
 312                         /*
 313                          * Our client thread just died.
 314                          */
 315                         System.err.println("Client died...");
 316                         clientException = e;
 317                     }
 318                 }
 319             };
 320             clientThread.start();
 321         } else {
 322             doClientSide();
 323         }
 324     }
 325 }