This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 4f9bc8a23b Load OCSP test status from certificate database
4f9bc8a23b is described below
commit 4f9bc8a23b5178f9599515cdd9561d492da2eb76
Author: sainadh777 <[email protected]>
AuthorDate: Tue Sep 8 08:10:08 2026 -0700
Load OCSP test status from certificate database
---
TODO.md | 10 ---
.../net/ocsp/TestTesterOcspResponderServlet.java | 45 +++++++++++++
.../util/net/ocsp/TesterOcspResponderServlet.java | 75 +++++++++++++++++-----
3 files changed, 105 insertions(+), 25 deletions(-)
diff --git a/TODO.md b/TODO.md
index 6b35e723ca..f5e14b1e59 100644
--- a/TODO.md
+++ b/TODO.md
@@ -901,16 +901,6 @@ These are bugs, correctness issues, or missing
functionality that may affect pro
---
-### 82. OCSP Test Hardcoded Serials (1 item)
-
-| # | File:Line | Description | Fix Idea | Effort | Difficulty |
-|---|-----------|-------------|----------|--------|------------|
-| 82.1 | `TesterOcspResponderServlet.java:221` | Certificate serial numbers
hardcoded instead of read from index.db | Parse the OpenSSL CA `index.txt` file
to extract serial numbers dynamically. | 1 day | Medium |
-
-**Total estimated effort: 1 day, Medium difficulty**
-
----
-
### 83. EL in JSP Escape Test (1 item)
| # | File:Line | Description | Fix Idea | Effort | Difficulty |
diff --git
a/test/org/apache/tomcat/util/net/ocsp/TestTesterOcspResponderServlet.java
b/test/org/apache/tomcat/util/net/ocsp/TestTesterOcspResponderServlet.java
new file mode 100644
index 0000000000..11c664b3d0
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/TestTesterOcspResponderServlet.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.net.ocsp;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigInteger;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import
org.apache.tomcat.util.net.ocsp.TesterOcspResponderServlet.CertificateState;
+
+public class TestTesterOcspResponderServlet {
+
+ @Test
+ public void testLoadCertificateStatuses() throws IOException {
+ String input = "V\t280811131918Z\t\t1000\tunknown\t/CN=valid\n" +
+
"R\t280811131918Z\t260812131922Z\t1001\tunknown\t/CN=revoked\n" +
+ "E\t250811131918Z\t\t1002\tunknown\t/CN=expired\n";
+
+ Map<BigInteger,CertificateState> statuses =
+ TesterOcspResponderServlet.loadCertificateStatuses(new
StringReader(input));
+
+ Assert.assertEquals(2, statuses.size());
+ Assert.assertSame(CertificateState.GOOD, statuses.get(new
BigInteger("1000", 16)));
+ Assert.assertSame(CertificateState.REVOKED, statuses.get(new
BigInteger("1001", 16)));
+ Assert.assertNull(statuses.get(new BigInteger("1002", 16)));
+ }
+}
diff --git
a/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponderServlet.java
b/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponderServlet.java
index 0b39c206cf..48e9f69361 100644
--- a/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponderServlet.java
+++ b/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponderServlet.java
@@ -16,8 +16,11 @@
*/
package org.apache.tomcat.util.net.ocsp;
+import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
+import java.io.Reader;
+import java.math.BigInteger;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
@@ -28,6 +31,8 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
@@ -82,6 +87,12 @@ public class TesterOcspResponderServlet extends HttpServlet {
private X509CertificateHolder[] responderCertificateChain;
private RespID responderID;
private ContentSigner contentSigner;
+ private Map<BigInteger,CertificateState> certificateStatuses;
+
+ enum CertificateState {
+ GOOD,
+ REVOKED
+ }
@Override
@@ -91,6 +102,12 @@ public class TesterOcspResponderServlet extends HttpServlet
{
fixedResponse = TesterOcspResponder.OcspResponse.valueOf(value);
}
+ try (FileReader reader = new FileReader(TesterSupport.DB_INDEX)) {
+ certificateStatuses = loadCertificateStatuses(reader);
+ } catch (IOException e) {
+ throw new ServletException(e);
+ }
+
// Enable the Bouncy Castle Provider
Provider provider = new BouncyCastleProvider();
Security.addProvider(provider);
@@ -159,6 +176,37 @@ public class TesterOcspResponderServlet extends
HttpServlet {
}
+ static Map<BigInteger,CertificateState> loadCertificateStatuses(Reader
input) throws IOException {
+ Map<BigInteger,CertificateState> result = new HashMap<>();
+ BufferedReader reader = new BufferedReader(input);
+ String line;
+ int lineNumber = 0;
+ while ((line = reader.readLine()) != null) {
+ lineNumber++;
+ String[] fields = line.split("\\t", -1);
+ if (fields.length < 4) {
+ throw new IOException("Invalid certificate database entry at
line " + lineNumber);
+ }
+
+ CertificateState state;
+ if ("V".equals(fields[0])) {
+ state = CertificateState.GOOD;
+ } else if ("R".equals(fields[0])) {
+ state = CertificateState.REVOKED;
+ } else {
+ continue;
+ }
+
+ try {
+ result.put(new BigInteger(fields[3], 16), state);
+ } catch (NumberFormatException e) {
+ throw new IOException("Invalid certificate serial at line " +
lineNumber, e);
+ }
+ }
+ return Map.copyOf(result);
+ }
+
+
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
@@ -217,21 +265,18 @@ public class TesterOcspResponderServlet extends
HttpServlet {
for (Req request : requests) {
CertificateID certificateID = request.getCertID();
if (fixedResponse == null) {
- switch (certificateID.getSerialNumber().intValue()) {
- // TODO read index.db rather than hard-code certificate
serial numbers
- case 4096:
- case 4098:
- case 4100:
- case 4101:
- responseBuilder.addResponse(certificateID,
CertificateStatus.GOOD);
- break;
- case 4097:
- case 4099:
- case 4102:
- responseBuilder.addResponse(certificateID, new
RevokedStatus(new Date(0)));
- break;
- default:
- responseBuilder.addResponse(certificateID, new
UnknownStatus());
+ CertificateState state =
certificateStatuses.get(certificateID.getSerialNumber());
+ if (state == null) {
+ responseBuilder.addResponse(certificateID, new
UnknownStatus());
+ } else {
+ switch (state) {
+ case GOOD:
+ responseBuilder.addResponse(certificateID,
CertificateStatus.GOOD);
+ break;
+ case REVOKED:
+ responseBuilder.addResponse(certificateID, new
RevokedStatus(new Date(0)));
+ break;
+ }
}
} else {
switch (fixedResponse) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]