1 /* 2 * Copyright (c) 2002, 2014, 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 4717766 27 * @author Brad Wetmore 28 * @summary 1.0.3 JsseX509TrustManager erroneously calls isClientTrusted() 29 * @run main/manual ClientServer 30 */ 31 32 /* 33 * SunJSSE does not support dynamic system properties, no way to re-use 34 * system properties in samevm/agentvm mode. 35 * 36 * JSSE supports algorithm constraints with CR 6916074, need to update 37 * this test case in JDK 7 soon. 38 * 39 * This problem didn't exist in JSSE 1.4, only JSSE 1.0.3. However, 40 * this is a useful test, so I decided to include it in 1.4.2. 41 */ 42 43 import java.io.*; 44 import java.net.*; 45 import javax.net.ssl.*; 46 import java.security.cert.*; 47 import java.security.*; 48 import com.sun.net.ssl.*; 49 50 public class ClientServer { 51 52 /* 53 * ============================================================= 54 * Set the various variables needed for the tests, then 55 * specify what tests to run on each side. 56 */ 57 58 /* 59 * Should we run the client or server in a separate thread? 60 * Both sides can throw exceptions, but do you have a preference 61 * as to which side should be the main thread. 62 */ 63 static boolean separateServerThread = true; 64 65 /* 66 * Where do we find the keystores? 67 */ 68 static String pathToStores = "../../../../javax/net/ssl/etc"; 69 static String keyStoreFile = "keystore"; 70 static String trustStoreFile = "truststore"; 71 static String passwd = "passphrase"; 72 73 /* 74 * Is the server ready to serve? 75 */ 76 volatile static boolean serverReady = false; 77 78 /* 79 * Turn on SSL debugging? 80 */ 81 static boolean debug = false; 82 83 /* 84 * If the client or server is doing some kind of object creation 85 * that the other side depends on, and that thread prematurely 86 * exits, you may experience a hang. The test harness will 87 * terminate all hung threads after its timeout has expired, 88 * currently 3 minutes by default, but you might try to be 89 * smart about it.... 90 */ 91 92 /* 93 * Define the server side of the test. 94 * 95 * If the server prematurely exits, serverReady will be set to true 96 * to avoid infinite hangs. 97 */ 98 void doServerSide() throws Exception { 99 SSLServerSocketFactory sslssf = getDefaultServer(); 100 SSLServerSocket sslServerSocket = 101 (SSLServerSocket) sslssf.createServerSocket(serverPort); 102 serverPort = sslServerSocket.getLocalPort(); 103 104 /* 105 * Signal Client, we're ready for his connect. 106 */ 107 serverReady = true; 108 109 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 110 sslSocket.setNeedClientAuth(true); 111 InputStream sslIS = sslSocket.getInputStream(); 112 OutputStream sslOS = sslSocket.getOutputStream(); 113 114 sslIS.read(); 115 sslOS.write(85); 116 sslOS.flush(); 117 118 sslSocket.close(); 119 120 if (!serverTM.wasServerChecked() && serverTM.wasClientChecked()) { 121 System.out.println("SERVER TEST PASSED!"); 122 } else { 123 throw new Exception("SERVER TEST FAILED! " + 124 !serverTM.wasServerChecked() + " " + 125 serverTM.wasClientChecked()); 126 } 127 } 128 129 /* 130 * Define the client side of the test. 131 * 132 * If the server prematurely exits, serverReady will be set to true 133 * to avoid infinite hangs. 134 */ 135 void doClientSide() throws Exception { 136 137 /* 138 * Wait for server to get started. 139 */ 140 while (!serverReady) { 141 Thread.sleep(50); 142 } 143 144 SSLSocketFactory sslsf = getDefaultClient(); 145 SSLSocket sslSocket = (SSLSocket) 146 sslsf.createSocket("localhost", serverPort); 147 148 InputStream sslIS = sslSocket.getInputStream(); 149 OutputStream sslOS = sslSocket.getOutputStream(); 150 151 sslOS.write(280); 152 sslOS.flush(); 153 sslIS.read(); 154 155 sslSocket.close(); 156 157 if (clientTM.wasServerChecked() && !clientTM.wasClientChecked()) { 158 System.out.println("CLIENT TEST PASSED!"); 159 } else { 160 throw new Exception("CLIENT TEST FAILED! " + 161 clientTM.wasServerChecked() + " " + 162 !clientTM.wasClientChecked()); 163 } 164 } 165 166 private com.sun.net.ssl.SSLContext getDefault(MyX509TM tm) 167 throws Exception { 168 169 String keyFilename = 170 System.getProperty("test.src", "./") + "/" + pathToStores + 171 "/" + keyStoreFile; 172 String trustFilename = 173 System.getProperty("test.src", "./") + "/" + pathToStores + 174 "/" + trustStoreFile; 175 176 char[] passphrase = "passphrase".toCharArray(); 177 KeyStore ks = KeyStore.getInstance("JKS"); 178 ks.load(new FileInputStream(keyFilename), passphrase); 179 180 com.sun.net.ssl.KeyManagerFactory kmf = 181 com.sun.net.ssl.KeyManagerFactory.getInstance("SunX509"); 182 kmf.init(ks, passphrase); 183 184 ks = KeyStore.getInstance("JKS"); 185 ks.load(new FileInputStream(trustFilename), passphrase); 186 187 com.sun.net.ssl.TrustManagerFactory tmf = 188 com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509"); 189 tmf.init(ks); 190 191 com.sun.net.ssl.TrustManager [] tms = tmf.getTrustManagers(); 192 193 int i; 194 for (i = 0; i < tms.length; i++) { 195 if (tms[i] instanceof com.sun.net.ssl.X509TrustManager) { 196 break; 197 } 198 } 199 200 if (i >= tms.length) { 201 throw new Exception("Couldn't find X509TM"); 202 } 203 204 tm.init((com.sun.net.ssl.X509TrustManager)tms[i]); 205 tms = new MyX509TM [] { tm }; 206 207 com.sun.net.ssl.SSLContext ctx = 208 com.sun.net.ssl.SSLContext.getInstance("TLS"); 209 ctx.init(kmf.getKeyManagers(), tms, null); 210 return ctx; 211 } 212 213 MyX509TM serverTM; 214 MyX509TM clientTM; 215 216 private SSLServerSocketFactory getDefaultServer() throws Exception { 217 serverTM = new MyX509TM(); 218 return getDefault(serverTM).getServerSocketFactory(); 219 } 220 221 private SSLSocketFactory getDefaultClient() throws Exception { 222 clientTM = new MyX509TM(); 223 return getDefault(clientTM).getSocketFactory(); 224 } 225 226 static class MyX509TM implements com.sun.net.ssl.X509TrustManager { 227 228 com.sun.net.ssl.X509TrustManager tm; 229 boolean clientChecked; 230 boolean serverChecked; 231 232 void init(com.sun.net.ssl.X509TrustManager x509TM) { 233 tm = x509TM; 234 } 235 236 public boolean wasClientChecked() { 237 return clientChecked; 238 } 239 240 public boolean wasServerChecked() { 241 return serverChecked; 242 } 243 244 public boolean isClientTrusted(X509Certificate[] chain) { 245 clientChecked = true; 246 return true; 247 } 248 249 public boolean isServerTrusted(X509Certificate[] chain) { 250 serverChecked = true; 251 return true; 252 } 253 254 public X509Certificate[] getAcceptedIssuers() { 255 return tm.getAcceptedIssuers(); 256 } 257 } 258 259 /* 260 * ============================================================= 261 * The remainder is just support stuff 262 */ 263 264 // use any free port by default 265 volatile int serverPort = 0; 266 267 volatile Exception serverException = null; 268 volatile Exception clientException = null; 269 270 public static void main(String[] args) throws Exception { 271 272 if (debug) 273 System.setProperty("javax.net.debug", "all"); 274 275 /* 276 * Start the tests. 277 */ 278 new ClientServer(); 279 } 280 281 Thread clientThread = null; 282 Thread serverThread = null; 283 284 /* 285 * Primary constructor, used to drive remainder of the test. 286 * 287 * Fork off the other side, then do your work. 288 */ 289 ClientServer() throws Exception { 290 if (separateServerThread) { 291 startServer(true); 292 startClient(false); 293 } else { 294 startClient(true); 295 startServer(false); 296 } 297 298 /* 299 * Wait for other side to close down. 300 */ 301 if (separateServerThread) { 302 serverThread.join(); 303 } else { 304 clientThread.join(); 305 } 306 307 /* 308 * When we get here, the test is pretty much over. 309 * 310 * If the main thread excepted, that propagates back 311 * immediately. If the other thread threw an exception, we 312 * should report back. 313 */ 314 if (serverException != null) 315 throw serverException; 316 if (clientException != null) 317 throw clientException; 318 } 319 320 void startServer(boolean newThread) throws Exception { 321 if (newThread) { 322 serverThread = new Thread() { 323 public void run() { 324 try { 325 doServerSide(); 326 } catch (Exception e) { 327 /* 328 * Our server thread just died. 329 * 330 * Release the client, if not active already... 331 */ 332 System.err.println("Server died..."); 333 serverReady = true; 334 serverException = e; 335 } 336 } 337 }; 338 serverThread.start(); 339 } else { 340 doServerSide(); 341 } 342 } 343 344 void startClient(boolean newThread) throws Exception { 345 if (newThread) { 346 clientThread = new Thread() { 347 public void run() { 348 try { 349 doClientSide(); 350 } catch (Exception e) { 351 /* 352 * Our client thread just died. 353 */ 354 System.err.println("Client died..."); 355 clientException = e; 356 } 357 } 358 }; 359 clientThread.start(); 360 } else { 361 doClientSide(); 362 } 363 } 364 }