Skip to content

Commit 28224e5

Browse files
aarmammadislm
andcommitted
AUT-2473 Add rejectUnknownOcspResponseStatus configuration option
Co-authored-by: Madis Jaagup Laurson <madisjaagup.laurson@nortal.com>
1 parent 92e01f4 commit 28224e5

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

src/main/java/eu/webeid/ocsp/OcspCertificateRevocationChecker.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public List<RevocationInfo> validateCertificateNotRevoked(X509Certificate subjec
131131
}
132132
LOG.debug("OCSP response received successfully");
133133

134-
verifyOcspResponse(basicResponse, ocspService, certificateId);
134+
verifyOcspResponse(basicResponse, ocspService, certificateId, false);
135135
if (ocspService.doesSupportNonce()) {
136136
checkNonce(request, basicResponse, ocspResponderUri);
137137
}
@@ -144,7 +144,7 @@ public List<RevocationInfo> validateCertificateNotRevoked(X509Certificate subjec
144144
}
145145
}
146146

147-
protected void verifyOcspResponse(BasicOCSPResp basicResponse, OcspService ocspService, CertificateID requestCertificateId) throws AuthTokenException, OCSPException, CertificateException, OperatorCreationException {
147+
protected void verifyOcspResponse(BasicOCSPResp basicResponse, OcspService ocspService, CertificateID requestCertificateId, boolean rejectUnknownOcspResponseStatus) throws AuthTokenException, OCSPException, CertificateException, OperatorCreationException {
148148
// The verification algorithm follows RFC 2560, https://www.ietf.org/rfc/rfc2560.txt.
149149
//
150150
// 3.2. Signed Response Acceptance Requirements
@@ -198,7 +198,7 @@ protected void verifyOcspResponse(BasicOCSPResp basicResponse, OcspService ocspS
198198
OcspResponseValidator.validateCertificateStatusUpdateTime(certStatusResponse, allowedOcspResponseTimeSkew, maxOcspResponseThisUpdateAge, ocspService.getAccessLocation());
199199

200200
// Now we can accept the signed response as valid and validate the certificate status.
201-
OcspResponseValidator.validateSubjectCertificateStatus(certStatusResponse, ocspService.getAccessLocation());
201+
OcspResponseValidator.validateSubjectCertificateStatus(certStatusResponse, ocspService.getAccessLocation(), rejectUnknownOcspResponseStatus);
202202
LOG.debug("OCSP check result is GOOD");
203203
}
204204

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2020-2025 Estonian Information System Authority
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
package eu.webeid.ocsp.exceptions;
24+
25+
import eu.webeid.security.exceptions.AuthTokenException;
26+
27+
import java.net.URI;
28+
29+
import static eu.webeid.ocsp.exceptions.OcspResponderUriMessage.withResponderUri;
30+
31+
public class UserCertificateUnknownException extends AuthTokenException {
32+
33+
public UserCertificateUnknownException(String msg, URI ocspResponderUri) {
34+
super(withResponderUri("User certificate status is unknown: " + msg, ocspResponderUri));
35+
}
36+
}

src/main/java/eu/webeid/ocsp/protocol/OcspResponseValidator.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import eu.webeid.ocsp.exceptions.OCSPCertificateException;
2626
import eu.webeid.ocsp.exceptions.UserCertificateOCSPCheckFailedException;
2727
import eu.webeid.ocsp.exceptions.UserCertificateRevokedException;
28+
import eu.webeid.ocsp.exceptions.UserCertificateUnknownException;
29+
import eu.webeid.security.exceptions.AuthTokenException;
2830
import eu.webeid.security.util.DateAndTime;
2931
import org.bouncycastle.cert.X509CertificateHolder;
3032
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
@@ -118,7 +120,7 @@ public static void validateCertificateStatusUpdateTime(SingleResp certStatusResp
118120
}
119121
}
120122

121-
public static void validateSubjectCertificateStatus(SingleResp certStatusResponse, URI ocspResponderUri) throws UserCertificateRevokedException {
123+
public static void validateSubjectCertificateStatus(SingleResp certStatusResponse, URI ocspResponderUri, boolean rejectUnknownOcspResponseStatus) throws AuthTokenException {
122124
final CertificateStatus status = certStatusResponse.getCertStatus();
123125
if (status == null) {
124126
return;
@@ -128,9 +130,11 @@ public static void validateSubjectCertificateStatus(SingleResp certStatusRespons
128130
new UserCertificateRevokedException("Revocation reason: " + revokedStatus.getRevocationReason(), ocspResponderUri) :
129131
new UserCertificateRevokedException(ocspResponderUri));
130132
} else if (status instanceof UnknownStatus) {
131-
throw new UserCertificateRevokedException("Unknown status", ocspResponderUri);
133+
throw rejectUnknownOcspResponseStatus ? new UserCertificateUnknownException("Unknown status", ocspResponderUri)
134+
: new UserCertificateRevokedException("Unknown status", ocspResponderUri);
132135
} else {
133-
throw new UserCertificateRevokedException("Status is neither good, revoked nor unknown", ocspResponderUri);
136+
throw rejectUnknownOcspResponseStatus ? new UserCertificateUnknownException("Status is neither good, revoked nor unknown", ocspResponderUri)
137+
: new UserCertificateRevokedException("Status is neither good, revoked nor unknown", ocspResponderUri);
134138
}
135139
}
136140

src/main/java/eu/webeid/resilientocsp/ResilientOcspCertificateRevocationChecker.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import eu.webeid.ocsp.client.OcspClient;
2727
import eu.webeid.ocsp.exceptions.UserCertificateOCSPCheckFailedException;
2828
import eu.webeid.ocsp.exceptions.UserCertificateRevokedException;
29+
import eu.webeid.ocsp.exceptions.UserCertificateUnknownException;
2930
import eu.webeid.ocsp.protocol.OcspRequestBuilder;
3031
import eu.webeid.ocsp.service.OcspService;
3132
import eu.webeid.ocsp.service.OcspServiceProvider;
@@ -67,14 +68,17 @@ public class ResilientOcspCertificateRevocationChecker extends OcspCertificateRe
6768

6869
private final CircuitBreakerRegistry circuitBreakerRegistry;
6970
private final RetryRegistry retryRegistry;
71+
private final boolean rejectUnknownOcspResponseStatus;
7072

7173
public ResilientOcspCertificateRevocationChecker(OcspClient ocspClient,
7274
OcspServiceProvider ocspServiceProvider,
7375
CircuitBreakerConfig circuitBreakerConfig,
7476
RetryConfig retryConfig,
7577
Duration allowedOcspResponseTimeSkew,
76-
Duration maxOcspResponseThisUpdateAge) {
78+
Duration maxOcspResponseThisUpdateAge,
79+
boolean rejectUnknownOcspResponseStatus) {
7780
super(ocspClient, ocspServiceProvider, allowedOcspResponseTimeSkew, maxOcspResponseThisUpdateAge);
81+
this.rejectUnknownOcspResponseStatus = rejectUnknownOcspResponseStatus;
7882
this.circuitBreakerRegistry = CircuitBreakerRegistry.custom()
7983
.withCircuitBreakerConfig(getCircuitBreakerConfig(circuitBreakerConfig))
8084
.build();
@@ -116,7 +120,7 @@ public List<RevocationInfo> validateCertificateNotRevoked(X509Certificate subjec
116120
decorateCheckedSupplier.withRetry(retry);
117121
}
118122
decorateCheckedSupplier.withCircuitBreaker(circuitBreaker)
119-
.withFallback(List.of(UserCertificateOCSPCheckFailedException.class, CallNotPermittedException.class), e -> fallbackSupplier.apply());
123+
.withFallback(List.of(UserCertificateOCSPCheckFailedException.class, CallNotPermittedException.class, UserCertificateUnknownException.class), e -> fallbackSupplier.apply());
120124

121125
CheckedFunction0<RevocationInfo> decoratedSupplier = decorateCheckedSupplier.decorate();
122126

@@ -156,7 +160,7 @@ private RevocationInfo request(OcspService ocspService, X509Certificate subjectC
156160
}
157161
LOG.debug("OCSP response received successfully");
158162

159-
verifyOcspResponse(basicResponse, ocspService, certificateId);
163+
verifyOcspResponse(basicResponse, ocspService, certificateId, rejectUnknownOcspResponseStatus);
160164
if (ocspService.doesSupportNonce()) {
161165
checkNonce(request, basicResponse, ocspResponderUri);
162166
}

0 commit comments

Comments
 (0)