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