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 24 import java.io.*; 25 import java.net.*; 26 import java.util.*; 27 import java.security.*; 28 import javax.net.*; 29 import javax.net.ssl.*; 30 31 public 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 Provider p2 = p.configure(System.getProperty("CUSTOM_P11_CONFIG")); 226 if (p2 != null) { 227 Security.addProvider(p2); 228 } else { 229 throw new Exception("Error: PKCS11 provider configuration failed"); 230 } 231 232 if (debug) { 233 System.setProperty("javax.net.debug", "all"); 234 } 235 236 /* 237 * Start the tests. 238 */ 239 go(); 240 } 241 242 Thread clientThread = null; 243 Thread serverThread = null; 244 245 /* 246 * Fork off the other side, then do your work. 247 */ 248 private void go() throws Exception { 249 try { 250 if (separateServerThread) { 251 startServer(true); 252 startClient(false); 253 } else { 254 startClient(true); 255 startServer(false); 256 } 257 } catch (Exception e) { 258 //swallow for now. Show later 259 } 260 261 /* 262 * Wait for other side to close down. 263 */ 264 if (separateServerThread) { 265 serverThread.join(); 266 } else { 267 clientThread.join(); 268 } 269 270 /* 271 * When we get here, the test is pretty much over. 272 * Which side threw the error? 273 */ 274 Exception local; 275 Exception remote; 276 String whichRemote; 277 278 if (separateServerThread) { 279 remote = serverException; 280 local = clientException; 281 whichRemote = "server"; 282 } else { 283 remote = clientException; 284 local = serverException; 285 whichRemote = "client"; 286 } 287 288 /* 289 * If both failed, return the curthread's exception, but also 290 * print the remote side Exception 291 */ 292 if ((local != null) && (remote != null)) { 293 System.out.println(whichRemote + " also threw:"); 294 remote.printStackTrace(); 295 System.out.println(); 296 throw local; 297 } 298 299 if (remote != null) { 300 throw remote; 301 } 302 303 if (local != null) { 304 throw local; 305 } 306 } 307 308 void startServer(boolean newThread) throws Exception { 309 if (newThread) { 310 serverThread = new Thread() { 311 public void run() { 312 try { 313 doServerSide(); 314 } catch (Exception e) { 315 /* 316 * Our server thread just died. 317 * 318 * Release the client, if not active already... 319 */ 320 System.err.println("Server died..."); 321 serverReady = true; 322 serverException = e; 323 } 324 } 325 }; 326 serverThread.start(); 327 } else { 328 try { 329 doServerSide(); 330 } catch (Exception e) { 331 serverException = e; 332 } finally { 333 serverReady = true; 334 } 335 } 336 } 337 338 void startClient(boolean newThread) throws Exception { 339 if (newThread) { 340 clientThread = new Thread() { 341 public void run() { 342 try { 343 doClientSide(); 344 } catch (Exception e) { 345 /* 346 * Our client thread just died. 347 */ 348 System.err.println("Client died..."); 349 clientException = e; 350 } 351 } 352 }; 353 clientThread.start(); 354 } else { 355 try { 356 doClientSide(); 357 } catch (Exception e) { 358 clientException = e; 359 } 360 } 361 } 362 }