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