Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
66645 views
1
/*
2
* Copyright (c) 2015, 2021, 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
// SunJSSE does not support dynamic system properties, no way to re-use
25
// system properties in samevm/agentvm mode.
26
27
/*
28
* @test
29
* @bug 8046321 8153829
30
* @summary OCSP Stapling for TLS
31
* @library ../../../../java/security/testlibrary
32
* @build CertificateBuilder SimpleOCSPServer
33
* @run main/othervm HttpsUrlConnClient RSA SHA256withRSA
34
* @run main/othervm HttpsUrlConnClient RSASSA-PSS RSASSA-PSS
35
*/
36
37
import java.io.*;
38
import java.math.BigInteger;
39
import java.security.KeyPair;
40
import java.security.KeyPairGenerator;
41
import java.net.Socket;
42
import java.net.URL;
43
import java.net.HttpURLConnection;
44
import java.net.InetAddress;
45
import javax.net.ssl.*;
46
import java.security.KeyStore;
47
import java.security.PublicKey;
48
import java.security.Security;
49
import java.security.GeneralSecurityException;
50
import java.security.cert.CertPathValidatorException;
51
import java.security.cert.CertPathValidatorException.BasicReason;
52
import java.security.cert.Certificate;
53
import java.security.cert.PKIXBuilderParameters;
54
import java.security.cert.X509CertSelector;
55
import java.security.cert.X509Certificate;
56
import java.security.cert.PKIXRevocationChecker;
57
import java.security.spec.PKCS8EncodedKeySpec;
58
import java.text.SimpleDateFormat;
59
import java.util.*;
60
import java.util.concurrent.TimeUnit;
61
62
import sun.security.testlibrary.SimpleOCSPServer;
63
import sun.security.testlibrary.CertificateBuilder;
64
65
public class HttpsUrlConnClient {
66
67
/*
68
* =============================================================
69
* Set the various variables needed for the tests, then
70
* specify what tests to run on each side.
71
*/
72
73
static final byte[] LINESEP = { 10 };
74
static final Base64.Encoder B64E = Base64.getMimeEncoder(64, LINESEP);
75
76
static String SIGALG;
77
static String KEYALG;
78
79
// Turn on TLS debugging
80
static boolean debug = true;
81
82
/*
83
* Should we run the client or server in a separate thread?
84
* Both sides can throw exceptions, but do you have a preference
85
* as to which side should be the main thread.
86
*/
87
static boolean separateServerThread = true;
88
Thread clientThread = null;
89
Thread serverThread = null;
90
91
static String passwd = "passphrase";
92
static String ROOT_ALIAS = "root";
93
static String INT_ALIAS = "intermediate";
94
static String SSL_ALIAS = "ssl";
95
96
/*
97
* Is the server ready to serve?
98
*/
99
volatile static boolean serverReady = false;
100
volatile int serverPort = 0;
101
102
volatile Exception serverException = null;
103
volatile Exception clientException = null;
104
105
// PKI components we will need for this test
106
static KeyStore rootKeystore; // Root CA Keystore
107
static KeyStore intKeystore; // Intermediate CA Keystore
108
static KeyStore serverKeystore; // SSL Server Keystore
109
static KeyStore trustStore; // SSL Client trust store
110
static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder
111
static int rootOcspPort; // Port number for root OCSP
112
static SimpleOCSPServer intOcsp; // Intermediate CA OCSP Responder
113
static int intOcspPort; // Port number for intermed. OCSP
114
115
// Extra configuration parameters and constants
116
static final String[] TLS13ONLY = new String[] { "TLSv1.3" };
117
static final String[] TLS12MAX =
118
new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" };
119
120
private static final String SIMPLE_WEB_PAGE = "<HTML>\n" +
121
"<HEAD><Title>Web Page!</Title></HEAD>\n" +
122
"<BODY><H1>Web Page!</H1></BODY>\n</HTML>";
123
private static final SimpleDateFormat utcDateFmt =
124
new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
125
/*
126
* If the client or server is doing some kind of object creation
127
* that the other side depends on, and that thread prematurely
128
* exits, you may experience a hang. The test harness will
129
* terminate all hung threads after its timeout has expired,
130
* currently 3 minutes by default, but you might try to be
131
* smart about it....
132
*/
133
public static void main(String[] args) throws Exception {
134
if (debug) {
135
System.setProperty("javax.net.debug", "ssl:handshake");
136
}
137
138
System.setProperty("javax.net.ssl.keyStore", "");
139
System.setProperty("javax.net.ssl.keyStorePassword", "");
140
System.setProperty("javax.net.ssl.trustStore", "");
141
System.setProperty("javax.net.ssl.trustStorePassword", "");
142
143
KEYALG = args[0];
144
SIGALG = args[1];
145
146
// Create the PKI we will use for the test and start the OCSP servers
147
createPKI();
148
utcDateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
149
150
testPKIXParametersRevEnabled(TLS12MAX);
151
testPKIXParametersRevEnabled(TLS13ONLY);
152
153
// shut down the OCSP responders before finishing the test
154
intOcsp.stop();
155
rootOcsp.stop();
156
}
157
158
/**
159
* Do a basic connection using PKIXParameters with revocation checking
160
* enabled and client-side OCSP disabled. It will only pass if all
161
* stapled responses are present, valid and have a GOOD status.
162
*/
163
static void testPKIXParametersRevEnabled(String[] allowedProts)
164
throws Exception {
165
ClientParameters cliParams = new ClientParameters();
166
cliParams.protocols = allowedProts;
167
ServerParameters servParams = new ServerParameters();
168
serverReady = false;
169
170
System.out.println("=====================================");
171
System.out.println("Stapling enabled, PKIXParameters with");
172
System.out.println("Revocation checking enabled ");
173
System.out.println("=====================================");
174
175
// Set the certificate entry in the intermediate OCSP responder
176
// with a revocation date of 8 hours ago.
177
X509Certificate sslCert =
178
(X509Certificate)serverKeystore.getCertificate(SSL_ALIAS);
179
Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
180
new HashMap<>();
181
revInfo.put(sslCert.getSerialNumber(),
182
new SimpleOCSPServer.CertStatusInfo(
183
SimpleOCSPServer.CertStatus.CERT_STATUS_REVOKED,
184
new Date(System.currentTimeMillis() -
185
TimeUnit.HOURS.toMillis(8))));
186
intOcsp.updateStatusDb(revInfo);
187
188
// Set up revocation checking on the client with no client-side
189
// OCSP fall-back
190
cliParams.pkixParams = new PKIXBuilderParameters(trustStore,
191
new X509CertSelector());
192
cliParams.pkixParams.setRevocationEnabled(true);
193
Security.setProperty("ocsp.enable", "false");
194
195
HttpsUrlConnClient sslTest = new HttpsUrlConnClient(cliParams,
196
servParams);
197
TestResult tr = sslTest.getResult();
198
if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) {
199
if (tr.clientExc != null) {
200
throw tr.clientExc;
201
} else {
202
throw new RuntimeException(
203
"Expected client failure, but the client succeeded");
204
}
205
}
206
207
// In this case the server should also have thrown an exception
208
// because of the client alert
209
if (tr.serverExc instanceof SSLHandshakeException) {
210
if (!tr.serverExc.getMessage().contains(
211
"bad_certificate_status_response")) {
212
throw tr.serverExc;
213
}
214
}
215
216
System.out.println(" PASS");
217
System.out.println("=====================================\n");
218
}
219
220
/*
221
* Define the server side of the test.
222
*
223
* If the server prematurely exits, serverReady will be set to true
224
* to avoid infinite hangs.
225
*/
226
void doServerSide(ServerParameters servParams) throws Exception {
227
228
// Selectively enable or disable the feature
229
System.setProperty("jdk.tls.server.enableStatusRequestExtension",
230
Boolean.toString(servParams.enabled));
231
232
// Set all the other operating parameters
233
System.setProperty("jdk.tls.stapling.cacheSize",
234
Integer.toString(servParams.cacheSize));
235
System.setProperty("jdk.tls.stapling.cacheLifetime",
236
Integer.toString(servParams.cacheLifetime));
237
System.setProperty("jdk.tls.stapling.responseTimeout",
238
Integer.toString(servParams.respTimeout));
239
System.setProperty("jdk.tls.stapling.responderURI", servParams.respUri);
240
System.setProperty("jdk.tls.stapling.responderOverride",
241
Boolean.toString(servParams.respOverride));
242
System.setProperty("jdk.tls.stapling.ignoreExtensions",
243
Boolean.toString(servParams.ignoreExts));
244
245
// Set keystores and trust stores for the server
246
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
247
kmf.init(serverKeystore, passwd.toCharArray());
248
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
249
tmf.init(trustStore);
250
251
SSLContext sslc = SSLContext.getInstance("TLS");
252
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
253
254
SSLServerSocketFactory sslssf = sslc.getServerSocketFactory();
255
SSLServerSocket sslServerSocket =
256
(SSLServerSocket) sslssf.createServerSocket(serverPort);
257
258
serverPort = sslServerSocket.getLocalPort();
259
log("Server Port is " + serverPort);
260
261
// Dump the private key in PKCS8 format, not encrypted. This
262
// key dump can be used if the traffic was captured using tcpdump
263
// or wireshark to look into the encrypted packets for debug purposes.
264
if (debug) {
265
byte[] keybytes = serverKeystore.getKey(SSL_ALIAS,
266
passwd.toCharArray()).getEncoded();
267
PKCS8EncodedKeySpec p8spec = new PKCS8EncodedKeySpec(keybytes);
268
StringBuilder keyPem = new StringBuilder();
269
keyPem.append("-----BEGIN PRIVATE KEY-----\n");
270
keyPem.append(B64E.encodeToString(p8spec.getEncoded())).append("\n");
271
keyPem.append("-----END PRIVATE KEY-----\n");
272
log("Private key is:\n" + keyPem.toString());
273
}
274
275
/*
276
* Signal Client, we're ready for his connect.
277
*/
278
serverReady = true;
279
280
try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
281
BufferedReader in = new BufferedReader(
282
new InputStreamReader(sslSocket.getInputStream()));
283
OutputStream out = sslSocket.getOutputStream()) {
284
StringBuilder hdrBldr = new StringBuilder();
285
String line;
286
while ((line = in.readLine()) != null && !line.isEmpty()) {
287
hdrBldr.append(line).append("\n");
288
}
289
String headerText = hdrBldr.toString();
290
log("Header Received: " + headerText.length() + " bytes\n" +
291
headerText);
292
293
StringBuilder sb = new StringBuilder();
294
sb.append("HTTP/1.0 200 OK\r\n");
295
sb.append("Date: ").append(utcDateFmt.format(new Date())).
296
append("\r\n");
297
sb.append("Content-Type: text/html\r\n");
298
sb.append("Content-Length: ").append(SIMPLE_WEB_PAGE.length());
299
sb.append("\r\n\r\n");
300
out.write(sb.toString().getBytes("UTF-8"));
301
out.write(SIMPLE_WEB_PAGE.getBytes("UTF-8"));
302
out.flush();
303
log("Server replied with:\n" + sb.toString() + SIMPLE_WEB_PAGE);
304
}
305
}
306
307
/*
308
* Define the client side of the test.
309
*
310
* If the server prematurely exits, serverReady will be set to true
311
* to avoid infinite hangs.
312
*/
313
void doClientSide(ClientParameters cliParams) throws Exception {
314
315
// Wait 5 seconds for server ready
316
for (int i = 0; (i < 100 && !serverReady); i++) {
317
Thread.sleep(50);
318
}
319
if (!serverReady) {
320
throw new RuntimeException("Server not ready yet");
321
}
322
323
// Selectively enable or disable the feature
324
System.setProperty("jdk.tls.client.enableStatusRequestExtension",
325
Boolean.toString(cliParams.enabled));
326
327
HtucSSLSocketFactory sockFac = new HtucSSLSocketFactory(cliParams);
328
HttpsURLConnection.setDefaultSSLSocketFactory(sockFac);
329
URL location = new URL("https://localhost:" + serverPort);
330
HttpsURLConnection tlsConn =
331
(HttpsURLConnection)location.openConnection();
332
tlsConn.setConnectTimeout(5000);
333
tlsConn.setReadTimeout(5000);
334
tlsConn.setDoInput(true);
335
336
try (InputStream in = tlsConn.getInputStream()) {
337
// Check the response
338
if (debug && tlsConn.getResponseCode() !=
339
HttpURLConnection.HTTP_OK) {
340
log("Received HTTP error: " + tlsConn.getResponseCode() +
341
" - " + tlsConn.getResponseMessage());
342
throw new IOException("HTTP error: " +
343
tlsConn.getResponseCode());
344
}
345
346
int contentLength = tlsConn.getContentLength();
347
if (contentLength == -1) {
348
contentLength = Integer.MAX_VALUE;
349
}
350
byte[] response = new byte[contentLength > 2048 ? 2048 :
351
contentLength];
352
int total = 0;
353
while (total < contentLength) {
354
int count = in.read(response, total, response.length - total);
355
if (count < 0)
356
break;
357
358
total += count;
359
log("Read " + count + " bytes (" + total + " total)");
360
if (total >= response.length && total < contentLength) {
361
response = Arrays.copyOf(response, total * 2);
362
}
363
}
364
response = Arrays.copyOf(response, total);
365
String webPage = new String(response, 0, total);
366
if (debug) {
367
log("Web page:\n" + webPage);
368
}
369
}
370
}
371
372
/*
373
* Primary constructor, used to drive remainder of the test.
374
*
375
* Fork off the other side, then do your work.
376
*/
377
HttpsUrlConnClient(ClientParameters cliParams,
378
ServerParameters servParams) throws Exception {
379
Exception startException = null;
380
try {
381
if (separateServerThread) {
382
startServer(servParams, true);
383
startClient(cliParams, false);
384
} else {
385
startClient(cliParams, true);
386
startServer(servParams, false);
387
}
388
} catch (Exception e) {
389
startException = e;
390
}
391
392
/*
393
* Wait for other side to close down.
394
*/
395
if (separateServerThread) {
396
if (serverThread != null) {
397
serverThread.join();
398
}
399
} else {
400
if (clientThread != null) {
401
clientThread.join();
402
}
403
}
404
}
405
406
/**
407
* Checks a validation failure to see if it failed for the reason we think
408
* it should. This comes in as an SSLException of some sort, but it
409
* encapsulates a CertPathValidatorException at some point in the
410
* exception stack.
411
*
412
* @param e the exception thrown at the top level
413
* @param reason the underlying CertPathValidatorException BasicReason
414
* we are expecting it to have.
415
*
416
* @return true if the reason matches up, false otherwise.
417
*/
418
static boolean checkClientValidationFailure(Exception e,
419
BasicReason reason) {
420
boolean result = false;
421
422
// Locate the CertPathValidatorException. If one
423
// Does not exist, then it's an automatic failure of
424
// the test.
425
Throwable curExc = e;
426
CertPathValidatorException cpve = null;
427
while (curExc != null) {
428
if (curExc instanceof CertPathValidatorException) {
429
cpve = (CertPathValidatorException)curExc;
430
}
431
curExc = curExc.getCause();
432
}
433
434
// If we get through the loop and cpve is null then we
435
// we didn't find CPVE and this is a failure
436
if (cpve != null) {
437
if (cpve.getReason() == reason) {
438
result = true;
439
} else {
440
System.out.println("CPVE Reason Mismatch: Expected = " +
441
reason + ", Actual = " + cpve.getReason());
442
}
443
} else {
444
System.out.println("Failed to find an expected CPVE");
445
}
446
447
return result;
448
}
449
450
TestResult getResult() {
451
TestResult tr = new TestResult();
452
tr.clientExc = clientException;
453
tr.serverExc = serverException;
454
return tr;
455
}
456
457
final void startServer(ServerParameters servParams, boolean newThread)
458
throws Exception {
459
if (newThread) {
460
serverThread = new Thread() {
461
@Override
462
public void run() {
463
try {
464
doServerSide(servParams);
465
} catch (Exception e) {
466
/*
467
* Our server thread just died.
468
*
469
* Release the client, if not active already...
470
*/
471
System.err.println("Server died...");
472
serverReady = true;
473
serverException = e;
474
}
475
}
476
};
477
serverThread.start();
478
} else {
479
try {
480
doServerSide(servParams);
481
} catch (Exception e) {
482
serverException = e;
483
} finally {
484
serverReady = true;
485
}
486
}
487
}
488
489
final void startClient(ClientParameters cliParams, boolean newThread)
490
throws Exception {
491
if (newThread) {
492
clientThread = new Thread() {
493
@Override
494
public void run() {
495
try {
496
doClientSide(cliParams);
497
} catch (Exception e) {
498
/*
499
* Our client thread just died.
500
*/
501
System.err.println("Client died...");
502
clientException = e;
503
}
504
}
505
};
506
clientThread.start();
507
} else {
508
try {
509
doClientSide(cliParams);
510
} catch (Exception e) {
511
clientException = e;
512
}
513
}
514
}
515
516
/**
517
* Creates the PKI components necessary for this test, including
518
* Root CA, Intermediate CA and SSL server certificates, the keystores
519
* for each entity, a client trust store, and starts the OCSP responders.
520
*/
521
private static void createPKI() throws Exception {
522
CertificateBuilder cbld = new CertificateBuilder();
523
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KEYALG);
524
keyGen.initialize(2048);
525
KeyStore.Builder keyStoreBuilder =
526
KeyStore.Builder.newInstance("PKCS12", null,
527
new KeyStore.PasswordProtection(passwd.toCharArray()));
528
529
// Generate Root, IntCA, EE keys
530
KeyPair rootCaKP = keyGen.genKeyPair();
531
log("Generated Root CA KeyPair");
532
KeyPair intCaKP = keyGen.genKeyPair();
533
log("Generated Intermediate CA KeyPair");
534
KeyPair sslKP = keyGen.genKeyPair();
535
log("Generated SSL Cert KeyPair");
536
537
// Set up the Root CA Cert
538
cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany");
539
cbld.setPublicKey(rootCaKP.getPublic());
540
cbld.setSerialNumber(new BigInteger("1"));
541
// Make a 3 year validity starting from 60 days ago
542
long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
543
long end = start + TimeUnit.DAYS.toMillis(1085);
544
cbld.setValidity(new Date(start), new Date(end));
545
addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic());
546
addCommonCAExts(cbld);
547
// Make our Root CA Cert!
548
X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(),
549
SIGALG);
550
log("Root CA Created:\n" + certInfo(rootCert));
551
552
// Now build a keystore and add the keys and cert
553
rootKeystore = keyStoreBuilder.getKeyStore();
554
Certificate[] rootChain = {rootCert};
555
rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(),
556
passwd.toCharArray(), rootChain);
557
558
// Now fire up the OCSP responder
559
rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null);
560
rootOcsp.enableLog(debug);
561
rootOcsp.setNextUpdateInterval(3600);
562
rootOcsp.start();
563
564
// Wait 5 seconds for server ready
565
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
566
Thread.sleep(50);
567
}
568
if (!rootOcsp.isServerReady()) {
569
throw new RuntimeException("Server not ready yet");
570
}
571
572
rootOcspPort = rootOcsp.getPort();
573
String rootRespURI = "http://localhost:" + rootOcspPort;
574
log("Root OCSP Responder URI is " + rootRespURI);
575
576
// Now that we have the root keystore and OCSP responder we can
577
// create our intermediate CA.
578
cbld.reset();
579
cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany");
580
cbld.setPublicKey(intCaKP.getPublic());
581
cbld.setSerialNumber(new BigInteger("100"));
582
// Make a 2 year validity starting from 30 days ago
583
start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30);
584
end = start + TimeUnit.DAYS.toMillis(730);
585
cbld.setValidity(new Date(start), new Date(end));
586
addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic());
587
addCommonCAExts(cbld);
588
cbld.addAIAExt(Collections.singletonList(rootRespURI));
589
// Make our Intermediate CA Cert!
590
X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(),
591
SIGALG);
592
log("Intermediate CA Created:\n" + certInfo(intCaCert));
593
594
// Provide intermediate CA cert revocation info to the Root CA
595
// OCSP responder.
596
Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
597
new HashMap<>();
598
revInfo.put(intCaCert.getSerialNumber(),
599
new SimpleOCSPServer.CertStatusInfo(
600
SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
601
rootOcsp.updateStatusDb(revInfo);
602
603
// Now build a keystore and add the keys, chain and root cert as a TA
604
intKeystore = keyStoreBuilder.getKeyStore();
605
Certificate[] intChain = {intCaCert, rootCert};
606
intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(),
607
passwd.toCharArray(), intChain);
608
intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
609
610
// Now fire up the Intermediate CA OCSP responder
611
intOcsp = new SimpleOCSPServer(intKeystore, passwd,
612
INT_ALIAS, null);
613
intOcsp.enableLog(debug);
614
intOcsp.setNextUpdateInterval(3600);
615
intOcsp.start();
616
617
// Wait 5 seconds for server ready
618
for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {
619
Thread.sleep(50);
620
}
621
if (!intOcsp.isServerReady()) {
622
throw new RuntimeException("Server not ready yet");
623
}
624
625
intOcspPort = intOcsp.getPort();
626
String intCaRespURI = "http://localhost:" + intOcspPort;
627
log("Intermediate CA OCSP Responder URI is " + intCaRespURI);
628
629
// Last but not least, let's make our SSLCert and add it to its own
630
// Keystore
631
cbld.reset();
632
cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany");
633
cbld.setPublicKey(sslKP.getPublic());
634
cbld.setSerialNumber(new BigInteger("4096"));
635
// Make a 1 year validity starting from 7 days ago
636
start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7);
637
end = start + TimeUnit.DAYS.toMillis(365);
638
cbld.setValidity(new Date(start), new Date(end));
639
640
// Add extensions
641
addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic());
642
boolean[] kuBits = {true, false, true, false, false, false,
643
false, false, false};
644
cbld.addKeyUsageExt(kuBits);
645
List<String> ekuOids = new ArrayList<>();
646
ekuOids.add("1.3.6.1.5.5.7.3.1");
647
ekuOids.add("1.3.6.1.5.5.7.3.2");
648
cbld.addExtendedKeyUsageExt(ekuOids);
649
cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost"));
650
cbld.addAIAExt(Collections.singletonList(intCaRespURI));
651
// Make our SSL Server Cert!
652
X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(),
653
SIGALG);
654
log("SSL Certificate Created:\n" + certInfo(sslCert));
655
656
// Provide SSL server cert revocation info to the Intermeidate CA
657
// OCSP responder.
658
revInfo = new HashMap<>();
659
revInfo.put(sslCert.getSerialNumber(),
660
new SimpleOCSPServer.CertStatusInfo(
661
SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
662
intOcsp.updateStatusDb(revInfo);
663
664
// Now build a keystore and add the keys, chain and root cert as a TA
665
serverKeystore = keyStoreBuilder.getKeyStore();
666
Certificate[] sslChain = {sslCert, intCaCert, rootCert};
667
serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(),
668
passwd.toCharArray(), sslChain);
669
serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
670
671
// And finally a Trust Store for the client
672
trustStore = keyStoreBuilder.getKeyStore();
673
trustStore.setCertificateEntry(ROOT_ALIAS, rootCert);
674
}
675
676
private static void addCommonExts(CertificateBuilder cbld,
677
PublicKey subjKey, PublicKey authKey) throws IOException {
678
cbld.addSubjectKeyIdExt(subjKey);
679
cbld.addAuthorityKeyIdExt(authKey);
680
}
681
682
private static void addCommonCAExts(CertificateBuilder cbld)
683
throws IOException {
684
cbld.addBasicConstraintsExt(true, true, -1);
685
// Set key usage bits for digitalSignature, keyCertSign and cRLSign
686
boolean[] kuBitSettings = {true, false, false, false, false, true,
687
true, false, false};
688
cbld.addKeyUsageExt(kuBitSettings);
689
}
690
691
/**
692
* Helper routine that dumps only a few cert fields rather than
693
* the whole toString() output.
694
*
695
* @param cert an X509Certificate to be displayed
696
*
697
* @return the String output of the issuer, subject and
698
* serial number
699
*/
700
private static String certInfo(X509Certificate cert) {
701
StringBuilder sb = new StringBuilder();
702
sb.append("Issuer: ").append(cert.getIssuerX500Principal()).
703
append("\n");
704
sb.append("Subject: ").append(cert.getSubjectX500Principal()).
705
append("\n");
706
sb.append("Serial: ").append(cert.getSerialNumber()).append("\n");
707
return sb.toString();
708
}
709
710
/**
711
* Log a message on stdout
712
*
713
* @param message The message to log
714
*/
715
private static void log(String message) {
716
if (debug) {
717
System.out.println(message);
718
}
719
}
720
721
// The following two classes are Simple nested class to group a handful
722
// of configuration parameters used before starting a client or server.
723
// We'll just access the data members directly for convenience.
724
static class ClientParameters {
725
boolean enabled = true;
726
PKIXBuilderParameters pkixParams = null;
727
PKIXRevocationChecker revChecker = null;
728
String[] protocols = null;
729
String[] cipherSuites = null;
730
731
ClientParameters() { }
732
}
733
734
static class ServerParameters {
735
boolean enabled = true;
736
int cacheSize = 256;
737
int cacheLifetime = 3600;
738
int respTimeout = 5000;
739
String respUri = "";
740
boolean respOverride = false;
741
boolean ignoreExts = false;
742
743
ServerParameters() { }
744
}
745
746
static class TestResult {
747
Exception serverExc = null;
748
Exception clientExc = null;
749
750
@Override
751
public String toString() {
752
StringBuilder sb = new StringBuilder();
753
sb.append("Test Result:\n").
754
append("\tServer Exc = ").append(serverExc).append("\n").
755
append("\tClient Exc = ").append(clientExc).append("\n");
756
return sb.toString();
757
}
758
}
759
760
static class HtucSSLSocketFactory extends SSLSocketFactory {
761
ClientParameters params;
762
SSLContext sslc = SSLContext.getInstance("TLS");
763
764
HtucSSLSocketFactory(ClientParameters cliParams)
765
throws GeneralSecurityException {
766
super();
767
768
// Create the Trust Manager Factory using the PKIX variant
769
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
770
771
// If we have a customized pkixParameters then use it
772
if (cliParams.pkixParams != null) {
773
// LIf we have a customized PKIXRevocationChecker, add
774
// it to the PKIXBuilderParameters.
775
if (cliParams.revChecker != null) {
776
cliParams.pkixParams.addCertPathChecker(
777
cliParams.revChecker);
778
}
779
780
ManagerFactoryParameters trustParams =
781
new CertPathTrustManagerParameters(
782
cliParams.pkixParams);
783
tmf.init(trustParams);
784
} else {
785
tmf.init(trustStore);
786
}
787
788
sslc.init(null, tmf.getTrustManagers(), null);
789
params = cliParams;
790
}
791
792
@Override
793
public Socket createSocket(Socket s, String host, int port,
794
boolean autoClose) throws IOException {
795
Socket sock = sslc.getSocketFactory().createSocket(s, host, port,
796
autoClose);
797
customizeSocket(sock);
798
return sock;
799
}
800
801
@Override
802
public Socket createSocket(InetAddress host, int port)
803
throws IOException {
804
Socket sock = sslc.getSocketFactory().createSocket(host, port);
805
customizeSocket(sock);
806
return sock;
807
}
808
809
@Override
810
public Socket createSocket(InetAddress host, int port,
811
InetAddress localAddress, int localPort) throws IOException {
812
Socket sock = sslc.getSocketFactory().createSocket(host, port,
813
localAddress, localPort);
814
customizeSocket(sock);
815
return sock;
816
}
817
818
@Override
819
public Socket createSocket(String host, int port)
820
throws IOException {
821
Socket sock = sslc.getSocketFactory().createSocket(host, port);
822
customizeSocket(sock);
823
return sock;
824
}
825
826
@Override
827
public Socket createSocket(String host, int port,
828
InetAddress localAddress, int localPort)
829
throws IOException {
830
Socket sock = sslc.getSocketFactory().createSocket(host, port,
831
localAddress, localPort);
832
customizeSocket(sock);
833
return sock;
834
}
835
836
@Override
837
public String[] getDefaultCipherSuites() {
838
return sslc.getDefaultSSLParameters().getCipherSuites();
839
}
840
841
@Override
842
public String[] getSupportedCipherSuites() {
843
return sslc.getSupportedSSLParameters().getCipherSuites();
844
}
845
846
private void customizeSocket(Socket sock) {
847
if (sock instanceof SSLSocket) {
848
SSLSocket sslSock = (SSLSocket)sock;
849
if (params.protocols != null) {
850
sslSock.setEnabledProtocols(params.protocols);
851
}
852
if (params.cipherSuites != null) {
853
sslSock.setEnabledCipherSuites(params.cipherSuites);
854
}
855
}
856
}
857
}
858
859
}
860
861