1/* 2 * Copyright (c) 2003, 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. 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 24import java.io.*; 25import java.net.*; 26import java.util.*; 27import java.security.*; 28import javax.net.*; 29import javax.net.ssl.*; 30 31public class ClientAuth extends PKCS11Test { 32 33 /* 34 * ============================================================= 35 * Set the various variables needed for the tests, then 36 * specify what tests to run on each side. 37 */ 38 39 private static Provider provider; 40 private static final String NSS_PWD = "test12"; 41 private static final String JKS_PWD = "passphrase"; 42 private static final String SERVER_KS = "server.keystore"; 43 private static final String TS = "truststore"; 44 private static String p11config; 45 46 private static String DIR = System.getProperty("DIR"); 47 48 /* 49 * Should we run the client or server in a separate thread? 50 * Both sides can throw exceptions, but do you have a preference 51 * as to which side should be the main thread. 52 */ 53 static boolean separateServerThread = false; 54 55 /* 56 * Is the server ready to serve? 57 */ 58 volatile static boolean serverReady = false; 59 60 /* 61 * Turn on SSL debugging? 62 */ 63 static boolean debug = false; 64 65 /* 66 * If the client or server is doing some kind of object creation 67 * that the other side depends on, and that thread prematurely 68 * exits, you may experience a hang. The test harness will 69 * terminate all hung threads after its timeout has expired, 70 * currently 3 minutes by default, but you might try to be 71 * smart about it.... 72 */ 73 74 /* 75 * Define the server side of the test. 76 * 77 * If the server prematurely exits, serverReady will be set to true 78 * to avoid infinite hangs. 79 */ 80 void doServerSide() throws Exception { 81 82 SSLContext ctx = SSLContext.getInstance("TLS"); 83 char[] passphrase = JKS_PWD.toCharArray(); 84 85 // server gets KeyStore from JKS keystore 86 KeyStore ks = KeyStore.getInstance("JKS"); 87 ks.load(new FileInputStream(new File(DIR, SERVER_KS)), passphrase); 88 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 89 kmf.init(ks, passphrase); 90 91 // server gets TrustStore from PKCS#11 token 92/* 93 passphrase = NSS_PWD.toCharArray(); 94 KeyStore ts = KeyStore.getInstance("PKCS11", "SunPKCS11-nss"); 95 ts.load(null, passphrase); 96 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 97 tmf.init(ts); 98*/ 99 100 //ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 101 ctx.init(kmf.getKeyManagers(), null, null); 102 ServerSocketFactory ssf = ctx.getServerSocketFactory(); 103 SSLServerSocket sslServerSocket = (SSLServerSocket) 104 ssf.createServerSocket(serverPort); 105 sslServerSocket.setNeedClientAuth(true); 106 serverPort = sslServerSocket.getLocalPort(); 107 System.out.println("serverPort = " + serverPort); 108 109 /* 110 * Signal Client, we're ready for his connect. 111 */ 112 serverReady = true; 113 114 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 115 InputStream sslIS = sslSocket.getInputStream(); 116 OutputStream sslOS = sslSocket.getOutputStream(); 117 118 sslIS.read(); 119 sslOS.write(85); 120 sslOS.flush(); 121 122 sslSocket.close(); 123 } 124 125 /* 126 * Define the client side of the test. 127 * 128 * If the server prematurely exits, serverReady will be set to true 129 * to avoid infinite hangs. 130 */ 131 void doClientSide() throws Exception { 132 133 /* 134 * Wait for server to get started. 135 */ 136 while (!serverReady) { 137 Thread.sleep(50); 138 } 139 140 SSLContext ctx = SSLContext.getInstance("TLS"); 141 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 142 143 // client gets KeyStore from PKCS#11 token, 144 // and gets TrustStore from JKS KeyStore (using system properties) 145 char[] passphrase = NSS_PWD.toCharArray(); 146 KeyStore ks = KeyStore.getInstance("PKCS11", "SunPKCS11-nss"); 147 ks.load(null, passphrase); 148 149 kmf = KeyManagerFactory.getInstance("SunX509"); 150 kmf.init(ks, passphrase); 151 ctx.init(kmf.getKeyManagers(), null, null); 152 153 SSLSocketFactory sslsf = ctx.getSocketFactory(); 154 SSLSocket sslSocket = (SSLSocket) 155 sslsf.createSocket("localhost", serverPort); 156 157 if (clientProtocol != null) { 158 sslSocket.setEnabledProtocols(new String[] {clientProtocol}); 159 } 160 161 if (clientCiperSuite != null) { 162 sslSocket.setEnabledCipherSuites(new String[] {clientCiperSuite}); 163 } 164 165 InputStream sslIS = sslSocket.getInputStream(); 166 OutputStream sslOS = sslSocket.getOutputStream(); 167 168 sslOS.write(280); 169 sslOS.flush(); 170 sslIS.read(); 171 172 sslSocket.close(); 173 } 174 175 /* 176 * ============================================================= 177 * The remainder is just support stuff 178 */ 179 180 // use any free port by default 181 volatile int serverPort = 0; 182 183 volatile Exception serverException = null; 184 volatile Exception clientException = null; 185 186 private static String clientProtocol = null; 187 private static String clientCiperSuite = null; 188 189 private static void parseArguments(String[] args) { 190 if (args.length > 0) { 191 clientProtocol = args[0]; 192 } 193 194 if (args.length > 1) { 195 clientCiperSuite = args[1]; 196 } 197 } 198 199 public static void main(String[] args) throws Exception { 200 // Get the customized arguments. 201 parseArguments(args); 202 main(new ClientAuth()); 203 } 204 205 public void main(Provider p) throws Exception { 206 // SSL RSA client auth currently needs an RSA cipher 207 // (cf. NONEwithRSA hack), which is currently not available in 208 // open builds. 209 try { 210 javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding", p); 211 } catch (GeneralSecurityException e) { 212 System.out.println("Not supported by provider, skipping"); 213 return; 214 } 215 216 this.provider = p; 217 218 System.setProperty("javax.net.ssl.trustStore", 219 new File(DIR, TS).toString()); 220 System.setProperty("javax.net.ssl.trustStoreType", "JKS"); 221 System.setProperty("javax.net.ssl.trustStoreProvider", "SUN"); 222 System.setProperty("javax.net.ssl.trustStorePassword", JKS_PWD); 223 224 // perform Security.addProvider of P11 provider 225 Security.addProvider(getSunPKCS11(System.getProperty("CUSTOM_P11_CONFIG"))); 226 227 if (debug) { 228 System.setProperty("javax.net.debug", "all"); 229 } 230 231 /* 232 * Start the tests. 233 */ 234 go(); 235 } 236 237 Thread clientThread = null; 238 Thread serverThread = null; 239 240 /* 241 * Fork off the other side, then do your work. 242 */ 243 private void go() throws Exception { 244 try { 245 if (separateServerThread) { 246 startServer(true); 247 startClient(false); 248 } else { 249 startClient(true); 250 startServer(false); 251 } 252 } catch (Exception e) { 253 //swallow for now. Show later 254 } 255 256 /* 257 * Wait for other side to close down. 258 */ 259 if (separateServerThread) { 260 serverThread.join(); 261 } else { 262 clientThread.join(); 263 } 264 265 /* 266 * When we get here, the test is pretty much over. 267 * Which side threw the error? 268 */ 269 Exception local; 270 Exception remote; 271 String whichRemote; 272 273 if (separateServerThread) { 274 remote = serverException; 275 local = clientException; 276 whichRemote = "server"; 277 } else { 278 remote = clientException; 279 local = serverException; 280 whichRemote = "client"; 281 } 282 283 /* 284 * If both failed, return the curthread's exception, but also 285 * print the remote side Exception 286 */ 287 if ((local != null) && (remote != null)) { 288 System.out.println(whichRemote + " also threw:"); 289 remote.printStackTrace(); 290 System.out.println(); 291 throw local; 292 } 293 294 if (remote != null) { 295 throw remote; 296 } 297 298 if (local != null) { 299 throw local; 300 } 301 } 302 303 void startServer(boolean newThread) throws Exception { 304 if (newThread) { 305 serverThread = new Thread() { 306 public void run() { 307 try { 308 doServerSide(); 309 } catch (Exception e) { 310 /* 311 * Our server thread just died. 312 * 313 * Release the client, if not active already... 314 */ 315 System.err.println("Server died..."); 316 serverReady = true; 317 serverException = e; 318 } 319 } 320 }; 321 serverThread.start(); 322 } else { 323 try { 324 doServerSide(); 325 } catch (Exception e) { 326 serverException = e; 327 } finally { 328 serverReady = true; 329 } 330 } 331 } 332 333 void startClient(boolean newThread) throws Exception { 334 if (newThread) { 335 clientThread = new Thread() { 336 public void run() { 337 try { 338 doClientSide(); 339 } catch (Exception e) { 340 /* 341 * Our client thread just died. 342 */ 343 System.err.println("Client died..."); 344 clientException = e; 345 } 346 } 347 }; 348 clientThread.start(); 349 } else { 350 try { 351 doClientSide(); 352 } catch (Exception e) { 353 clientException = e; 354 } 355 } 356 } 357} 358