Skip to content

Commit c13e60e

Browse files
committed
Align behaviour (but not implementation) with Tomcat Native
1 parent 1fab40c commit c13e60e

5 files changed

Lines changed: 125 additions & 1 deletion

File tree

java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,7 @@ private static void parseOCSPURLs(Asn1Parser parser, ArrayList<String> urls) {
13051305
private static int processOCSPRequest(EngineState state, URL url, MemorySegment issuer, MemorySegment x509,
13061306
MemorySegment /* X509_STORE_CTX */ x509ctx, Arena localArena) {
13071307
if (openssl_h_Compatibility.BORINGSSL || openssl_h_Compatibility.isLibreSSLPre35()) {
1308+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13081309
return V_OCSP_CERTSTATUS_UNKNOWN();
13091310
}
13101311
MemorySegment ocspRequest = MemorySegment.NULL;
@@ -1317,20 +1318,24 @@ private static int processOCSPRequest(EngineState state, URL url, MemorySegment
13171318
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
13181319
ocspRequest = OCSP_REQUEST_new();
13191320
if (MemorySegment.NULL.equals(ocspRequest)) {
1321+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13201322
return V_OCSP_CERTSTATUS_UNKNOWN();
13211323
}
13221324
id = OCSP_cert_to_id(MemorySegment.NULL, x509, issuer);
13231325
if (MemorySegment.NULL.equals(id)) {
1326+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13241327
return V_OCSP_CERTSTATUS_UNKNOWN();
13251328
}
13261329
ocspOneReq = OCSP_request_add0_id(ocspRequest, id);
13271330
if (MemorySegment.NULL.equals(ocspOneReq)) {
1331+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13281332
return V_OCSP_CERTSTATUS_UNKNOWN();
13291333
}
13301334
OCSP_request_add1_nonce(ocspRequest, (char) 0, -1);
13311335
MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL);
13321336
int requestLength = i2d_OCSP_REQUEST(ocspRequest, bufPointer);
13331337
if (requestLength <= 0) {
1338+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13341339
return V_OCSP_CERTSTATUS_UNKNOWN();
13351340
}
13361341
MemorySegment buf = bufPointer.get(ValueLayout.ADDRESS, 0);
@@ -1352,13 +1357,15 @@ private static int processOCSPRequest(EngineState state, URL url, MemorySegment
13521357
connection.getOutputStream().write(ocspRequestData);
13531358
int responseCode = connection.getResponseCode();
13541359
if (responseCode != HttpURLConnection.HTTP_OK) {
1360+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13551361
return V_OCSP_CERTSTATUS_UNKNOWN();
13561362
}
13571363
InputStream is = connection.getInputStream();
13581364
int read;
13591365
byte[] responseBuf = new byte[1024];
13601366
while ((read = is.read(responseBuf)) > 0) {
13611367
if (baos.size() > OCSP_MAX_RESPONSE_SIZE) {
1368+
X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL());
13621369
return V_OCSP_CERTSTATUS_UNKNOWN();
13631370
}
13641371
baos.write(responseBuf, 0, read);
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.tomcat.util.net.ocsp;
18+
19+
import java.util.ArrayList;
20+
import java.util.Collection;
21+
import java.util.List;
22+
23+
import javax.net.ssl.SSLHandshakeException;
24+
25+
import org.junit.AfterClass;
26+
import org.junit.Assert;
27+
import org.junit.Assume;
28+
import org.junit.BeforeClass;
29+
import org.junit.Test;
30+
import org.junit.runner.RunWith;
31+
import org.junit.runners.Parameterized;
32+
import org.junit.runners.Parameterized.Parameter;
33+
import org.junit.runners.Parameterized.Parameters;
34+
35+
import org.apache.tomcat.util.net.ocsp.TesterOcspResponder.OcspResponse;
36+
37+
@RunWith(Parameterized.class)
38+
public class TestOcspSoftFailInternalError extends OcspBaseTest {
39+
40+
private static TesterOcspResponder ocspResponder;
41+
42+
@BeforeClass
43+
public static void startOcspResponder() {
44+
ocspResponder = new TesterOcspResponder();
45+
ocspResponder.setFixedResponse(OcspResponse.INTERNAL_ERROR);
46+
try {
47+
ocspResponder.start();
48+
} catch (Exception e) {
49+
e.printStackTrace();
50+
}
51+
}
52+
53+
54+
@AfterClass
55+
public static void stopOcspResponder() {
56+
if (ocspResponder != null) {
57+
ocspResponder.stop();
58+
ocspResponder = null;
59+
}
60+
}
61+
62+
63+
@Parameters(name = "{0} with OpenSSL trust {2}: softFail {4}, clientOk {5}")
64+
public static Collection<Object[]> parameters() {
65+
List<Object[]> parameterSets = new ArrayList<>();
66+
Collection<Object[]> baseData = OcspBaseTest.parameters();
67+
68+
for (Object[] base : baseData) {
69+
for (Boolean softFail : booleans) {
70+
for (Boolean clientCertValid : booleans) {
71+
Boolean handshakeFailureExpected;
72+
73+
if (softFail.booleanValue()) {
74+
handshakeFailureExpected = Boolean.FALSE;
75+
} else {
76+
handshakeFailureExpected = Boolean.TRUE;
77+
}
78+
79+
parameterSets.add(new Object[] { base[0], base[1], base[2], base[3], softFail, clientCertValid,
80+
handshakeFailureExpected});
81+
}
82+
}
83+
}
84+
return parameterSets;
85+
}
86+
87+
@Parameter(4)
88+
public Boolean softFail;
89+
90+
@Parameter(5)
91+
public boolean clientCertValid;
92+
93+
@Parameter(6)
94+
public boolean handshakeFailureExpected;
95+
96+
@Test
97+
public void test() throws Exception {
98+
Assume.assumeNotNull(ocspResponder);
99+
try {
100+
doTest(clientCertValid, true, ClientCertificateVerification.ENABLED, false, softFail);
101+
if (handshakeFailureExpected) {
102+
Assert.fail("Handshake did not fail when expected to do so.");
103+
}
104+
} catch (SSLHandshakeException e) {
105+
if (!handshakeFailureExpected) {
106+
Assert.fail("Handshake failed when not expected to do so.");
107+
}
108+
}
109+
}
110+
}

test/org/apache/tomcat/util/net/ocsp/TesterOcspResponder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public enum OcspResponse {
106106
OK,
107107
REVOKED,
108108
UNKNOWN,
109-
TRY_LATER
109+
TRY_LATER,
110+
INTERNAL_ERROR
110111
}
111112
}

test/org/apache/tomcat/util/net/ocsp/TesterOcspResponderServlet.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ private OCSPResp processOscpRequest(byte[] derEncodeOCSPRequest) throws ServletE
247247
case UNKNOWN:
248248
responseBuilder.addResponse(certificateID, new UnknownStatus());
249249
break;
250+
case INTERNAL_ERROR:
251+
throw new ServletException("Internal error");
250252
}
251253
}
252254
}

webapps/docs/changelog.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@
134134
non-trailer fields. Control characters (excluding TAB), and characters
135135
with code points above 255 will be replaced with a space. (markt)
136136
</add>
137+
<fix>
138+
Align OpenSSl FFM behaviour with Tomcat Native for various OCSP edge
139+
cases. (markt)
140+
</fix>
137141
</changelog>
138142
</subsection>
139143
<subsection name="Cluster">

0 commit comments

Comments
 (0)