1 /* 2 * Copyright (c) 2011, 2015, 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 7113275 34 * @summary compatibility issue with MD2 trust anchor and old X509TrustManager 35 * @run main/othervm MD2InTrustAnchor PKIX TLSv1.1 36 * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.1 37 * @run main/othervm MD2InTrustAnchor PKIX TLSv1.2 38 * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2 39 */ 40 41 import java.net.*; 42 import java.util.*; 43 import java.io.*; 44 import javax.net.ssl.*; 45 import java.security.Security; 46 import java.security.KeyStore; 47 import java.security.KeyFactory; 48 import java.security.cert.Certificate; 49 import java.security.cert.CertificateFactory; 50 import java.security.spec.*; 51 import java.security.interfaces.*; 52 import java.util.Base64; 53 54 public class MD2InTrustAnchor { 55 56 /* 57 * ============================================================= 58 * Set the various variables needed for the tests, then 59 * specify what tests to run on each side. 60 */ 61 62 /* 63 * Should we run the client or server in a separate thread? 64 * Both sides can throw exceptions, but do you have a preference 65 * as to which side should be the main thread. 66 */ 67 static boolean separateServerThread = false; 68 69 /* 70 * Certificates and key used in the test. 71 */ 72 73 // It's a trust anchor signed with MD2 hash function. 74 static String trustedCertStr = 75 "-----BEGIN CERTIFICATE-----\n" + 76 "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" + 77 "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + 78 "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + 79 "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + 80 "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" + 81 "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" + 82 "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" + 83 "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" + 84 "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" + 85 "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + 86 "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" + 87 "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" + 88 "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" + 89 "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" + 90 "-----END CERTIFICATE-----"; 91 92 // The certificate issued by above trust anchor, signed with MD5 93 static String targetCertStr = 94 "-----BEGIN CERTIFICATE-----\n" + 95 "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + 96 "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + 97 "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" + 98 "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + 99 "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" + 100 "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" + 101 "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" + 102 "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" + 103 "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" + 104 "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + 105 "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" + 106 "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" + 107 "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" + 108 "yvudOlX4BkVR0l1K\n" + 109 "-----END CERTIFICATE-----"; 110 111 // Private key in the format of PKCS#8. 112 static String targetPrivateKey = 113 "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" + 114 "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" + 115 "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" + 116 "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" + 117 "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" + 118 "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" + 119 "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" + 120 "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" + 121 "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" + 122 "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" + 123 "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" + 124 "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" + 125 "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" + 126 "njWHoKY3axDQ8OU=\n"; 127 128 129 static char passphrase[] = "passphrase".toCharArray(); 130 131 /* 132 * Is the server ready to serve? 133 */ 134 volatile static boolean serverReady = false; 135 136 /* 137 * Turn on SSL debugging? 138 */ 139 static boolean debug = false; 140 141 /* 142 * Define the server side of the test. 143 * 144 * If the server prematurely exits, serverReady will be set to true 145 * to avoid infinite hangs. 146 */ 147 void doServerSide() throws Exception { 148 SSLContext context = generateSSLContext(trustedCertStr, targetCertStr, 149 targetPrivateKey); 150 SSLServerSocketFactory sslssf = context.getServerSocketFactory(); 151 SSLServerSocket sslServerSocket = 152 (SSLServerSocket)sslssf.createServerSocket(serverPort); 153 sslServerSocket.setNeedClientAuth(true); 154 serverPort = sslServerSocket.getLocalPort(); 155 156 /* 157 * Signal Client, we're ready for his connect. 158 */ 159 serverReady = true; 160 161 SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept(); 162 InputStream sslIS = sslSocket.getInputStream(); 163 OutputStream sslOS = sslSocket.getOutputStream(); 164 165 sslIS.read(); 166 sslOS.write('A'); 167 sslOS.flush(); 168 169 sslSocket.close(); 170 } 171 172 /* 173 * Define the client side of the test. 174 * 175 * If the server prematurely exits, serverReady will be set to true 176 * to avoid infinite hangs. 177 */ 178 void doClientSide() throws Exception { 179 180 /* 181 * Wait for server to get started. 182 */ 183 while (!serverReady) { 184 Thread.sleep(50); 185 } 186 187 SSLContext context = generateSSLContext(trustedCertStr, targetCertStr, 188 targetPrivateKey); 189 SSLSocketFactory sslsf = context.getSocketFactory(); 190 191 SSLSocket sslSocket = 192 (SSLSocket)sslsf.createSocket("localhost", serverPort); 193 194 // enable the specified TLS protocol 195 sslSocket.setEnabledProtocols(new String[] {tlsProtocol}); 196 197 InputStream sslIS = sslSocket.getInputStream(); 198 OutputStream sslOS = sslSocket.getOutputStream(); 199 200 sslOS.write('B'); 201 sslOS.flush(); 202 sslIS.read(); 203 204 sslSocket.close(); 205 } 206 207 /* 208 * ============================================================= 209 * The remainder is just support stuff 210 */ 211 private static String tmAlgorithm; // trust manager 212 private static String tlsProtocol; // trust manager 213 214 private static void parseArguments(String[] args) { 215 tmAlgorithm = args[0]; 216 tlsProtocol = args[1]; 217 } 218 219 private static SSLContext generateSSLContext(String trustedCertStr, 220 String keyCertStr, String keySpecStr) throws Exception { 221 222 // generate certificate from cert string 223 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 224 225 // create a key store 226 KeyStore ks = KeyStore.getInstance("JKS"); 227 ks.load(null, null); 228 229 // import the trused cert 230 Certificate trusedCert = null; 231 ByteArrayInputStream is = null; 232 if (trustedCertStr != null) { 233 is = new ByteArrayInputStream(trustedCertStr.getBytes()); 234 trusedCert = cf.generateCertificate(is); 235 is.close(); 236 237 ks.setCertificateEntry("RSA Export Signer", trusedCert); 238 } 239 240 if (keyCertStr != null) { 241 // generate the private key. 242 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 243 Base64.getMimeDecoder().decode(keySpecStr)); 244 KeyFactory kf = KeyFactory.getInstance("RSA"); 245 RSAPrivateKey priKey = 246 (RSAPrivateKey)kf.generatePrivate(priKeySpec); 247 248 // generate certificate chain 249 is = new ByteArrayInputStream(keyCertStr.getBytes()); 250 Certificate keyCert = cf.generateCertificate(is); 251 is.close(); 252 253 // It's not allowed to send MD2 signed certificate to peer, 254 // even it may be a trusted certificate. Then we will not 255 // place the trusted certficate in the chain. 256 Certificate[] chain = new Certificate[1]; 257 chain[0] = keyCert; 258 259 // import the key entry. 260 ks.setKeyEntry("Whatever", priKey, passphrase, chain); 261 } 262 263 // create SSL context 264 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); 265 tmf.init(ks); 266 267 SSLContext ctx = SSLContext.getInstance(tlsProtocol); 268 if (keyCertStr != null && !keyCertStr.isEmpty()) { 269 KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 270 kmf.init(ks, passphrase); 271 272 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 273 ks = null; 274 } else { 275 ctx.init(null, tmf.getTrustManagers(), null); 276 } 277 278 return ctx; 279 } 280 281 282 // use any free port by default 283 volatile int serverPort = 0; 284 285 volatile Exception serverException = null; 286 volatile Exception clientException = null; 287 288 public static void main(String[] args) throws Exception { 289 // MD5 is used in this test case, don't disable MD5 algorithm. 290 Security.setProperty("jdk.certpath.disabledAlgorithms", 291 "MD2, RSA keySize < 1024"); 292 Security.setProperty("jdk.tls.disabledAlgorithms", 293 "SSLv3, RC4, DH keySize < 768"); 294 295 if (debug) 296 System.setProperty("javax.net.debug", "all"); 297 298 /* 299 * Get the customized arguments. 300 */ 301 parseArguments(args); 302 303 /* 304 * Start the tests. 305 */ 306 new MD2InTrustAnchor(); 307 } 308 309 Thread clientThread = null; 310 Thread serverThread = null; 311 312 /* 313 * Primary constructor, used to drive remainder of the test. 314 * 315 * Fork off the other side, then do your work. 316 */ 317 MD2InTrustAnchor() throws Exception { 318 try { 319 if (separateServerThread) { 320 startServer(true); 321 startClient(false); 322 } else { 323 startClient(true); 324 startServer(false); 325 } 326 } catch (Exception e) { 327 // swallow for now. Show later 328 } 329 330 /* 331 * Wait for other side to close down. 332 */ 333 if (separateServerThread) { 334 serverThread.join(); 335 } else { 336 clientThread.join(); 337 } 338 339 /* 340 * When we get here, the test is pretty much over. 341 * Which side threw the error? 342 */ 343 Exception local; 344 Exception remote; 345 String whichRemote; 346 347 if (separateServerThread) { 348 remote = serverException; 349 local = clientException; 350 whichRemote = "server"; 351 } else { 352 remote = clientException; 353 local = serverException; 354 whichRemote = "client"; 355 } 356 357 /* 358 * If both failed, return the curthread's exception, but also 359 * print the remote side Exception 360 */ 361 if ((local != null) && (remote != null)) { 362 System.out.println(whichRemote + " also threw:"); 363 remote.printStackTrace(); 364 System.out.println(); 365 throw local; 366 } 367 368 if (remote != null) { 369 throw remote; 370 } 371 372 if (local != null) { 373 throw local; 374 } 375 } 376 377 void startServer(boolean newThread) throws Exception { 378 if (newThread) { 379 serverThread = new Thread() { 380 public void run() { 381 try { 382 doServerSide(); 383 } catch (Exception e) { 384 /* 385 * Our server thread just died. 386 * 387 * Release the client, if not active already... 388 */ 389 System.err.println("Server died..."); 390 serverReady = true; 391 serverException = e; 392 } 393 } 394 }; 395 serverThread.start(); 396 } else { 397 try { 398 doServerSide(); 399 } catch (Exception e) { 400 serverException = e; 401 } finally { 402 serverReady = true; 403 } 404 } 405 } 406 407 void startClient(boolean newThread) throws Exception { 408 if (newThread) { 409 clientThread = new Thread() { 410 public void run() { 411 try { 412 doClientSide(); 413 } catch (Exception e) { 414 /* 415 * Our client thread just died. 416 */ 417 System.err.println("Client died..."); 418 clientException = e; 419 } 420 } 421 }; 422 clientThread.start(); 423 } else { 424 try { 425 doClientSide(); 426 } catch (Exception e) { 427 clientException = e; 428 } 429 } 430 } 431 } | 1 /* 2 * Copyright (c) 2011, 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 7113275 34 * @summary compatibility issue with MD2 trust anchor and old X509TrustManager 35 * @run main/othervm MD2InTrustAnchor PKIX TLSv1.1 36 * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.1 37 * @run main/othervm MD2InTrustAnchor PKIX TLSv1.2 38 * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2 39 */ 40 import java.io.ByteArrayInputStream; 41 import java.io.InputStream; 42 import java.io.OutputStream; 43 import javax.net.ssl.*; 44 import java.security.Security; 45 import java.security.KeyStore; 46 import java.security.KeyFactory; 47 import java.security.cert.Certificate; 48 import java.security.cert.CertificateFactory; 49 import java.security.interfaces.RSAPrivateKey; 50 import java.security.spec.PKCS8EncodedKeySpec; 51 import java.util.Base64; 52 import java.util.concurrent.CountDownLatch; 53 54 public class MD2InTrustAnchor { 55 56 /* 57 * Certificates and key used in the test. 58 */ 59 // It's a trust anchor signed with MD2 hash function. 60 private static final String TRUSTED_CERT_STR = "-----BEGIN CERTIFICATE-----\n" 61 + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" 62 + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" 63 + "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" 64 + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" 65 + "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" 66 + "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" 67 + "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" 68 + "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" 69 + "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" 70 + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" 71 + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" 72 + "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" 73 + "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" 74 + "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" 75 + "-----END CERTIFICATE-----"; 76 77 // The certificate issued by above trust anchor, signed with MD5 78 private static final String TARGET_CERT_STR = "-----BEGIN CERTIFICATE-----\n" 79 + "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" 80 + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" 81 + "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" 82 + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" 83 + "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" 84 + "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" 85 + "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" 86 + "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" 87 + "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" 88 + "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" 89 + "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" 90 + "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" 91 + "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" 92 + "yvudOlX4BkVR0l1K\n" 93 + "-----END CERTIFICATE-----"; 94 95 // Private key in the format of PKCS#8. 96 private static final String TARGET_PRIV_KEY_STR = "MIICdwIBADANBgkqhkiG9w0B\n" 97 + "AQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4F5NVEtFXCbEFcVLRjMp3AL3j\n" 98 + "LswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa9+uHt0Z9Wmh4wjHAZhX5Tm5x\n" 99 + "p4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPMKBpyzK6rusorkwpWywTyvH1s\n" 100 + "016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+KSH9tFt+WQbiojjz9ac49trkv\n" 101 + "Ufu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck5mOIYV4uZK8jfNMSQ8v0tFEe\n" 102 + "IPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+HaY3d76hR5qly+Ys+Ww0CQQDj\n" 103 + "eOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ6t0v/xryVIdvOYcRBvKnqEog\n" 104 + "OH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7ez3TDpU9w1B0JXklcV5HddYsR\n" 105 + "qp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3ML11xwwJBAKsZ+Hur3x0tUY29\n" 106 + "No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDElhIM6Rqv12kwCMuQE9i7vo1o3\n" 107 + "WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXsekdXAA4d2d5zGI7q/aGD9SYU6\n" 108 + "phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRTA5kokFb+E3Gplu29tJvCUpfw\n" 109 + "gBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiEnjWHoKY3axDQ8OU="; 110 111 private static final char PASSPHRASE[] = "passphrase".toCharArray(); 112 113 /* 114 * Is the server ready to serve? 115 */ 116 private static volatile CountDownLatch sync = new CountDownLatch(1); 117 118 /* 119 * Turn on SSL debugging? 120 */ 121 private static final boolean DEBUG = false; 122 123 /* 124 * Define the server side of the test. 125 * 126 * If the server prematurely exits, serverReady will be set to true 127 * to avoid infinite hangs. 128 */ 129 private void doServerSide() throws Exception { 130 SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR, 131 TARGET_PRIV_KEY_STR); 132 SSLServerSocketFactory sslssf = context.getServerSocketFactory(); 133 try (SSLServerSocket sslServerSocket 134 = (SSLServerSocket) sslssf.createServerSocket(serverPort)) { 135 sslServerSocket.setNeedClientAuth(true); 136 serverPort = sslServerSocket.getLocalPort(); 137 /* 138 * Signal Client, we're ready for his connect. 139 */ 140 System.out.println("Signal server ready"); 141 sync.countDown(); 142 143 System.out.println("Waiting for client connection"); 144 try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept()) { 145 InputStream sslIS = sslSocket.getInputStream(); 146 OutputStream sslOS = sslSocket.getOutputStream(); 147 148 sslIS.read(); 149 sslOS.write('A'); 150 sslOS.flush(); 151 } 152 } 153 } 154 155 /* 156 * Define the client side of the test. 157 * 158 * If the server prematurely exits, serverReady will be set to true 159 * to avoid infinite hangs. 160 */ 161 private void doClientSide() throws Exception { 162 163 /* 164 * Wait for server to get started. 165 */ 166 System.out.println("Waiting for server ready"); 167 sync.await(); 168 169 SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR, 170 TARGET_PRIV_KEY_STR); 171 SSLSocketFactory sslsf = context.getSocketFactory(); 172 173 System.out.println("Connect to server on port: " + serverPort); 174 try (SSLSocket sslSocket 175 = (SSLSocket) sslsf.createSocket("localhost", serverPort)) { 176 // enable the specified TLS protocol 177 sslSocket.setEnabledProtocols(new String[]{tlsProtocol}); 178 179 InputStream sslIS = sslSocket.getInputStream(); 180 OutputStream sslOS = sslSocket.getOutputStream(); 181 182 sslOS.write('B'); 183 sslOS.flush(); 184 sslIS.read(); 185 } 186 } 187 188 /* 189 * ============================================================= 190 * The remainder is just support stuff 191 */ 192 private static String tmAlgorithm; // trust manager 193 private static String tlsProtocol; // trust manager 194 195 private static void parseArguments(String[] args) { 196 tmAlgorithm = args[0]; 197 tlsProtocol = args[1]; 198 } 199 200 private static SSLContext generateSSLContext(String trustedCertStr, 201 String keyCertStr, String keySpecStr) throws Exception { 202 203 // generate certificate from cert string 204 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 205 206 // create a key store 207 KeyStore ks = KeyStore.getInstance("JKS"); 208 ks.load(null, null); 209 210 // import the trused cert 211 Certificate trusedCert = null; 212 ByteArrayInputStream is = null; 213 if (trustedCertStr != null) { 214 is = new ByteArrayInputStream(trustedCertStr.getBytes()); 215 trusedCert = cf.generateCertificate(is); 216 is.close(); 217 218 ks.setCertificateEntry("RSA Export Signer", trusedCert); 219 } 220 221 if (keyCertStr != null) { 222 // generate the private key. 223 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 224 Base64.getMimeDecoder().decode(keySpecStr)); 225 KeyFactory kf = KeyFactory.getInstance("RSA"); 226 RSAPrivateKey priKey 227 = (RSAPrivateKey) kf.generatePrivate(priKeySpec); 228 229 // generate certificate chain 230 is = new ByteArrayInputStream(keyCertStr.getBytes()); 231 Certificate keyCert = cf.generateCertificate(is); 232 is.close(); 233 234 // It's not allowed to send MD2 signed certificate to peer, 235 // even it may be a trusted certificate. Then we will not 236 // place the trusted certficate in the chain. 237 Certificate[] chain = new Certificate[1]; 238 chain[0] = keyCert; 239 240 // import the key entry. 241 ks.setKeyEntry("Whatever", priKey, PASSPHRASE, chain); 242 } 243 244 // create SSL context 245 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); 246 tmf.init(ks); 247 248 SSLContext ctx = SSLContext.getInstance(tlsProtocol); 249 if (keyCertStr != null && !keyCertStr.isEmpty()) { 250 KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 251 kmf.init(ks, PASSPHRASE); 252 253 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 254 ks = null; 255 } else { 256 ctx.init(null, tmf.getTrustManagers(), null); 257 } 258 259 return ctx; 260 } 261 262 // use any free port by default 263 private volatile int serverPort = 0; 264 265 private volatile Exception serverException = null; 266 267 public static void main(String[] args) throws Exception { 268 // MD5 is used in this test case, don't disable MD5 algorithm. 269 Security.setProperty("jdk.certpath.disabledAlgorithms", 270 "MD2, RSA keySize < 1024"); 271 Security.setProperty("jdk.tls.disabledAlgorithms", 272 "SSLv3, RC4, DH keySize < 768"); 273 274 if (DEBUG) { 275 System.setProperty("javax.net.debug", "all"); 276 } 277 278 /* 279 * Get the customized arguments. 280 */ 281 parseArguments(args); 282 /* 283 * Start the tests. 284 */ 285 new MD2InTrustAnchor().runTest(); 286 } 287 288 private Thread serverThread = null; 289 290 /* 291 * Used to drive remainder of the test. 292 * 293 * Fork off the other side, then do your work. 294 */ 295 public void runTest() throws Exception { 296 startServerThread(); 297 doClientSide(); 298 299 /* 300 * Wait for other side to close down. 301 */ 302 serverThread.join(); 303 304 if (serverException != null) { 305 throw serverException; 306 } 307 } 308 309 private void startServerThread() { 310 serverThread = new Thread() { 311 @Override 312 public void run() { 313 try { 314 doServerSide(); 315 } catch (Exception e) { 316 /* 317 * Our server thread just died. 318 * 319 * Release the client, if not active already... 320 */ 321 System.err.println("Server died..."); 322 e.printStackTrace(System.out); 323 serverException = e; 324 sync.countDown(); 325 } 326 } 327 }; 328 329 serverThread.start(); 330 } 331 } |