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