8296343: CPVE thrown on missing content-length in OCSP response
Reviewed-by: mullan, rhalade
This commit is contained in:
parent
86fed79670
commit
1a3cb8c501
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -206,20 +206,23 @@ public final class OCSP {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
// Check the response
|
||||
if (debug != null &&
|
||||
con.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
debug.println("Received HTTP error: " + con.getResponseCode()
|
||||
+ " - " + con.getResponseMessage());
|
||||
// Check the response. Non-200 codes will generate an exception
|
||||
// but path validation may complete successfully if revocation info
|
||||
// can be obtained elsewhere (e.g. CRL).
|
||||
int respCode = con.getResponseCode();
|
||||
if (respCode != HttpURLConnection.HTTP_OK) {
|
||||
String msg = "Received HTTP error: " + respCode + " - " +
|
||||
con.getResponseMessage();
|
||||
if (debug != null) {
|
||||
debug.println(msg);
|
||||
}
|
||||
throw new IOException(msg);
|
||||
}
|
||||
|
||||
int contentLength = con.getContentLength();
|
||||
if (contentLength == -1) {
|
||||
contentLength = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
return IOUtils.readExactlyNBytes(con.getInputStream(),
|
||||
contentLength);
|
||||
return (contentLength == -1) ? con.getInputStream().readAllBytes() :
|
||||
IOUtils.readExactlyNBytes(con.getInputStream(),
|
||||
contentLength);
|
||||
} finally {
|
||||
if (con != null) {
|
||||
con.disconnect();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -60,6 +60,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import sun.security.testlibrary.SimpleOCSPServer;
|
||||
import sun.security.testlibrary.SimpleOCSPServer;
|
||||
import sun.security.testlibrary.SimpleOCSPServer;
|
||||
@ -114,11 +116,10 @@ public class GetAndPostTests {
|
||||
SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)));
|
||||
ocspResponder.start();
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !ocspResponder.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!ocspResponder.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean readyStatus =
|
||||
ocspResponder.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
int ocspPort = ocspResponder.getPort();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -84,10 +84,11 @@ public class SimpleOCSPServer {
|
||||
private boolean logEnabled = false;
|
||||
private ExecutorService threadPool;
|
||||
private volatile boolean started = false;
|
||||
private volatile boolean serverReady = false;
|
||||
private CountDownLatch serverReady = new CountDownLatch(1);
|
||||
private volatile boolean receivedShutdown = false;
|
||||
private volatile boolean acceptConnections = true;
|
||||
private volatile long delayMsec = 0;
|
||||
private boolean omitContentLength = false;
|
||||
|
||||
// Fields used in the generation of responses
|
||||
private long nextUpdateInterval = -1;
|
||||
@ -216,14 +217,15 @@ public class SimpleOCSPServer {
|
||||
listenPort), 128);
|
||||
log("Listening on " + servSocket.getLocalSocketAddress());
|
||||
|
||||
// Singal ready
|
||||
serverReady = true;
|
||||
|
||||
// Update the listenPort with the new port number. If
|
||||
// the server is restarted, it will bind to the same
|
||||
// port rather than picking a new one.
|
||||
listenPort = servSocket.getLocalPort();
|
||||
|
||||
// Decrement the latch, allowing any waiting entities
|
||||
// to proceed with their requests.
|
||||
serverReady.countDown();
|
||||
|
||||
// Main dispatch loop
|
||||
while (!receivedShutdown) {
|
||||
try {
|
||||
@ -257,7 +259,7 @@ public class SimpleOCSPServer {
|
||||
// Reset state variables so the server can be restarted
|
||||
receivedShutdown = false;
|
||||
started = false;
|
||||
serverReady = false;
|
||||
serverReady = new CountDownLatch(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -497,7 +499,7 @@ public class SimpleOCSPServer {
|
||||
* server has not yet been bound to a port.
|
||||
*/
|
||||
public int getPort() {
|
||||
if (serverReady) {
|
||||
if (serverReady.getCount() == 0) {
|
||||
InetSocketAddress inetSock =
|
||||
(InetSocketAddress)servSocket.getLocalSocketAddress();
|
||||
return inetSock.getPort();
|
||||
@ -507,12 +509,21 @@ public class SimpleOCSPServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to check if OCSP server is ready to accept connection.
|
||||
* Allow SimpleOCSPServer consumers to wait for the server to be in
|
||||
* the ready state before sending requests.
|
||||
*
|
||||
* @return true if server ready, false otherwise
|
||||
* @param timeout the length of time to wait for the server to be ready
|
||||
* @param unit the unit of time applied to the timeout parameter
|
||||
*
|
||||
* @return true if the server enters the ready state, false if the
|
||||
* timeout period elapses while the caller is waiting for the server
|
||||
* to become ready.
|
||||
*
|
||||
* @throws InterruptedException if the current thread is interrupted.
|
||||
*/
|
||||
public boolean isServerReady() {
|
||||
return serverReady;
|
||||
public boolean awaitServerReady(long timeout, TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
return serverReady.await(timeout, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -531,6 +542,19 @@ public class SimpleOCSPServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting to control whether HTTP responses have the Content-Length
|
||||
* field asserted or not.
|
||||
*
|
||||
* @param isDisabled true if the Content-Length field should not be
|
||||
* asserted, false otherwise.
|
||||
*/
|
||||
public void setDisableContentLength(boolean isDisabled) {
|
||||
if (!started) {
|
||||
omitContentLength = isDisabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to stdout.
|
||||
*
|
||||
@ -776,8 +800,11 @@ public class SimpleOCSPServer {
|
||||
|
||||
sb.append("HTTP/1.0 200 OK\r\n");
|
||||
sb.append("Content-Type: application/ocsp-response\r\n");
|
||||
sb.append("Content-Length: ").append(respBytes.length);
|
||||
sb.append("\r\n\r\n");
|
||||
if (!omitContentLength) {
|
||||
sb.append("Content-Length: ").append(respBytes.length).
|
||||
append("\r\n");
|
||||
}
|
||||
sb.append("\r\n");
|
||||
|
||||
out.write(sb.toString().getBytes("UTF-8"));
|
||||
out.write(respBytes);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -562,11 +562,9 @@ public class HttpsUrlConnClient {
|
||||
rootOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean readyStatus = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
rootOcspPort = rootOcsp.getPort();
|
||||
@ -615,11 +613,9 @@ public class HttpsUrlConnClient {
|
||||
intOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
readyStatus = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
intOcspPort = intOcsp.getPort();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -503,11 +503,9 @@ public class SSLEngineWithStapling {
|
||||
rootOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean readyStatus = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
rootOcspPort = rootOcsp.getPort();
|
||||
@ -556,11 +554,9 @@ public class SSLEngineWithStapling {
|
||||
intOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
readyStatus = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
intOcspPort = intOcsp.getPort();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -432,11 +432,9 @@ public class SSLSocketWithStapling {
|
||||
rootOcsp.acceptConnections();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Root OCSP responder not ready yet");
|
||||
boolean rootOcspReady = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!rootOcspReady) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,13 +491,11 @@ public class SSLSocketWithStapling {
|
||||
intOcsp.acceptConnections();
|
||||
rootOcsp.acceptConnections();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||
|
||||
!rootOcsp.isServerReady())); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
// Wait up to 5 seconds for each server
|
||||
boolean rootOcspReady = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
boolean intOcspReady = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!rootOcspReady || !intOcspReady) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,12 +559,10 @@ public class SSLSocketWithStapling {
|
||||
rootOcsp.acceptConnections();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||
|
||||
!rootOcsp.isServerReady())); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean rootOcspReady = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
boolean intOcspReady = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!rootOcspReady || !intOcspReady) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,12 +596,10 @@ public class SSLSocketWithStapling {
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||
|
||||
!rootOcsp.isServerReady())); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean rootOcspReady = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
boolean intOcspReady = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!rootOcspReady || !intOcspReady) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
System.out.println("========================================");
|
||||
@ -654,12 +646,10 @@ public class SSLSocketWithStapling {
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && (!intOcsp.isServerReady() ||
|
||||
!rootOcsp.isServerReady())); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady() || !rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
rootOcspReady = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
intOcspReady = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!rootOcspReady || !intOcspReady) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
}
|
||||
|
||||
@ -959,11 +949,9 @@ public class SSLSocketWithStapling {
|
||||
rootOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean readyStatus = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
rootOcspPort = rootOcsp.getPort();
|
||||
@ -1012,11 +1000,9 @@ public class SSLSocketWithStapling {
|
||||
intOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
readyStatus = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
intOcspPort = intOcsp.getPort();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -696,11 +696,9 @@ public class StapleEnableProps {
|
||||
rootOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean readyStatus = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
rootOcspPort = rootOcsp.getPort();
|
||||
@ -749,11 +747,9 @@ public class StapleEnableProps {
|
||||
intOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
readyStatus = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
intOcspPort = intOcsp.getPort();
|
||||
|
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8296343
|
||||
* @summary CPVE thrown on missing content-length in OCSP response
|
||||
* @modules java.base/sun.security.x509
|
||||
* java.base/sun.security.provider.certpath
|
||||
* java.base/sun.security.util
|
||||
* @library ../../../../../java/security/testlibrary
|
||||
* @build CertificateBuilder SimpleOCSPServer
|
||||
* @run main/othervm OCSPNoContentLength
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.*;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
import sun.security.testlibrary.SimpleOCSPServer;
|
||||
import sun.security.testlibrary.CertificateBuilder;
|
||||
|
||||
public class OCSPNoContentLength {
|
||||
|
||||
static String passwd = "passphrase";
|
||||
static String ROOT_ALIAS = "root";
|
||||
static String EE_ALIAS = "endentity";
|
||||
|
||||
// Enable debugging for additional output
|
||||
static final boolean debug = false;
|
||||
|
||||
// PKI components we will need for this test
|
||||
static X509Certificate rootCert; // The root CA certificate
|
||||
static X509Certificate eeCert; // The end entity certificate
|
||||
static KeyStore rootKeystore; // Root CA Keystore
|
||||
static KeyStore eeKeystore; // End Entity Keystore
|
||||
static KeyStore trustStore; // SSL Client trust store
|
||||
static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder
|
||||
static int rootOcspPort; // Port number for root OCSP
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
try {
|
||||
createPKI();
|
||||
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
CertPath path = cf.generateCertPath(List.of(eeCert));
|
||||
log("%s", path);
|
||||
|
||||
TrustAnchor anchor = new TrustAnchor(rootCert, null);
|
||||
log("%s", anchor);
|
||||
Set<TrustAnchor> anchors = Set.of(anchor);
|
||||
|
||||
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
|
||||
PKIXParameters params = new PKIXParameters(anchors);
|
||||
PKIXRevocationChecker prc =
|
||||
(PKIXRevocationChecker)validator.getRevocationChecker();
|
||||
params.addCertPathChecker(prc);
|
||||
|
||||
validator.validate(path, params);
|
||||
} finally {
|
||||
rootOcsp.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the PKI components necessary for this test, including
|
||||
* Root CA, Intermediate CA and SSL server certificates, the keystores
|
||||
* for each entity, a client trust store, and starts the OCSP responders.
|
||||
*/
|
||||
private static void createPKI() throws Exception {
|
||||
CertificateBuilder cbld = new CertificateBuilder();
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
|
||||
keyGen.initialize(new ECGenParameterSpec("secp256r1"));
|
||||
KeyStore.Builder keyStoreBuilder =
|
||||
KeyStore.Builder.newInstance("PKCS12", null,
|
||||
new KeyStore.PasswordProtection(passwd.toCharArray()));
|
||||
|
||||
// Generate Root and EE keys
|
||||
KeyPair rootCaKP = keyGen.genKeyPair();
|
||||
log("Generated Root CA KeyPair");
|
||||
KeyPair eeKP = keyGen.genKeyPair();
|
||||
log("Generated End Entity KeyPair");
|
||||
|
||||
// Set up the Root CA Cert
|
||||
cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany");
|
||||
cbld.setPublicKey(rootCaKP.getPublic());
|
||||
cbld.setSerialNumber(new BigInteger("1"));
|
||||
// Make a 3 year validity starting from 60 days ago
|
||||
long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
|
||||
long end = start + TimeUnit.DAYS.toMillis(1085);
|
||||
cbld.setValidity(new Date(start), new Date(end));
|
||||
addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic());
|
||||
addCommonCAExts(cbld);
|
||||
// Make our Root CA Cert!
|
||||
rootCert = cbld.build(null, rootCaKP.getPrivate(),
|
||||
"SHA256withECDSA");
|
||||
log("Root CA Created:\n%s", certInfo(rootCert));
|
||||
|
||||
// Now build a keystore and add the keys and cert
|
||||
rootKeystore = keyStoreBuilder.getKeyStore();
|
||||
Certificate[] rootChain = {rootCert};
|
||||
rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(),
|
||||
passwd.toCharArray(), rootChain);
|
||||
|
||||
// Now fire up the OCSP responder
|
||||
rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null);
|
||||
rootOcsp.enableLog(debug);
|
||||
rootOcsp.setNextUpdateInterval(3600);
|
||||
rootOcsp.setDisableContentLength(true);
|
||||
rootOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
boolean readyStatus = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
rootOcspPort = rootOcsp.getPort();
|
||||
String rootRespURI = "http://localhost:" + rootOcspPort;
|
||||
log("Root OCSP Responder URI is %s", rootRespURI);
|
||||
|
||||
// Now that we have the root keystore and OCSP responder we can
|
||||
// create our end entity certificate
|
||||
cbld.reset();
|
||||
cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany");
|
||||
cbld.setPublicKey(eeKP.getPublic());
|
||||
cbld.setSerialNumber(new BigInteger("4096"));
|
||||
// Make a 1 year validity starting from 7 days ago
|
||||
start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7);
|
||||
end = start + TimeUnit.DAYS.toMillis(365);
|
||||
cbld.setValidity(new Date(start), new Date(end));
|
||||
|
||||
// Add extensions
|
||||
addCommonExts(cbld, eeKP.getPublic(), rootCaKP.getPublic());
|
||||
boolean[] kuBits = {true, false, false, false, false, false,
|
||||
false, false, false};
|
||||
cbld.addKeyUsageExt(kuBits);
|
||||
List<String> ekuOids = new ArrayList<>();
|
||||
ekuOids.add("1.3.6.1.5.5.7.3.1");
|
||||
ekuOids.add("1.3.6.1.5.5.7.3.2");
|
||||
cbld.addExtendedKeyUsageExt(ekuOids);
|
||||
cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost"));
|
||||
cbld.addAIAExt(Collections.singletonList(rootRespURI));
|
||||
// Make our End Entity Cert!
|
||||
eeCert = cbld.build(rootCert, rootCaKP.getPrivate(),
|
||||
"SHA256withECDSA");
|
||||
log("SSL Certificate Created:\n%s", certInfo(eeCert));
|
||||
|
||||
// Provide end entity cert revocation info to the Root CA
|
||||
// OCSP responder.
|
||||
Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
|
||||
new HashMap<>();
|
||||
revInfo.put(eeCert.getSerialNumber(),
|
||||
new SimpleOCSPServer.CertStatusInfo(
|
||||
SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
|
||||
rootOcsp.updateStatusDb(revInfo);
|
||||
|
||||
// Now build a keystore and add the keys, chain and root cert as a TA
|
||||
eeKeystore = keyStoreBuilder.getKeyStore();
|
||||
Certificate[] eeChain = {eeCert, rootCert};
|
||||
eeKeystore.setKeyEntry(EE_ALIAS, eeKP.getPrivate(),
|
||||
passwd.toCharArray(), eeChain);
|
||||
eeKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
|
||||
|
||||
// And finally a Trust Store for the client
|
||||
trustStore = keyStoreBuilder.getKeyStore();
|
||||
trustStore.setCertificateEntry(ROOT_ALIAS, rootCert);
|
||||
}
|
||||
|
||||
private static void addCommonExts(CertificateBuilder cbld,
|
||||
PublicKey subjKey, PublicKey authKey) throws IOException {
|
||||
cbld.addSubjectKeyIdExt(subjKey);
|
||||
cbld.addAuthorityKeyIdExt(authKey);
|
||||
}
|
||||
|
||||
private static void addCommonCAExts(CertificateBuilder cbld)
|
||||
throws IOException {
|
||||
cbld.addBasicConstraintsExt(true, true, -1);
|
||||
// Set key usage bits for digitalSignature, keyCertSign and cRLSign
|
||||
boolean[] kuBitSettings = {true, false, false, false, false, true,
|
||||
true, false, false};
|
||||
cbld.addKeyUsageExt(kuBitSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper routine that dumps only a few cert fields rather than
|
||||
* the whole toString() output.
|
||||
*
|
||||
* @param cert an X509Certificate to be displayed
|
||||
*
|
||||
* @return the String output of the issuer, subject and
|
||||
* serial number
|
||||
*/
|
||||
private static String certInfo(X509Certificate cert) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Issuer: ").append(cert.getIssuerX500Principal()).
|
||||
append("\n");
|
||||
sb.append("Subject: ").append(cert.getSubjectX500Principal()).
|
||||
append("\n");
|
||||
sb.append("Serial: ").append(cert.getSerialNumber()).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message on stdout
|
||||
*
|
||||
* @param format the format string for the log entry
|
||||
* @param args zero or more arguments corresponding to the format string
|
||||
*/
|
||||
private static void log(String format, Object ... args) {
|
||||
System.out.format(format + "\n", args);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -304,11 +304,9 @@ public class StatusResponseManagerTests {
|
||||
rootOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !rootOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!rootOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
boolean readyStatus = rootOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
rootOcspPort = rootOcsp.getPort();
|
||||
@ -357,11 +355,9 @@ public class StatusResponseManagerTests {
|
||||
intOcsp.start();
|
||||
|
||||
// Wait 5 seconds for server ready
|
||||
for (int i = 0; (i < 100 && !intOcsp.isServerReady()); i++) {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
if (!intOcsp.isServerReady()) {
|
||||
throw new RuntimeException("Server not ready yet");
|
||||
readyStatus = intOcsp.awaitServerReady(5, TimeUnit.SECONDS);
|
||||
if (!readyStatus) {
|
||||
throw new RuntimeException("Server not ready");
|
||||
}
|
||||
|
||||
intOcspPort = intOcsp.getPort();
|
||||
|
Loading…
x
Reference in New Issue
Block a user