1 /* 2 * Copyright (c) 2010, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 // 27 // SunJSSE does not support dynamic system properties, no way to re-use 28 // system properties in samevm/agentvm mode. 29 // 30 31 /* 32 * @test 33 * @bug 4873188 34 * @summary Support TLS 1.1 35 * @run main/othervm ExportableBlockCipher 36 * @author Xuelei Fan 37 */ 38 39 import java.io.*; 40 import java.net.*; 41 import javax.net.ssl.*; 42 43 public class ExportableBlockCipher { 44 45 /* 46 * ============================================================= 47 * Set the various variables needed for the tests, then 48 * specify what tests to run on each side. 49 */ 50 51 /* 52 * Should we run the client or server in a separate thread? 53 * Both sides can throw exceptions, but do you have a preference 54 * as to which side should be the main thread. 55 */ 56 static boolean separateServerThread = false; 57 58 /* 59 * Where do we find the keystores? 60 */ 61 static String pathToStores = "../etc"; 62 static String keyStoreFile = "keystore"; 63 static String trustStoreFile = "truststore"; 64 static String passwd = "passphrase"; 65 66 /* 67 * Is the server ready to serve? 68 */ 69 volatile static boolean serverReady = false; 70 71 /* 72 * Turn on SSL debugging? 73 */ 74 static boolean debug = false; 75 76 /* 77 * If the client or server is doing some kind of object creation 78 * that the other side depends on, and that thread prematurely 79 * exits, you may experience a hang. The test harness will 80 * terminate all hung threads after its timeout has expired, 81 * currently 3 minutes by default, but you might try to be 82 * smart about it.... 83 */ 84 85 /* 86 * Define the server side of the test. 87 * 88 * If the server prematurely exits, serverReady will be set to true 89 * to avoid infinite hangs. 90 */ 91 void doServerSide() throws Exception { 92 SSLServerSocketFactory sslssf = 93 (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 94 SSLServerSocket sslServerSocket = 95 (SSLServerSocket) sslssf.createServerSocket(serverPort); 96 97 serverPort = sslServerSocket.getLocalPort(); 98 99 /* 100 * Signal Client, we're ready for his connect. 101 */ 102 serverReady = true; 103 104 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 105 InputStream sslIS = sslSocket.getInputStream(); 106 OutputStream sslOS = sslSocket.getOutputStream(); 107 108 boolean interrupted = false; 109 try { 110 sslIS.read(); 111 sslOS.write('A'); 112 sslOS.flush(); 113 } catch (IOException ioe) { 114 // get the expected exception 115 interrupted = true; 116 } finally { 117 sslSocket.close(); 118 } 119 120 if (!interrupted) { 121 throw new SSLHandshakeException( 122 "A weak cipher suite is negotiated, " + 123 "TLSv1.1 must not negotiate the exportable cipher suites."); 124 } 125 } 126 127 /* 128 * Define the client side of the test. 129 * 130 * If the server prematurely exits, serverReady will be set to true 131 * to avoid infinite hangs. 132 */ 133 void doClientSide() throws Exception { 134 135 /* 136 * Wait for server to get started. 137 */ 138 while (!serverReady) { 139 Thread.sleep(50); 140 } 141 142 SSLSocketFactory sslsf = 143 (SSLSocketFactory) SSLSocketFactory.getDefault(); 144 SSLSocket sslSocket = (SSLSocket) 145 sslsf.createSocket("localhost", serverPort); 146 147 // enable TLSv1.1 only 148 sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"}); 149 150 // enable a exportable block cipher 151 sslSocket.setEnabledCipherSuites( 152 new String[] {"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"}); 153 154 InputStream sslIS = sslSocket.getInputStream(); 155 OutputStream sslOS = sslSocket.getOutputStream(); 156 157 boolean interrupted = false; 158 try { 159 sslOS.write('B'); 160 sslOS.flush(); 161 sslIS.read(); 162 } catch (SSLException ssle) { 163 // get the expected exception 164 interrupted = true; 165 } finally { 166 sslSocket.close(); 167 } 168 169 if (!interrupted) { 170 throw new SSLHandshakeException( 171 "A weak cipher suite is negotiated, " + 172 "TLSv1.1 must not negotiate the exportable cipher suites."); 173 } 174 } 175 176 /* 177 * ============================================================= 178 * The remainder is just support stuff 179 */ 180 181 // use any free port by default 182 volatile int serverPort = 0; 183 184 volatile Exception serverException = null; 185 volatile Exception clientException = null; 186 187 public static void main(String[] args) throws Exception { 188 String keyFilename = 189 System.getProperty("test.src", ".") + "/" + pathToStores + 190 "/" + keyStoreFile; 191 String trustFilename = 192 System.getProperty("test.src", ".") + "/" + pathToStores + 193 "/" + trustStoreFile; 194 195 System.setProperty("javax.net.ssl.keyStore", keyFilename); 196 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 197 System.setProperty("javax.net.ssl.trustStore", trustFilename); 198 System.setProperty("javax.net.ssl.trustStorePassword", passwd); 199 200 if (debug) 201 System.setProperty("javax.net.debug", "all"); 202 203 /* 204 * Start the tests. 205 */ 206 new ExportableBlockCipher(); 207 } 208 209 Thread clientThread = null; 210 Thread serverThread = null; 211 212 /* 213 * Primary constructor, used to drive remainder of the test. 214 * 215 * Fork off the other side, then do your work. 216 */ 217 ExportableBlockCipher() throws Exception { 218 try { 219 if (separateServerThread) { 220 startServer(true); 221 startClient(false); 222 } else { 223 startClient(true); 224 startServer(false); 225 } 226 } catch (Exception e) { 227 // swallow for now. Show later 228 } 229 230 /* 231 * Wait for other side to close down. 232 */ 233 if (separateServerThread) { 234 serverThread.join(); 235 } else { 236 clientThread.join(); 237 } 238 239 /* 240 * When we get here, the test is pretty much over. 241 * Which side threw the error? 242 */ 243 Exception local; 244 Exception remote; 245 String whichRemote; 246 247 if (separateServerThread) { 248 remote = serverException; 249 local = clientException; 250 whichRemote = "server"; 251 } else { 252 remote = clientException; 253 local = serverException; 254 whichRemote = "client"; 255 } 256 257 /* 258 * If both failed, return the curthread's exception, but also 259 * print the remote side Exception 260 */ 261 if ((local != null) && (remote != null)) { 262 System.out.println(whichRemote + " also threw:"); 263 remote.printStackTrace(); 264 System.out.println(); 265 throw local; 266 } 267 268 if (remote != null) { 269 throw remote; 270 } 271 272 if (local != null) { 273 throw local; 274 } 275 } 276 277 void startServer(boolean newThread) throws Exception { 278 if (newThread) { 279 serverThread = new Thread() { 280 public void run() { 281 try { 282 doServerSide(); 283 } catch (Exception e) { 284 /* 285 * Our server thread just died. 286 * 287 * Release the client, if not active already... 288 */ 289 System.err.println("Server died..."); 290 serverReady = true; 291 serverException = e; 292 } 293 } 294 }; 295 serverThread.start(); 296 } else { 297 try { 298 doServerSide(); 299 } catch (Exception e) { 300 serverException = e; 301 } finally { 302 serverReady = true; 303 } 304 } 305 } 306 307 void startClient(boolean newThread) throws Exception { 308 if (newThread) { 309 clientThread = new Thread() { 310 public void run() { 311 try { 312 doClientSide(); 313 } catch (Exception e) { 314 /* 315 * Our client thread just died. 316 */ 317 System.err.println("Client died..."); 318 clientException = e; 319 } 320 } 321 }; 322 clientThread.start(); 323 } else { 324 try { 325 doClientSide(); 326 } catch (Exception e) { 327 clientException = e; 328 } 329 } 330 } 331 }