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// 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 EmptyCertificateAuthorities 36 * @modules java.security.jgss 37 * java.security.jgss/sun.security.krb5:+open 38 * java.security.jgss/sun.security.krb5.internal:+open 39 * java.security.jgss/sun.security.krb5.internal.ccache 40 * java.security.jgss/sun.security.krb5.internal.crypto 41 * java.security.jgss/sun.security.krb5.internal.ktab 42 * java.base/sun.security.util 43 * @author Xuelei Fan 44 */ 45 46import java.io.FileInputStream; 47import java.io.InputStream; 48import java.io.OutputStream; 49import java.security.KeyStore; 50import java.security.Security; 51import java.security.cert.CertificateException; 52import java.security.cert.X509Certificate; 53import javax.net.ssl.KeyManager; 54import javax.net.ssl.KeyManagerFactory; 55import javax.net.ssl.SSLContext; 56import javax.net.ssl.SSLServerSocket; 57import javax.net.ssl.SSLServerSocketFactory; 58import javax.net.ssl.SSLSocket; 59import javax.net.ssl.SSLSocketFactory; 60import javax.net.ssl.TrustManager; 61import javax.net.ssl.TrustManagerFactory; 62import javax.net.ssl.X509TrustManager; 63 64public class EmptyCertificateAuthorities { 65 66 /* 67 * ============================================================= 68 * Set the various variables needed for the tests, then 69 * specify what tests to run on each side. 70 */ 71 72 /* 73 * Should we run the client or server in a separate thread? 74 * Both sides can throw exceptions, but do you have a preference 75 * as to which side should be the main thread. 76 */ 77 static boolean separateServerThread = false; 78 79 /* 80 * Where do we find the keystores? 81 */ 82 static String pathToStores = "../etc"; 83 static String keyStoreFile = "keystore"; 84 static String trustStoreFile = "truststore"; 85 static String passwd = "passphrase"; 86 87 /* 88 * Is the server ready to serve? 89 */ 90 volatile static boolean serverReady = false; 91 92 /* 93 * Turn on SSL debugging? 94 */ 95 static boolean debug = false; 96 97 /* 98 * If the client or server is doing some kind of object creation 99 * that the other side depends on, and that thread prematurely 100 * exits, you may experience a hang. The test harness will 101 * terminate all hung threads after its timeout has expired, 102 * currently 3 minutes by default, but you might try to be 103 * smart about it.... 104 */ 105 106 /* 107 * Define the server side of the test. 108 * 109 * If the server prematurely exits, serverReady will be set to true 110 * to avoid infinite hangs. 111 */ 112 void doServerSide() throws Exception { 113 SSLServerSocketFactory sslssf = getSSLServerSF(); 114 SSLServerSocket sslServerSocket = 115 (SSLServerSocket) sslssf.createServerSocket(serverPort); 116 117 // require client authentication. 118 sslServerSocket.setNeedClientAuth(true); 119 120 serverPort = sslServerSocket.getLocalPort(); 121 122 /* 123 * Signal Client, we're ready for his connect. 124 */ 125 serverReady = true; 126 127 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 128 InputStream sslIS = sslSocket.getInputStream(); 129 OutputStream sslOS = sslSocket.getOutputStream(); 130 131 sslIS.read(); 132 sslOS.write('A'); 133 sslOS.flush(); 134 135 sslSocket.close(); 136 } 137 138 /* 139 * Define the client side of the test. 140 * 141 * If the server prematurely exits, serverReady will be set to true 142 * to avoid infinite hangs. 143 */ 144 void doClientSide() throws Exception { 145 146 /* 147 * Wait for server to get started. 148 */ 149 while (!serverReady) { 150 Thread.sleep(50); 151 } 152 153 SSLSocketFactory sslsf = 154 (SSLSocketFactory) SSLSocketFactory.getDefault(); 155 SSLSocket sslSocket = (SSLSocket) 156 sslsf.createSocket("localhost", serverPort); 157 158 // enable TLSv1.1 only 159 sslSocket.setEnabledProtocols(new String[] {"TLSv1.1"}); 160 161 InputStream sslIS = sslSocket.getInputStream(); 162 OutputStream sslOS = sslSocket.getOutputStream(); 163 164 sslOS.write('B'); 165 sslOS.flush(); 166 sslIS.read(); 167 168 sslSocket.close(); 169 } 170 171 private SSLServerSocketFactory getSSLServerSF() throws Exception { 172 173 char [] password = 174 System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(); 175 String keyFilename = System.getProperty("javax.net.ssl.keyStore"); 176 177 KeyStore ks = KeyStore.getInstance("JKS"); 178 ks.load(new FileInputStream(keyFilename), password); 179 180 KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 181 kmf.init(ks, password); 182 183 KeyManager[] kms = kmf.getKeyManagers(); 184 TrustManager[] tms = new MyX509TM[] {new MyX509TM()}; 185 186 SSLContext ctx = SSLContext.getInstance("TLS"); 187 ctx.init(kms, tms, null); 188 189 return ctx.getServerSocketFactory(); 190 } 191 192 193 static class MyX509TM implements X509TrustManager { 194 X509TrustManager tm; 195 196 public void checkClientTrusted(X509Certificate[] chain, 197 String authType) throws CertificateException { 198 if (tm == null) { 199 initialize(); 200 } 201 tm.checkClientTrusted(chain, authType); 202 } 203 204 public void checkServerTrusted(X509Certificate[] chain, 205 String authType) throws CertificateException { 206 if (tm == null) { 207 initialize(); 208 } 209 tm.checkServerTrusted(chain, authType); 210 } 211 212 public X509Certificate[] getAcceptedIssuers() { 213 // always return empty array 214 return new X509Certificate[0]; 215 } 216 217 private void initialize() throws CertificateException { 218 String passwd = 219 System.getProperty("javax.net.ssl.trustStorePassword"); 220 char [] password = passwd.toCharArray(); 221 String trustFilename = 222 System.getProperty("javax.net.ssl.trustStore"); 223 224 try { 225 KeyStore ks = KeyStore.getInstance("JKS"); 226 ks.load(new FileInputStream(trustFilename), password); 227 228 TrustManagerFactory tmf = 229 TrustManagerFactory.getInstance("PKIX"); 230 tmf.init(ks); 231 tm = (X509TrustManager)tmf.getTrustManagers()[0]; 232 } catch (Exception e) { 233 throw new CertificateException("Unable to initialize TM"); 234 } 235 236 } 237 } 238 239 /* 240 * ============================================================= 241 * The remainder is just support stuff 242 */ 243 244 // use any free port by default 245 volatile int serverPort = 0; 246 247 volatile Exception serverException = null; 248 volatile Exception clientException = null; 249 250 public static void main(String[] args) throws Exception { 251 // MD5 is used in this test case, don't disable MD5 algorithm. 252 Security.setProperty("jdk.certpath.disabledAlgorithms", 253 "MD2, RSA keySize < 1024"); 254 Security.setProperty("jdk.tls.disabledAlgorithms", 255 "SSLv3, RC4, DH keySize < 768"); 256 257 String keyFilename = 258 System.getProperty("test.src", ".") + "/" + pathToStores + 259 "/" + keyStoreFile; 260 String trustFilename = 261 System.getProperty("test.src", ".") + "/" + pathToStores + 262 "/" + trustStoreFile; 263 264 System.setProperty("javax.net.ssl.keyStore", keyFilename); 265 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 266 System.setProperty("javax.net.ssl.trustStore", trustFilename); 267 System.setProperty("javax.net.ssl.trustStorePassword", passwd); 268 269 if (debug) 270 System.setProperty("javax.net.debug", "all"); 271 272 /* 273 * Start the tests. 274 */ 275 new EmptyCertificateAuthorities(); 276 } 277 278 Thread clientThread = null; 279 Thread serverThread = null; 280 281 /* 282 * Primary constructor, used to drive remainder of the test. 283 * 284 * Fork off the other side, then do your work. 285 */ 286 EmptyCertificateAuthorities() throws Exception { 287 try { 288 if (separateServerThread) { 289 startServer(true); 290 startClient(false); 291 } else { 292 startClient(true); 293 startServer(false); 294 } 295 } catch (Exception e) { 296 // swallow for now. Show later 297 } 298 299 /* 300 * Wait for other side to close down. 301 */ 302 if (separateServerThread) { 303 serverThread.join(); 304 } else { 305 clientThread.join(); 306 } 307 308 /* 309 * When we get here, the test is pretty much over. 310 * Which side threw the error? 311 */ 312 Exception local; 313 Exception remote; 314 String whichRemote; 315 316 if (separateServerThread) { 317 remote = serverException; 318 local = clientException; 319 whichRemote = "server"; 320 } else { 321 remote = clientException; 322 local = serverException; 323 whichRemote = "client"; 324 } 325 326 /* 327 * If both failed, return the curthread's exception, but also 328 * print the remote side Exception 329 */ 330 if ((local != null) && (remote != null)) { 331 System.out.println(whichRemote + " also threw:"); 332 remote.printStackTrace(); 333 System.out.println(); 334 throw local; 335 } 336 337 if (remote != null) { 338 throw remote; 339 } 340 341 if (local != null) { 342 throw local; 343 } 344 } 345 346 void startServer(boolean newThread) throws Exception { 347 if (newThread) { 348 serverThread = new Thread() { 349 public void run() { 350 try { 351 doServerSide(); 352 } catch (Exception e) { 353 /* 354 * Our server thread just died. 355 * 356 * Release the client, if not active already... 357 */ 358 System.err.println("Server died..."); 359 serverReady = true; 360 serverException = e; 361 } 362 } 363 }; 364 serverThread.start(); 365 } else { 366 try { 367 doServerSide(); 368 } catch (Exception e) { 369 serverException = e; 370 } finally { 371 serverReady = true; 372 } 373 } 374 } 375 376 void startClient(boolean newThread) throws Exception { 377 if (newThread) { 378 clientThread = new Thread() { 379 public void run() { 380 try { 381 doClientSide(); 382 } catch (Exception e) { 383 /* 384 * Our client thread just died. 385 */ 386 System.err.println("Client died..."); 387 clientException = e; 388 } 389 } 390 }; 391 clientThread.start(); 392 } else { 393 try { 394 doClientSide(); 395 } catch (Exception e) { 396 clientException = e; 397 } 398 } 399 } 400} 401