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