Skip to content

Commit

Permalink
8296343: CPVE thrown on missing content-length in OCSP response
Browse files Browse the repository at this point in the history
Reviewed-by: mullan, rhalade
  • Loading branch information
Jamil Nimeh committed Jan 23, 2023
1 parent 86fed79 commit 1a3cb8c
Show file tree
Hide file tree
Showing 9 changed files with 362 additions and 116 deletions.
@@ -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
Expand Down Expand Up @@ -206,20 +206,23 @@ public static byte[] getOCSPBytes(List<CertId> certIds, URI responderURI,
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();
Expand Down
@@ -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
Expand Down Expand Up @@ -60,6 +60,8 @@
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;
Expand Down Expand Up @@ -114,11 +116,10 @@ public static void main(String args[]) throws Exception {
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();
Expand Down
53 changes: 40 additions & 13 deletions test/jdk/java/security/testlibrary/SimpleOCSPServer.java
@@ -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
Expand Down Expand Up @@ -84,10 +84,11 @@ public static enum CertStatus {
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;
Expand Down Expand Up @@ -216,14 +217,15 @@ public void run() {
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 {
Expand Down Expand Up @@ -257,7 +259,7 @@ public void run() {
// Reset state variables so the server can be restarted
receivedShutdown = false;
started = false;
serverReady = false;
serverReady = new CountDownLatch(1);
}
}
});
Expand Down Expand Up @@ -497,7 +499,7 @@ public void setSignatureAlgorithm(String algName)
* 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();
Expand All @@ -507,12 +509,21 @@ public int getPort() {
}

/**
* 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.
*
* @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 server ready, false otherwise
* @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);
}

/**
Expand All @@ -531,6 +542,19 @@ public void setDelay(long delayMillis) {
}
}

/**
* 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.
*
Expand Down Expand Up @@ -776,8 +800,11 @@ public void sendResponse(OutputStream out, LocalOcspResponse resp)

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);
Expand Down
18 changes: 7 additions & 11 deletions test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java
@@ -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
Expand Down Expand Up @@ -562,11 +562,9 @@ private static void createPKI() throws Exception {
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();
Expand Down Expand Up @@ -615,11 +613,9 @@ private static void createPKI() throws Exception {
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();
Expand Down
18 changes: 7 additions & 11 deletions test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java
@@ -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
Expand Down Expand Up @@ -503,11 +503,9 @@ private static void createPKI() throws Exception {
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();
Expand Down Expand Up @@ -556,11 +554,9 @@ private static void createPKI() throws Exception {
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();
Expand Down
68 changes: 27 additions & 41 deletions test/jdk/javax/net/ssl/Stapling/SSLSocketWithStapling.java
@@ -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
Expand Down Expand Up @@ -432,11 +432,9 @@ static void testMissingIntermediate(boolean isTls13) throws Exception {
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");
}
}

Expand Down Expand Up @@ -493,13 +491,11 @@ static void testHardFailFallback(boolean isTls13) throws Exception {
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");
}
}

Expand Down Expand Up @@ -563,12 +559,10 @@ static void testSoftFailFallback(boolean isTls13) throws Exception {
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");
}
}

Expand Down Expand Up @@ -602,12 +596,10 @@ static void testLatencyNoStaple(Boolean fallback, boolean isTls13)
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("========================================");
Expand Down Expand Up @@ -654,12 +646,10 @@ static void testLatencyNoStaple(Boolean fallback, boolean isTls13)
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");
}
}

Expand Down Expand Up @@ -959,11 +949,9 @@ private static void createPKI() throws Exception {
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();
Expand Down Expand Up @@ -1012,11 +1000,9 @@ private static void createPKI() throws Exception {
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();
Expand Down

1 comment on commit 1a3cb8c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.