Skip to content

Commit afb5be8

Browse files
committed
AUT-2510 Disable thisUpdate in the past check for fallback OCSP service
1 parent 28224e5 commit afb5be8

File tree

4 files changed

+15
-15
lines changed

4 files changed

+15
-15
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, false);
134+
verifyOcspResponse(basicResponse, ocspService, certificateId, false, 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, boolean rejectUnknownOcspResponseStatus) throws AuthTokenException, OCSPException, CertificateException, OperatorCreationException {
147+
protected void verifyOcspResponse(BasicOCSPResp basicResponse, OcspService ocspService, CertificateID requestCertificateId, boolean rejectUnknownOcspResponseStatus, boolean allowThisUpdateInPast) 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
@@ -195,7 +195,7 @@ protected void verifyOcspResponse(BasicOCSPResp basicResponse, OcspService ocspS
195195
// be available about the status of the certificate (nextUpdate) is
196196
// greater than the current time.
197197

198-
OcspResponseValidator.validateCertificateStatusUpdateTime(certStatusResponse, allowedOcspResponseTimeSkew, maxOcspResponseThisUpdateAge, ocspService.getAccessLocation());
198+
OcspResponseValidator.validateCertificateStatusUpdateTime(certStatusResponse, allowedOcspResponseTimeSkew, maxOcspResponseThisUpdateAge, ocspService.getAccessLocation(), allowThisUpdateInPast);
199199

200200
// Now we can accept the signed response as valid and validate the certificate status.
201201
OcspResponseValidator.validateSubjectCertificateStatus(certStatusResponse, ocspService.getAccessLocation(), rejectUnknownOcspResponseStatus);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public static void validateResponseSignature(BasicOCSPResp basicResponse, X509Ce
7979
}
8080
}
8181

82-
public static void validateCertificateStatusUpdateTime(SingleResp certStatusResponse, Duration allowedTimeSkew, Duration maxThisupdateAge, URI ocspResponderUri) throws UserCertificateOCSPCheckFailedException {
82+
public static void validateCertificateStatusUpdateTime(SingleResp certStatusResponse, Duration allowedTimeSkew, Duration maxThisupdateAge, URI ocspResponderUri, boolean allowThisUpdateInPast) throws UserCertificateOCSPCheckFailedException {
8383
// From RFC 2560, https://www.ietf.org/rfc/rfc2560.txt:
8484
// 4.2.2. Notes on OCSP Responses
8585
// 4.2.2.1. Time
@@ -100,7 +100,7 @@ public static void validateCertificateStatusUpdateTime(SingleResp certStatusResp
100100
"thisUpdate '" + thisUpdate + "' is too far in the future, " +
101101
"latest allowed: '" + latestAcceptableTimeSkew + "'", ocspResponderUri);
102102
}
103-
if (thisUpdate.isBefore(minimumValidThisUpdateTime)) {
103+
if (!allowThisUpdateInPast && thisUpdate.isBefore(minimumValidThisUpdateTime)) {
104104
throw new UserCertificateOCSPCheckFailedException(ERROR_PREFIX +
105105
"thisUpdate '" + thisUpdate + "' is too old, " +
106106
"minimum time allowed: '" + minimumValidThisUpdateTime + "'", ocspResponderUri);

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,12 @@ public List<RevocationInfo> validateCertificateNotRevoked(X509Certificate subjec
108108
}
109109
final OcspService fallbackOcspService = ocspService.getFallbackService();
110110
if (fallbackOcspService == null) {
111-
return List.of(request(ocspService, subjectCertificate, issuerCertificate));
111+
return List.of(request(ocspService, subjectCertificate, issuerCertificate, false));
112112
}
113113

114114
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(ocspService.getAccessLocation().toASCIIString());
115-
CheckedFunction0<RevocationInfo> primarySupplier = () -> request(ocspService, subjectCertificate, issuerCertificate);
116-
CheckedFunction0<RevocationInfo> fallbackSupplier = () -> request(ocspService.getFallbackService(), subjectCertificate, issuerCertificate);
115+
CheckedFunction0<RevocationInfo> primarySupplier = () -> request(ocspService, subjectCertificate, issuerCertificate, false);
116+
CheckedFunction0<RevocationInfo> fallbackSupplier = () -> request(ocspService.getFallbackService(), subjectCertificate, issuerCertificate, true);
117117
Decorators.DecorateCheckedSupplier<RevocationInfo> decorateCheckedSupplier = Decorators.ofCheckedSupplier(primarySupplier);
118118
if (retryRegistry != null) {
119119
Retry retry = retryRegistry.retry(ocspService.getAccessLocation().toASCIIString());
@@ -133,7 +133,7 @@ public List<RevocationInfo> validateCertificateNotRevoked(X509Certificate subjec
133133
}));
134134
}
135135

136-
private RevocationInfo request(OcspService ocspService, X509Certificate subjectCertificate, X509Certificate issuerCertificate) throws AuthTokenException {
136+
private RevocationInfo request(OcspService ocspService, X509Certificate subjectCertificate, X509Certificate issuerCertificate, boolean allowThisUpdateInPast) throws AuthTokenException {
137137
URI ocspResponderUri = null;
138138
try {
139139
ocspResponderUri = requireNonNull(ocspService.getAccessLocation(), "ocspResponderUri");
@@ -160,7 +160,7 @@ private RevocationInfo request(OcspService ocspService, X509Certificate subjectC
160160
}
161161
LOG.debug("OCSP response received successfully");
162162

163-
verifyOcspResponse(basicResponse, ocspService, certificateId, rejectUnknownOcspResponseStatus);
163+
verifyOcspResponse(basicResponse, ocspService, certificateId, rejectUnknownOcspResponseStatus, allowThisUpdateInPast);
164164
if (ocspService.doesSupportNonce()) {
165165
checkNonce(request, basicResponse, ocspResponderUri);
166166
}

src/test/java/eu/webeid/ocsp/protocol/OcspResponseValidatorTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void whenThisAndNextUpdateWithinSkew_thenValidationSucceeds() {
5353
var nextUpdateWithinAgeLimit = Date.from(now.minus(THIS_UPDATE_AGE.minusSeconds(2)));
5454
when(mockResponse.getThisUpdate()).thenReturn(thisUpdateWithinAgeLimit);
5555
when(mockResponse.getNextUpdate()).thenReturn(nextUpdateWithinAgeLimit);
56-
assertThatCode(() -> validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL))
56+
assertThatCode(() -> validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL, false))
5757
.doesNotThrowAnyException();
5858
}
5959

@@ -67,7 +67,7 @@ void whenNextUpdateBeforeThisUpdate_thenThrows() {
6767
when(mockResponse.getNextUpdate()).thenReturn(beforeThisUpdate);
6868
assertThatExceptionOfType(UserCertificateOCSPCheckFailedException.class)
6969
.isThrownBy(() ->
70-
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL))
70+
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL, false))
7171
.withMessageStartingWith("User certificate revocation check has failed: "
7272
+ "Certificate status update time check failed: "
7373
+ "nextUpdate '" + beforeThisUpdate.toInstant() + "' is before thisUpdate '" + thisUpdateWithinAgeLimit.toInstant() + "'");
@@ -81,7 +81,7 @@ void whenThisUpdateHalfHourBeforeNow_thenThrows() {
8181
when(mockResponse.getThisUpdate()).thenReturn(halfHourBeforeNow);
8282
assertThatExceptionOfType(UserCertificateOCSPCheckFailedException.class)
8383
.isThrownBy(() ->
84-
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL))
84+
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL, false))
8585
.withMessageStartingWith("User certificate revocation check has failed: "
8686
+ "Certificate status update time check failed: "
8787
+ "thisUpdate '" + halfHourBeforeNow.toInstant() + "' is too old, minimum time allowed: ");
@@ -95,7 +95,7 @@ void whenThisUpdateHalfHourAfterNow_thenThrows() {
9595
when(mockResponse.getThisUpdate()).thenReturn(halfHourAfterNow);
9696
assertThatExceptionOfType(UserCertificateOCSPCheckFailedException.class)
9797
.isThrownBy(() ->
98-
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL))
98+
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL, false))
9999
.withMessageStartingWith("User certificate revocation check has failed: "
100100
+ "Certificate status update time check failed: "
101101
+ "thisUpdate '" + halfHourAfterNow.toInstant() + "' is too far in the future, latest allowed: ");
@@ -111,7 +111,7 @@ void whenNextUpdateHalfHourBeforeNow_thenThrows() {
111111
when(mockResponse.getNextUpdate()).thenReturn(halfHourBeforeNow);
112112
assertThatExceptionOfType(UserCertificateOCSPCheckFailedException.class)
113113
.isThrownBy(() ->
114-
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL))
114+
validateCertificateStatusUpdateTime(mockResponse, TIME_SKEW, THIS_UPDATE_AGE, OCSP_URL, false))
115115
.withMessage("User certificate revocation check has failed: "
116116
+ "Certificate status update time check failed: "
117117
+ "nextUpdate '" + halfHourBeforeNow.toInstant() + "' is in the past"

0 commit comments

Comments
 (0)