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