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. 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 * @test 26 * @bug 6916074 27 * @summary Add support for TLS 1.2 28 * @run main/othervm X509ExtendedTMEnabled 29 * 30 * SunJSSE does not support dynamic system properties, no way to re-use 31 * system properties in samevm/agentvm mode. 32 * 33 * Ensure that the SunJSSE provider enables the X509ExtendedTrustManager. 34 */ 35 36import java.io.*; 37import java.net.*; 38import javax.net.ssl.*; 39import java.security.cert.*; 40import java.security.*; 41 42public class X509ExtendedTMEnabled { 43 44 /* 45 * ============================================================= 46 * Set the various variables needed for the tests, then 47 * specify what tests to run on each side. 48 */ 49 50 /* 51 * Should we run the client or server in a separate thread? 52 * Both sides can throw exceptions, but do you have a preference 53 * as to which side should be the main thread. 54 */ 55 static boolean separateServerThread = true; 56 57 /* 58 * Where do we find the keystores? 59 */ 60 static String pathToStores = "../../../../javax/net/ssl/etc"; 61 static String keyStoreFile = "keystore"; 62 static String trustStoreFile = "truststore"; 63 static String passwd = "passphrase"; 64 private final static char[] cpasswd = "passphrase".toCharArray(); 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 getContext(true).getServerSocketFactory(); 94 SSLServerSocket sslServerSocket = 95 (SSLServerSocket) sslssf.createServerSocket(serverPort); 96 serverPort = sslServerSocket.getLocalPort(); 97 98 // enable endpoint identification 99 // ignore, we may test the feature when known how to parse client 100 // hostname 101 //SSLParameters params = sslServerSocket.getSSLParameters(); 102 //params.setEndpointIdentificationAlgorithm("HTTPS"); 103 //sslServerSocket.setSSLParameters(params); 104 105 /* 106 * Signal Client, we're ready for his connect. 107 */ 108 serverReady = true; 109 110 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 111 sslSocket.setNeedClientAuth(true); 112 InputStream sslIS = sslSocket.getInputStream(); 113 OutputStream sslOS = sslSocket.getOutputStream(); 114 115 sslIS.read(); 116 sslOS.write(85); 117 sslOS.flush(); 118 119 sslSocket.close(); 120 121 if (!serverTM.wasServerChecked() && serverTM.wasClientChecked()) { 122 System.out.println("SERVER TEST PASSED!"); 123 } else { 124 throw new Exception("SERVER TEST FAILED! " + 125 !serverTM.wasServerChecked() + " " + 126 serverTM.wasClientChecked()); 127 } 128 } 129 130 /* 131 * Define the client side of the test. 132 * 133 * If the server prematurely exits, serverReady will be set to true 134 * to avoid infinite hangs. 135 */ 136 void doClientSide() throws Exception { 137 138 /* 139 * Wait for server to get started. 140 */ 141 while (!serverReady) { 142 Thread.sleep(50); 143 } 144 145 SSLSocketFactory sslsf = getContext(false).getSocketFactory(); 146 SSLSocket sslSocket = (SSLSocket) 147 sslsf.createSocket("localhost", serverPort); 148 149 // enable endpoint identification 150 SSLParameters params = sslSocket.getSSLParameters(); 151 params.setEndpointIdentificationAlgorithm("HTTPS"); 152 sslSocket.setSSLParameters(params); 153 154 InputStream sslIS = sslSocket.getInputStream(); 155 OutputStream sslOS = sslSocket.getOutputStream(); 156 157 sslOS.write(280); 158 sslOS.flush(); 159 sslIS.read(); 160 161 sslSocket.close(); 162 163 if (clientTM.wasServerChecked() && !clientTM.wasClientChecked()) { 164 System.out.println("CLIENT TEST PASSED!"); 165 } else { 166 throw new Exception("CLIENT TEST FAILED! " + 167 clientTM.wasServerChecked() + " " + 168 !clientTM.wasClientChecked()); 169 } 170 } 171 172 MyExtendedX509TM serverTM; 173 MyExtendedX509TM clientTM; 174 175 private SSLContext getContext(boolean server) throws Exception { 176 String keyFilename = 177 System.getProperty("test.src", "./") + "/" + pathToStores + 178 "/" + keyStoreFile; 179 String trustFilename = 180 System.getProperty("test.src", "./") + "/" + pathToStores + 181 "/" + trustStoreFile; 182 183 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 184 KeyStore ks = KeyStore.getInstance("JKS"); 185 ks.load(new FileInputStream(keyFilename), cpasswd); 186 kmf.init(ks, cpasswd); 187 188 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 189 KeyStore ts = KeyStore.getInstance("JKS"); 190 ts.load(new FileInputStream(trustFilename), cpasswd); 191 tmf.init(ts); 192 193 TrustManager tms[] = tmf.getTrustManagers(); 194 if (tms == null || tms.length == 0) { 195 throw new Exception("unexpected trust manager implementation"); 196 } else { 197 if (!(tms[0] instanceof X509TrustManager)) { 198 throw new Exception("unexpected trust manager implementation: " 199 + tms[0].getClass().getCanonicalName()); 200 } 201 } 202 203 if (server) { 204 serverTM = new MyExtendedX509TM((X509TrustManager)tms[0]); 205 206 tms = new TrustManager[] {serverTM}; 207 } else { 208 clientTM = new MyExtendedX509TM((X509TrustManager)tms[0]); 209 210 tms = new TrustManager[] {clientTM}; 211 } 212 213 SSLContext ctx = SSLContext.getInstance("TLS"); 214 ctx.init(kmf.getKeyManagers(), tms, null); 215 216 return ctx; 217 } 218 219 static class MyExtendedX509TM extends X509ExtendedTrustManager 220 implements X509TrustManager { 221 222 X509TrustManager tm; 223 224 boolean clientChecked; 225 boolean serverChecked; 226 227 MyExtendedX509TM(X509TrustManager tm) { 228 clientChecked = false; 229 serverChecked = false; 230 231 this.tm = tm; 232 } 233 234 public boolean wasClientChecked() { 235 return clientChecked; 236 } 237 238 public boolean wasServerChecked() { 239 return serverChecked; 240 } 241 242 243 public void checkClientTrusted(X509Certificate chain[], String authType) 244 throws CertificateException { 245 tm.checkClientTrusted(chain, authType); 246 } 247 248 public void checkServerTrusted(X509Certificate chain[], String authType) 249 throws CertificateException { 250 tm.checkServerTrusted(chain, authType); 251 } 252 253 public X509Certificate[] getAcceptedIssuers() { 254 return tm.getAcceptedIssuers(); 255 } 256 257 public void checkClientTrusted(X509Certificate[] chain, String authType, 258 Socket socket) throws CertificateException { 259 clientChecked = true; 260 tm.checkClientTrusted(chain, authType); 261 } 262 263 public void checkServerTrusted(X509Certificate[] chain, String authType, 264 Socket socket) throws CertificateException { 265 serverChecked = true; 266 tm.checkServerTrusted(chain, authType); 267 } 268 269 public void checkClientTrusted(X509Certificate[] chain, String authType, 270 SSLEngine engine) throws CertificateException { 271 clientChecked = true; 272 tm.checkClientTrusted(chain, authType); 273 } 274 275 public void checkServerTrusted(X509Certificate[] chain, String authType, 276 SSLEngine engine) throws CertificateException { 277 serverChecked = true; 278 tm.checkServerTrusted(chain, authType); 279 } 280 } 281 282 /* 283 * ============================================================= 284 * The remainder is just support stuff 285 */ 286 287 // use any free port by default 288 volatile int serverPort = 0; 289 290 volatile Exception serverException = null; 291 volatile Exception clientException = null; 292 293 public static void main(String[] args) throws Exception { 294 295 if (debug) 296 System.setProperty("javax.net.debug", "all"); 297 298 /* 299 * Start the tests. 300 */ 301 new X509ExtendedTMEnabled(); 302 } 303 304 Thread clientThread = null; 305 Thread serverThread = null; 306 307 /* 308 * Primary constructor, used to drive remainder of the test. 309 * 310 * Fork off the other side, then do your work. 311 */ 312 X509ExtendedTMEnabled() throws Exception { 313 if (separateServerThread) { 314 startServer(true); 315 startClient(false); 316 } else { 317 startClient(true); 318 startServer(false); 319 } 320 321 /* 322 * Wait for other side to close down. 323 */ 324 if (separateServerThread) { 325 serverThread.join(); 326 } else { 327 clientThread.join(); 328 } 329 330 /* 331 * When we get here, the test is pretty much over. 332 * 333 * If the main thread excepted, that propagates back 334 * immediately. If the other thread threw an exception, we 335 * should report back. 336 */ 337 if (serverException != null) 338 throw serverException; 339 if (clientException != null) 340 throw clientException; 341 } 342 343 void startServer(boolean newThread) throws Exception { 344 if (newThread) { 345 serverThread = new Thread() { 346 public void run() { 347 try { 348 doServerSide(); 349 } catch (Exception e) { 350 /* 351 * Our server thread just died. 352 * 353 * Release the client, if not active already... 354 */ 355 System.err.println("Server died..."); 356 serverReady = true; 357 serverException = e; 358 } 359 } 360 }; 361 serverThread.start(); 362 } else { 363 doServerSide(); 364 } 365 } 366 367 void startClient(boolean newThread) throws Exception { 368 if (newThread) { 369 clientThread = new Thread() { 370 public void run() { 371 try { 372 doClientSide(); 373 } catch (Exception e) { 374 /* 375 * Our client thread just died. 376 */ 377 System.err.println("Client died..."); 378 clientException = e; 379 } 380 } 381 }; 382 clientThread.start(); 383 } else { 384 doClientSide(); 385 } 386 } 387} 388 389