1/* 2 * Copyright (c) 2001, 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 4395238 4354003 4387961 4395266 27 * @summary A test of many of the new functionality to go into JSSE 1.1 28 * Fixed 4395238: The new certificate chains APIs should really be 29 * returning certs, not x509 certs 30 * Fixed 4354003: Need API to get client certificate chain 31 * Fixed 4387961: HostnameVerifier needs to pass various hostnames 32 * Fixed 4395266: HttpsURLConnection should be made protected 33 * @run main/othervm HttpsURLConnectionLocalCertificateChain 34 * 35 * SunJSSE does not support dynamic system properties, no way to re-use 36 * system properties in samevm/agentvm mode. 37 * @author Brad Wetmore 38 */ 39 40import java.io.*; 41import java.net.*; 42import javax.net.ssl.*; 43import java.security.cert.*; 44 45public class HttpsURLConnectionLocalCertificateChain 46 implements HandshakeCompletedListener, 47 HostnameVerifier { 48 49 /* 50 * ============================================================= 51 * Set the various variables needed for the tests, then 52 * specify what tests to run on each side. 53 */ 54 55 /* 56 * Should we run the client or server in a separate thread? 57 * Both sides can throw exceptions, but do you have a preference 58 * as to which side should be the main thread. 59 */ 60 static boolean separateServerThread = false; 61 62 /* 63 * Where do we find the keystores? 64 */ 65 static String pathToStores = "../etc"; 66 static String keyStoreFile = "keystore"; 67 static String trustStoreFile = "truststore"; 68 static String passwd = "passphrase"; 69 70 /* 71 * Is the server ready to serve? 72 */ 73 volatile static boolean serverReady = false; 74 75 /* 76 * Default Verifier 77 */ 78 public boolean verify(String hostname, SSLSession session) { 79 try { 80 Certificate [] certs = session.getPeerCertificates(); 81 82 for (int i = 0; i< certs.length; i++) { 83 if (certs[i] instanceof X509Certificate) { 84 System.out.println("Hostname Verification cert #1: "); 85 // System.out.println(certs[i].toString()); 86 } 87 } 88 } catch (Exception e) { 89 serverException = e; 90 } 91 return true; 92 } 93 94 /* 95 * The event sent by the app. 96 */ 97 HandshakeCompletedEvent event; 98 99 /* 100 * Provide the Listener for the HandshakeCompletedEvent 101 * Store the event now, we'll examine it later as we're 102 * finishing the test... 103 */ 104 public void handshakeCompleted(HandshakeCompletedEvent theEvent) { 105 event = theEvent; 106 } 107 108 void examineHandshakeCompletedEvent() throws Exception { 109 /* 110 * Also check the types during compile. We changed 111 * from cert.x509 to certs. 112 */ 113 dumpCerts("examineHandshakeCompletedEvent received", 114 event.getPeerCertificates()); 115 dumpCerts("examineHandshakeCompletedEvent sent", 116 event.getLocalCertificates()); 117 } 118 119 synchronized void dumpCerts(String where, Certificate [] certs) 120 throws Exception { 121 122 System.out.println(""); 123 System.out.println(where + ":"); 124 125 if (certs == null) { 126 throw new Exception("certs == null"); 127 } 128 129 for (int i = 0; i< certs.length; i++) { 130 if (certs[i] instanceof X509Certificate) { 131 System.out.println("cert #1: " + 132 ((X509Certificate) certs[i]).getSubjectDN()); 133 } 134 } 135 } 136 137 void doServerSide() throws Exception { 138 139 SSLServerSocketFactory sslssf; 140 SSLServerSocket sslServerSocket; 141 142 System.out.println("Starting Server..."); 143 sslssf = 144 (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 145 sslServerSocket = 146 (SSLServerSocket) sslssf.createServerSocket(serverPort); 147 serverPort = sslServerSocket.getLocalPort(); 148 System.out.println("Kicking off Client..."); 149 150 serverReady = true; 151 152 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 153 sslSocket.setNeedClientAuth(true); 154 sslSocket.addHandshakeCompletedListener(this); 155 156 InputStream sslIS = sslSocket.getInputStream(); 157 OutputStream sslOS = sslSocket.getOutputStream(); 158 DataOutputStream out = new DataOutputStream(sslOS); 159 160 System.out.println("Server reading request..."); 161 sslIS.read(); 162 163 System.out.println("Server replying..."); 164 try { 165 out.writeBytes("HTTP/1.0 200 OK\r\n"); 166 out.writeBytes("Content-Length: " + 1 + "\r\n"); 167 out.writeBytes("Content-Type: text/html\r\n\r\n"); 168 out.write(57); 169 out.flush(); 170 } catch (IOException ie) { 171 serverException = ie; 172 } 173 174 System.out.println("Server getting certs..."); 175 SSLSession sslSession = sslSocket.getSession(); 176 dumpCerts("ServerSide sent", sslSession.getLocalCertificates()); 177 dumpCerts("ServerSide received", sslSession.getPeerCertificates()); 178 179 /* 180 * Won't bother closing IS/sockets this time, we're exiting... 181 */ 182 183 /* 184 * We'll eventually get this event, wait for it. 185 */ 186 while (event == null) { 187 Thread.sleep(1000); 188 } 189 190 System.out.println("Server examining Event..."); 191 examineHandshakeCompletedEvent(); 192 } 193 194 void doClientSide() throws Exception { 195 196 /* 197 * Wait for server to get started. 198 */ 199 while (!serverReady) { 200 Thread.sleep(50); 201 } 202 203 System.out.println("Starting Client..."); 204 205 String url = "https://localhost:" + serverPort; 206 System.out.println("connecting to: " + url); 207 URL myURL = new URL(url); 208 HttpsURLConnection myURLc; 209 210 System.out.println("Client setting up URL/connecting..."); 211 myURLc = (HttpsURLConnection) myURL.openConnection(); 212 myURLc.setHostnameVerifier(this); 213 myURLc.connect(); 214 215 InputStream sslIS = myURLc.getInputStream(); 216 217 System.out.println("Client reading..."); 218 sslIS.read(); 219 220 System.out.println("Client dumping certs..."); 221 222 dumpCerts("ClientSide received", myURLc.getServerCertificates()); 223 dumpCerts("ClientSide sent", myURLc.getLocalCertificates()); 224 225 /* 226 * Won't bother closing IS/sockets this time, we're exiting... 227 */ 228 } 229 /* 230 * ============================================================= 231 * The remainder is just support stuff 232 */ 233 234 // use any free port by default 235 volatile int serverPort = 0; 236 237 volatile Exception serverException = null; 238 volatile Exception clientException = null; 239 240 public static void main(String[] args) throws Exception { 241 String keyFilename = 242 System.getProperty("test.src", "./") + "/" + pathToStores + 243 "/" + keyStoreFile; 244 String trustFilename = 245 System.getProperty("test.src", "./") + "/" + pathToStores + 246 "/" + trustStoreFile; 247 248 System.setProperty("javax.net.ssl.keyStore", keyFilename); 249 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 250 System.setProperty("javax.net.ssl.trustStore", trustFilename); 251 System.setProperty("javax.net.ssl.trustStorePassword", passwd); 252 253 /* 254 * Start the tests. 255 */ 256 new HttpsURLConnectionLocalCertificateChain(); 257 } 258 259 Thread clientThread = null; 260 Thread serverThread = null; 261 262 HttpsURLConnectionLocalCertificateChain () throws Exception { 263 if (separateServerThread) { 264 startServer(true); 265 startClient(false); 266 } else { 267 startClient(true); 268 startServer(false); 269 } 270 271 /* 272 * Wait for other side to close down. 273 */ 274 if (separateServerThread) { 275 serverThread.join(); 276 } else { 277 clientThread.join(); 278 } 279 280 /* 281 * When we get here, the test is pretty much over. 282 * 283 * If the main thread excepted, that propagates back 284 * immediately. If the other thread threw an exception, we 285 * should report back. 286 */ 287 if (serverException != null) 288 throw serverException; 289 if (clientException != null) 290 throw clientException; 291 } 292 293 void startServer(boolean newThread) throws Exception { 294 if (newThread) { 295 serverThread = new Thread() { 296 public void run() { 297 try { 298 doServerSide(); 299 } catch (Exception e) { 300 /* 301 * Our server thread just died. 302 * 303 * Release the client, if not active already... 304 */ 305 System.out.println("Server died..."); 306 serverReady = true; 307 serverException = e; 308 } 309 } 310 }; 311 serverThread.start(); 312 } else { 313 doServerSide(); 314 } 315 } 316 317 void startClient(boolean newThread) throws Exception { 318 if (newThread) { 319 clientThread = new Thread() { 320 public void run() { 321 try { 322 doClientSide(); 323 } catch (Exception e) { 324 /* 325 * Our client thread just died. 326 */ 327 System.out.println("Client died..."); 328 clientException = e; 329 } 330 } 331 }; 332 clientThread.start(); 333 } else { 334 doClientSide(); 335 } 336 } 337} 338