Skip to content

Commit 567f5e9

Browse files
committed
Add exception handling around interface points
DEVSIX-8400
1 parent cb25480 commit 567f5e9

30 files changed

+1509
-172
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.itextpdf.commons.utils;
2+
3+
4+
/**
5+
* Functional interface which takes 0 parameters and returns nothing and can throw a checked exception.
6+
*/
7+
@FunctionalInterface
8+
public interface ThrowingAction {
9+
/**
10+
* Execute action.
11+
*
12+
* @throws Exception any exception thrown by the encapsulated code
13+
*/
14+
void execute() throws Exception;
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.itextpdf.commons.utils;
2+
3+
/**
4+
* Functional interface which takes 0 parameters and returns T and can throw a checked exception.
5+
*/
6+
@FunctionalInterface
7+
public interface ThrowingSupplier<T> {
8+
9+
/**
10+
* Gets a result.
11+
*
12+
* @return a result
13+
* @throws Exception any exception thrown by the encapsulated code
14+
*/
15+
T get() throws Exception;
16+
}

sharpenConfiguration.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
<ignored>
55
<java>
66
<!-- commons -->
7+
<fileset reason="Delegates already exist in .net">
8+
<file path="com/itextpdf/commons/utils/Action.java"/>
9+
<file path="com/itextpdf/commons/utils/ThrowingSupplier.java"/>
10+
<file path="com/itextpdf/commons/utils/ThrowingAction.java"/>
11+
</fileset>
712
<fileset reason="Namespaces differs in Java an .NET, so it can't be ported automatically">
813
<file path="com/itextpdf/commons/actions/NamespaceConstant.java"/>
914
</fileset>

sign/src/main/java/com/itextpdf/signatures/cms/SignerInfo.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ public X509Certificate getSigningCertificate() {
210210
return signerCertificate;
211211
}
212212

213+
/**
214+
* Gets the signature data.
215+
*
216+
* @return the signature data.
217+
*/
218+
public byte[] getSignatureData() {
219+
return signatureData;
220+
}
221+
213222
/**
214223
* Sets the certificate that is used to sign a document and adds it to the signed attributes.
215224
*

sign/src/main/java/com/itextpdf/signatures/validation/v1/CRLValidator.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ This file is part of the iText (R) project.
5555
import java.util.HashMap;
5656
import java.util.Map;
5757

58+
import static com.itextpdf.signatures.validation.v1.SafeCalling.onExceptionLog;
59+
5860
/**
5961
* Class that allows you to validate a certificate against a Certificate Revocation List (CRL) Response.
6062
*/
@@ -69,6 +71,11 @@ public class CRLValidator {
6971
static final String CERTIFICATE_IS_NOT_IN_THE_CRL_SCOPE = "Certificate isn't in the current CRL scope.";
7072
static final String CERTIFICATE_REVOKED = "Certificate was revoked by {0} on {1}.";
7173
static final String CRL_ISSUER_NOT_FOUND = "Unable to validate CRL response: no issuer certificate found.";
74+
static final String CRL_ISSUER_REQUEST_FAILED =
75+
"Unable to validate CRL response: Unexpected exception occurred retrieving issuer certificate.";
76+
static final String CRL_ISSUER_CHAIN_FAILED =
77+
"Unable to validate CRL response: Unexpected exception occurred validating issuer certificate.";
78+
7279
static final String CRL_ISSUER_NO_COMMON_ROOT =
7380
"The CRL issuer does not share the root of the inspected certificate.";
7481
static final String CRL_INVALID = "CRL response is invalid.";
@@ -236,7 +243,7 @@ private static IIssuingDistributionPoint getIssuingDistributionPointExtension(X5
236243
try {
237244
issuingDistPointExtension = CertificateUtil.getExtensionValue(crl,
238245
FACTORY.createExtension().getIssuingDistributionPoint().getId());
239-
} catch (IOException e) {
246+
} catch (IOException | RuntimeException e) {
240247
// Ignore exception.
241248
}
242249
return FACTORY.createIssuingDistributionPoint(issuingDistPointExtension);
@@ -249,7 +256,7 @@ private static Date getExpiredCertsOnCRLExtensionDate(X509CRL crl) {
249256
// certificates that expired after the date specified in ExpiredCertsOnCRL or at that date.
250257
expiredCertsOnCRL = CertificateUtil.getExtensionValue(crl,
251258
FACTORY.createExtension().getExpiredCertsOnCRL().getId());
252-
} catch (IOException e) {
259+
} catch (IOException | RuntimeException e) {
253260
// Ignore exception.
254261
}
255262
if (expiredCertsOnCRL != null) {
@@ -282,12 +289,21 @@ private static int computeInterimReasonsMask(IIssuingDistributionPoint issuingDi
282289

283290
private void verifyCrlIntegrity(ValidationReport report, ValidationContext context, X509Certificate certificate,
284291
X509CRL crl, Date responseGenerationDate) {
285-
Certificate[] certs = certificateRetriever.getCrlIssuerCertificates(crl);
286-
if (certs.length == 0) {
292+
Certificate[] certs = null;
293+
try {
294+
certs = certificateRetriever.getCrlIssuerCertificates(crl);
295+
} catch (RuntimeException e) {
296+
report.addReportItem(new CertificateReportItem(certificate, CRL_CHECK, CRL_ISSUER_REQUEST_FAILED, e,
297+
ReportItemStatus.INDETERMINATE));
298+
return;
299+
}
300+
301+
if (certs == null || certs.length == 0) {
287302
report.addReportItem(new CertificateReportItem(certificate, CRL_CHECK, CRL_ISSUER_NOT_FOUND,
288303
ReportItemStatus.INDETERMINATE));
289304
return;
290305
}
306+
291307
Certificate crlIssuer = certs[0];
292308
Certificate crlIssuerRoot = getRoot(crlIssuer);
293309
Certificate subjectRoot = getRoot(certificate);
@@ -296,18 +312,14 @@ private void verifyCrlIntegrity(ValidationReport report, ValidationContext conte
296312
ReportItemStatus.INDETERMINATE));
297313
return;
298314
}
299-
try {
300-
crl.verify(crlIssuer.getPublicKey());
301-
} catch (Exception e) {
302-
report.addReportItem(new CertificateReportItem(certificate, CRL_CHECK, CRL_INVALID, e,
303-
ReportItemStatus.INDETERMINATE));
304-
return;
305-
}
306-
315+
onExceptionLog(() -> crl.verify(crlIssuer.getPublicKey()), report,
316+
e -> new CertificateReportItem(certificate, CRL_CHECK, CRL_INVALID, e, ReportItemStatus.INDETERMINATE));
307317
ValidationReport responderReport = new ValidationReport();
308-
builder.getCertificateChainValidator().validate(responderReport,
318+
onExceptionLog(() -> builder.getCertificateChainValidator().validate(responderReport,
309319
context.setCertificateSource(CertificateSource.CRL_ISSUER),
310-
(X509Certificate) crlIssuer, responseGenerationDate);
320+
(X509Certificate) crlIssuer, responseGenerationDate), report, e ->
321+
new CertificateReportItem(certificate, CRL_CHECK, CRL_ISSUER_CHAIN_FAILED, e,
322+
ReportItemStatus.INDETERMINATE));
311323
addResponderValidationReport(report, responderReport);
312324
}
313325

sign/src/main/java/com/itextpdf/signatures/validation/v1/CertificateChainValidator.java

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ This file is part of the iText (R) project.
4141
import java.util.Date;
4242
import java.util.List;
4343

44+
import static com.itextpdf.signatures.validation.v1.SafeCalling.onExceptionLog;
45+
import static com.itextpdf.signatures.validation.v1.SafeCalling.onRuntimeExceptionLog;
46+
4447
/**
4548
* Validator class, which is expected to be used for certificates chain validation.
4649
*/
@@ -60,6 +63,18 @@ public class CertificateChainValidator {
6063
static final String ISSUER_CANNOT_BE_VERIFIED =
6164
"Issuer certificate {0} for subject certificate {1} cannot be mathematically verified.";
6265

66+
static final String ISSUER_VERIFICATION_FAILED =
67+
"Unexpected exception occurred while verifying issuer certificate.";
68+
static final String ISSUER_RETRIEVAL_FAILED =
69+
"Unexpected exception occurred while retrieving certificate issuer from IssuingCertificateRetriever.";
70+
static final String TRUSTSTORE_RETRIEVAL_FAILED =
71+
"Unexpected exception occurred while retrieving trust store from IssuingCertificateRetriever.";
72+
static final String REVOCATION_VALIDATION_FAILED =
73+
"Unexpected exception occurred while validating certificate revocation.";
74+
static final String VALIDITY_PERIOD_CHECK_FAILED =
75+
"Unexpected exception occurred while validating certificate validity period.";
76+
77+
6378
private final SignatureValidationProperties properties;
6479
private final IssuingCertificateRetriever certificateRetriever;
6580
private final RevocationDataValidator revocationDataValidator;
@@ -102,15 +117,15 @@ public CertificateChainValidator addOcspClient(IOcspClient ocpsClient) {
102117
/**
103118
* Validate given certificate using provided validation date and required extensions.
104119
*
105-
* @param context the validation context in which to validate the certificate chain
106-
* @param certificate {@link X509Certificate} to be validated
107-
* @param validationDate {@link Date} against which certificate is expected to be validated. Usually signing
108-
* date
120+
* @param context the validation context in which to validate the certificate chain
121+
* @param certificate {@link X509Certificate} to be validated
122+
* @param validationDate {@link Date} against which certificate is expected to be validated. Usually signing
123+
* date
109124
*
110125
* @return {@link ValidationReport} which contains detailed validation results
111126
*/
112127
public ValidationReport validateCertificate(ValidationContext context, X509Certificate certificate,
113-
Date validationDate) {
128+
Date validationDate) {
114129
ValidationReport result = new ValidationReport();
115130
return validate(result, context, certificate, validationDate);
116131
}
@@ -119,11 +134,11 @@ public ValidationReport validateCertificate(ValidationContext context, X509Certi
119134
* Validate given certificate using provided validation date and required extensions.
120135
* Result is added into provided report.
121136
*
122-
* @param result {@link ValidationReport} which is populated with detailed validation results
123-
* @param context the context in which to perform the validation
124-
* @param certificate {@link X509Certificate} to be validated
125-
* @param validationDate {@link Date} against which certificate is expected to be validated. Usually signing
126-
* date
137+
* @param result {@link ValidationReport} which is populated with detailed validation results
138+
* @param context the context in which to perform the validation
139+
* @param certificate {@link X509Certificate} to be validated
140+
* @param validationDate {@link Date} against which certificate is expected to be validated. Usually signing
141+
* date
127142
*
128143
* @return {@link ValidationReport} which contains both provided and new validation results
129144
*/
@@ -135,9 +150,12 @@ public ValidationReport validate(ValidationReport result, ValidationContext cont
135150
if (stopValidation(result, localContext)) {
136151
return result;
137152
}
138-
if (checkIfCertIsTrusted(result, localContext, certificate)) {
153+
if (onExceptionLog(() -> checkIfCertIsTrusted(result, localContext, certificate), Boolean.FALSE, result,
154+
e -> new CertificateReportItem(certificate, CERTIFICATE_CHECK, TRUSTSTORE_RETRIEVAL_FAILED,
155+
e, ReportItemStatus.INFO))) {
139156
return result;
140157
}
158+
141159
validateRevocationData(result, localContext, certificate, validationDate);
142160
if (stopValidation(result, localContext)) {
143161
return result;
@@ -230,6 +248,9 @@ private void validateValidityPeriod(ValidationReport result, X509Certificate cer
230248
} catch (CertificateNotYetValidException e) {
231249
result.addReportItem(new CertificateReportItem(certificate, VALIDITY_CHECK, MessageFormatUtil.format(
232250
NOT_YET_VALID_CERTIFICATE, certificate.getSubjectX500Principal()), e, ReportItemStatus.INVALID));
251+
} catch (RuntimeException e) {
252+
result.addReportItem(new CertificateReportItem(certificate, VALIDITY_CHECK, MessageFormatUtil.format(
253+
VALIDITY_PERIOD_CHECK_FAILED, certificate.getSubjectX500Principal()), e, ReportItemStatus.INVALID));
233254
}
234255
}
235256

@@ -249,13 +270,23 @@ private void validateRequiredExtensions(ValidationReport result, ValidationConte
249270

250271
private void validateRevocationData(ValidationReport report, ValidationContext context, X509Certificate certificate,
251272
Date validationDate) {
252-
revocationDataValidator.validate(report, context, certificate, validationDate);
273+
onRuntimeExceptionLog(() ->
274+
revocationDataValidator.validate(report, context, certificate, validationDate), report, e ->
275+
new CertificateReportItem(certificate, CERTIFICATE_CHECK,
276+
REVOCATION_VALIDATION_FAILED, e, ReportItemStatus.INDETERMINATE));
253277
}
254278

255279
private void validateChain(ValidationReport result, ValidationContext context, X509Certificate certificate,
256280
Date validationDate) {
257-
X509Certificate issuerCertificate =
258-
(X509Certificate) certificateRetriever.retrieveIssuerCertificate(certificate);
281+
X509Certificate issuerCertificate = null;
282+
try {
283+
issuerCertificate =
284+
(X509Certificate) certificateRetriever.retrieveIssuerCertificate(certificate);
285+
} catch (RuntimeException e) {
286+
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK,
287+
ISSUER_RETRIEVAL_FAILED, e, ReportItemStatus.INDETERMINATE));
288+
return;
289+
}
259290
if (issuerCertificate == null) {
260291
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
261292
ISSUER_MISSING, certificate.getSubjectX500Principal()), ReportItemStatus.INDETERMINATE));
@@ -268,6 +299,11 @@ private void validateChain(ValidationReport result, ValidationContext context, X
268299
MessageFormatUtil.format(ISSUER_CANNOT_BE_VERIFIED, issuerCertificate.getSubjectX500Principal(),
269300
certificate.getSubjectX500Principal()), e, ReportItemStatus.INVALID));
270301
return;
302+
} catch (RuntimeException e) {
303+
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK,
304+
MessageFormatUtil.format(ISSUER_VERIFICATION_FAILED, issuerCertificate.getSubjectX500Principal(),
305+
certificate.getSubjectX500Principal()), e, ReportItemStatus.INVALID));
306+
return;
271307
}
272308
this.validate(result, context.setCertificateSource(CertificateSource.CERT_ISSUER),
273309
issuerCertificate, validationDate);

0 commit comments

Comments
 (0)