diff --git a/itext.tests/itext.sign.tests/itext/signatures/SignMetaInfoHandlingTest.cs b/itext.tests/itext.sign.tests/itext/signatures/SignMetaInfoHandlingTest.cs index ac8252088f..94f2fc1388 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/SignMetaInfoHandlingTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/SignMetaInfoHandlingTest.cs @@ -25,6 +25,7 @@ You should have received a copy of the GNU Affero General Public License using System.IO; using iText.Commons.Actions; using iText.Commons.Actions.Confirmations; +using iText.Commons.Actions.Contexts; using iText.Commons.Actions.Sequence; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Crypto; @@ -93,7 +94,7 @@ public static void Before() { [NUnit.Framework.SetUp] public virtual void SetUpHandler() { - handler = new SignMetaInfoHandlingTest.StoreEventsHandler(); + handler = new SignMetaInfoHandlingTest.StoreEventsHandler(UnknownContext.PERMISSIVE); EventManager.GetInstance().Register(handler); } @@ -115,13 +116,9 @@ public virtual void CreateDocumentWithSignMetaInfoTest() { // No confirmed events. NUnit.Framework.Assert.AreEqual(0, confirmedEvents.Count); IList events = handler.GetEvents(); - NUnit.Framework.Assert.AreEqual(1, events.Count); - NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, ((ITextCoreProductEvent)events[0]).GetEventType - ()); + NUnit.Framework.Assert.AreEqual(0, events.Count); } - // ITextCoreProductEvent contains SignMetaInfo, but getter for the meta info is package-private. [NUnit.Framework.Test] public virtual void SignWithBaselineLTProfileEventHandlingTest() { ByteArrayOutputStream @out = new ByteArrayOutputStream(); @@ -135,7 +132,7 @@ public virtual void SignWithBaselineLTProfileEventHandlingTest() { padesSigner.SetStampingProperties(new StampingProperties().UseAppendMode()); padesSigner.SignWithBaselineLTProfile(signerProperties, signRsaChain, signRsaPrivateKey, testTsa); IList events = handler.GetEvents(); - NUnit.Framework.Assert.AreEqual(3, events.Count); + NUnit.Framework.Assert.AreEqual(2, events.Count); NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); @@ -143,12 +140,8 @@ public virtual void SignWithBaselineLTProfileEventHandlingTest() { NUnit.Framework.Assert.IsTrue(events[1] is ConfirmEvent); ConfirmEvent confirmEvent = (ConfirmEvent)events[1]; NUnit.Framework.Assert.AreEqual(iTextCoreProductEvent, confirmEvent.GetConfirmedEvent()); - NUnit.Framework.Assert.IsTrue(events[2] is ITextCoreProductEvent); - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, ((ITextCoreProductEvent)events[2]).GetEventType - ()); } - // Second ITextCoreProductEvent contains SignMetaInfo (getter is package-private), so it is not confirmed. [NUnit.Framework.Test] public virtual void SignWithBaselineLTAProfileEventHandlingTest() { ByteArrayOutputStream @out = new ByteArrayOutputStream(); @@ -161,7 +154,7 @@ public virtual void SignWithBaselineLTAProfileEventHandlingTest() { padesSigner.SetOcspClient(ocspClient).SetCrlClient(crlClient).SetTimestampSignatureName("timestampSig1"); padesSigner.SignWithBaselineLTAProfile(signerProperties, signRsaChain, signRsaPrivateKey, testTsa); IList events = handler.GetEvents(); - NUnit.Framework.Assert.AreEqual(3, events.Count); + NUnit.Framework.Assert.AreEqual(2, events.Count); NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); @@ -169,12 +162,8 @@ public virtual void SignWithBaselineLTAProfileEventHandlingTest() { NUnit.Framework.Assert.IsTrue(events[1] is ConfirmEvent); ConfirmEvent confirmEvent = (ConfirmEvent)events[1]; NUnit.Framework.Assert.AreEqual(iTextCoreProductEvent, confirmEvent.GetConfirmedEvent()); - NUnit.Framework.Assert.IsTrue(events[2] is ITextCoreProductEvent); - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, ((ITextCoreProductEvent)events[2]).GetEventType - ()); } - // Second ITextCoreProductEvent contains SignMetaInfo (getter is package-private), so it is not confirmed. [NUnit.Framework.Test] public virtual void SignCMSContainerWithBaselineLTProfileEventHandlingTest() { ByteArrayOutputStream @out = new ByteArrayOutputStream(); @@ -194,7 +183,7 @@ public virtual void SignCMSContainerWithBaselineLTProfileEventHandlingTest() { (preparedDoc.ToArray())), @out, "Signature1", container); } IList events = handler.GetEvents(); - NUnit.Framework.Assert.AreEqual(5, events.Count); + NUnit.Framework.Assert.AreEqual(4, events.Count); NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); @@ -209,12 +198,8 @@ public virtual void SignCMSContainerWithBaselineLTProfileEventHandlingTest() { NUnit.Framework.Assert.IsTrue(events[3] is ConfirmEvent); confirmEvent = (ConfirmEvent)events[3]; NUnit.Framework.Assert.AreEqual(iTextCoreProductEvent, confirmEvent.GetConfirmedEvent()); - NUnit.Framework.Assert.IsTrue(events[4] is ITextCoreProductEvent); - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, ((ITextCoreProductEvent)events[4]).GetEventType - ()); } - // Third ITextCoreProductEvent contains SignMetaInfo (getter is package-private), so it is not confirmed. [NUnit.Framework.Test] public virtual void SignCMSContainerWithBaselineLTAProfileEventHandlingTest() { ByteArrayOutputStream @out = new ByteArrayOutputStream(); @@ -234,7 +219,7 @@ public virtual void SignCMSContainerWithBaselineLTAProfileEventHandlingTest() { (preparedDoc.ToArray())), @out, "Signature1", container); } IList events = handler.GetEvents(); - NUnit.Framework.Assert.AreEqual(5, events.Count); + NUnit.Framework.Assert.AreEqual(4, events.Count); NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); @@ -249,12 +234,8 @@ public virtual void SignCMSContainerWithBaselineLTAProfileEventHandlingTest() { NUnit.Framework.Assert.IsTrue(events[3] is ConfirmEvent); confirmEvent = (ConfirmEvent)events[3]; NUnit.Framework.Assert.AreEqual(iTextCoreProductEvent, confirmEvent.GetConfirmedEvent()); - NUnit.Framework.Assert.IsTrue(events[4] is ITextCoreProductEvent); - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, ((ITextCoreProductEvent)events[4]).GetEventType - ()); } - // Third ITextCoreProductEvent contains SignMetaInfo (getter is package-private), so it is not confirmed. [NUnit.Framework.Test] public virtual void PassSignMetaInfoThroughStampingPropertiesTest() { ByteArrayOutputStream @out = new ByteArrayOutputStream(); @@ -269,16 +250,9 @@ public virtual void PassSignMetaInfoThroughStampingPropertiesTest() { (new SignMetaInfo())); padesSigner.SignWithBaselineLTProfile(signerProperties, signRsaChain, signRsaPrivateKey, testTsa); IList events = handler.GetEvents(); - NUnit.Framework.Assert.AreEqual(2, events.Count); - NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); - ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); - NUnit.Framework.Assert.IsTrue(events[1] is ITextCoreProductEvent); - NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, ((ITextCoreProductEvent)events[1]).GetEventType - ()); + NUnit.Framework.Assert.AreEqual(0, events.Count); } - // Both ITextCoreProductEvents contain SignMetaInfo, so they are both not confirmed. private class TestConfigurationEvent : AbstractITextConfigurationEvent { protected override void DoAction() { throw new InvalidOperationException(); @@ -289,17 +263,19 @@ public virtual IList GetPublicEvents(SequenceI } } - private class StoreEventsHandler : IEventHandler { + private class StoreEventsHandler : AbstractContextBasedEventHandler { private readonly IList events = new List(); + protected internal StoreEventsHandler(IContext onUnknownContext) + : base(onUnknownContext) { + } + public virtual IList GetEvents() { return events; } - public virtual void OnEvent(IEvent @event) { - if (@event is AbstractContextBasedITextEvent) { - events.Add((AbstractContextBasedITextEvent)@event); - } + protected override void OnAcceptedEvent(AbstractContextBasedITextEvent @event) { + events.Add(@event); } } } diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs index 108eb81d8c..88df2d6abe 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs @@ -92,6 +92,11 @@ public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItems return this; } + public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItems(int count, Action c) { + return this.HasLogItems(count, count, c); + } + public virtual iText.Signatures.Validation.V1.AssertValidationReport HasStatus(ValidationReport.ValidationResult expectedStatus) { chain.SetNext((new AssertValidationReport.StatusCheck(expectedStatus))); diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs index d3f719f0f7..e0decdf118 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs @@ -32,6 +32,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Testutils; using iText.Signatures.Testutils.Builder; using iText.Signatures.Validation.V1.Context; +using iText.Signatures.Validation.V1.Mocks; using iText.Signatures.Validation.V1.Report; using iText.Test; diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs index 24a7081d4d..61d93f93ee 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs @@ -28,6 +28,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Testutils; using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Extensions; +using iText.Signatures.Validation.V1.Mocks; using iText.Signatures.Validation.V1.Report; using iText.Test; diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorIntegrationTest.cs index c4be4826dd..1718b1a996 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorIntegrationTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorIntegrationTest.cs @@ -21,31 +21,65 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ using System; +using System.Collections.Generic; +using System.Linq; using iText.Bouncycastleconnector; using iText.Commons.Bouncycastle; using iText.Commons.Utils; using iText.Kernel.Pdf; using iText.Signatures; +using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; using iText.Test; namespace iText.Signatures.Validation.V1 { [NUnit.Framework.Category("BouncyCastleIntegrationTest")] + [NUnit.Framework.TestFixtureSource("CreateParametersTestFixtureData")] public class DocumentRevisionsValidatorIntegrationTest : ExtendedITextTest { private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorIntegrationTest/"; private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory(); + private ValidatorChainBuilder builder; + + private readonly ValidationContext validationContext = new ValidationContext(ValidatorContext.DOCUMENT_REVISIONS_VALIDATOR + , CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT); + + private readonly bool continueValidationAfterFail; + [NUnit.Framework.OneTimeSetUp] public static void Before() { } + [NUnit.Framework.SetUp] + public virtual void SetUp() { + builder = new ValidatorChainBuilder(); + builder.GetProperties().SetContinueAfterFailure(ValidatorContexts.All(), CertificateSources.All(), continueValidationAfterFail + ); + } + + public DocumentRevisionsValidatorIntegrationTest(Object continueValidationAfterFail) { + this.continueValidationAfterFail = (bool)continueValidationAfterFail; + } + + public DocumentRevisionsValidatorIntegrationTest(Object[] array) + : this(array[0]) { + } + + public static IEnumerable CreateParameters() { + return JavaUtil.ArraysAsList(new Object[] { false }, new Object[] { true }); + } + + public static ICollection CreateParametersTestFixtureData() { + return CreateParameters().Select(array => new NUnit.Framework.TestFixtureData(array)).ToList(); + } + [NUnit.Framework.Test] public virtual void NoSignaturesDocTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "noSignaturesDoc.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage (DocumentRevisionsValidator.DOCUMENT_WITHOUT_SIGNATURES).WithStatus(ReportItem.ReportItemStatus.INFO)) @@ -59,8 +93,8 @@ public virtual void NoSignaturesDocTest() { public virtual void MultipleRevisionsDocumentWithoutPermissionsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocumentWithoutPermissions.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); NUnit.Framework.Assert.AreEqual(AccessPermissions.ANNOTATION_MODIFICATION, validator.GetAccessPermissions( )); @@ -71,8 +105,8 @@ public virtual void MultipleRevisionsDocumentWithoutPermissionsTest() { public virtual void MultipleRevisionsDocumentWithPermissionsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocumentWithPermissions.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); NUnit.Framework.Assert.AreEqual(AccessPermissions.FORM_FIELDS_MODIFICATION, validator.GetAccessPermissions ()); @@ -83,13 +117,21 @@ public virtual void MultipleRevisionsDocumentWithPermissionsTest() { public virtual void TwoCertificationSignaturesTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "twoCertificationSignatures.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); - AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures - (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage - (DocumentRevisionsValidator.PERMISSION_REMOVED, (i) => PdfName.DocMDP).WithStatus(ReportItem.ReportItemStatus - .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator - .TOO_MANY_CERTIFICATION_SIGNATURES).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE))); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); + if (continueValidationAfterFail) { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.PERMISSION_REMOVED, (i) => PdfName.DocMDP).WithStatus(ReportItem.ReportItemStatus + .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator + .TOO_MANY_CERTIFICATION_SIGNATURES).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE))); + } + else { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.PERMISSION_REMOVED, (i) => PdfName.DocMDP).WithStatus(ReportItem.ReportItemStatus + .INVALID))); + } NUnit.Framework.Assert.AreEqual(AccessPermissions.FORM_FIELDS_MODIFICATION, validator.GetAccessPermissions ()); } @@ -98,8 +140,8 @@ public virtual void TwoCertificationSignaturesTest() { [NUnit.Framework.Test] public virtual void SignatureNotFoundTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "signatureNotFound.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage (DocumentRevisionsValidator.SIGNATURE_REVISION_NOT_FOUND).WithStatus(ReportItem.ReportItemStatus.INVALID @@ -113,8 +155,8 @@ public virtual void SignatureNotFoundTest() { public virtual void DifferentFieldLockLevelsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "differentFieldLockLevels.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage (DocumentRevisionsValidator.UNEXPECTED_FORM_FIELD, (i) => "Signature4").WithStatus(ReportItem.ReportItemStatus @@ -128,8 +170,8 @@ public virtual void DifferentFieldLockLevelsTest() { public virtual void FieldLockLevelIncreaseTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockLevelIncrease.pdf")) ) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.ACCESS_PERMISSIONS_ADDED, (i) => "Signature3"). @@ -143,8 +185,8 @@ public virtual void FieldLockLevelIncreaseTest() { public virtual void CertificationSignatureAfterApprovalTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "certificationSignatureAfterApproval.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); NUnit.Framework.Assert.AreEqual(AccessPermissions.FORM_FIELDS_MODIFICATION, validator.GetAccessPermissions ()); @@ -155,8 +197,8 @@ public virtual void CertificationSignatureAfterApprovalTest() { public virtual void FieldLockChildModificationAllowedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockChildModificationAllowed.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); } } @@ -165,8 +207,8 @@ public virtual void FieldLockChildModificationAllowedTest() { public virtual void FieldLockChildModificationNotAllowedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockChildModificationNotAllowed.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "rootField.childTextField").WithStatus(ReportItem.ReportItemStatus @@ -178,8 +220,8 @@ public virtual void FieldLockChildModificationNotAllowedTest() { public virtual void FieldLockRootModificationAllowedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockRootModificationAllowed.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); } } @@ -188,8 +230,8 @@ public virtual void FieldLockRootModificationAllowedTest() { public virtual void FieldLockRootModificationNotAllowedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockRootModificationNotAllowed.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "childTextField").WithStatus(ReportItem.ReportItemStatus @@ -201,8 +243,8 @@ public virtual void FieldLockRootModificationNotAllowedTest() { public virtual void FieldLockSequentialExcludeValuesTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockSequentialExcludeValues.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "rootField.childTextField").WithStatus(ReportItem.ReportItemStatus @@ -214,13 +256,21 @@ public virtual void FieldLockSequentialExcludeValuesTest() { public virtual void FieldLockSequentialIncludeValuesTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockSequentialIncludeValues.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); - AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures - (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage - (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "rootField.childTextField").WithStatus(ReportItem.ReportItemStatus - .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage(DocumentRevisionsValidator - .LOCKED_FIELD_MODIFIED, (i) => "childTextField").WithStatus(ReportItem.ReportItemStatus.INVALID))); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); + if (continueValidationAfterFail) { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "rootField.childTextField").WithStatus(ReportItem.ReportItemStatus + .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage(DocumentRevisionsValidator + .LOCKED_FIELD_MODIFIED, (i) => "childTextField").WithStatus(ReportItem.ReportItemStatus.INVALID))); + } + else { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "rootField.childTextField").WithStatus(ReportItem.ReportItemStatus + .INVALID))); + } } } @@ -228,13 +278,21 @@ public virtual void FieldLockSequentialIncludeValuesTest() { public virtual void FieldLockKidsRemovedAndAddedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fieldLockKidsRemovedAndAdded.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); - AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures - (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage - (DocumentRevisionsValidator.LOCKED_FIELD_KIDS_REMOVED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus - .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage(DocumentRevisionsValidator - .LOCKED_FIELD_KIDS_ADDED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus.INVALID))); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); + if (continueValidationAfterFail) { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.LOCKED_FIELD_KIDS_REMOVED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus + .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage(DocumentRevisionsValidator + .LOCKED_FIELD_KIDS_ADDED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus.INVALID))); + } + else { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.LOCKED_FIELD_KIDS_REMOVED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus + .INVALID))); + } } } @@ -242,8 +300,8 @@ public virtual void FieldLockKidsRemovedAndAddedTest() { public virtual void PageAndParentIndirectReferenceModifiedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "pageAndParentIndirectReferenceModified.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "rootField.childTextField2").WithStatus(ReportItem.ReportItemStatus @@ -255,8 +313,8 @@ public virtual void PageAndParentIndirectReferenceModifiedTest() { public virtual void LockedSignatureFieldModifiedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "lockedSignatureFieldModified.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage (DocumentRevisionsValidator.LOCKED_FIELD_MODIFIED, (i) => "Signature2").WithStatus(ReportItem.ReportItemStatus @@ -268,21 +326,29 @@ public virtual void LockedSignatureFieldModifiedTest() { public virtual void LockedFieldRemoveAddKidsEntryTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "lockedFieldRemoveAddKidsEntry.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); - AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures - (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage - (DocumentRevisionsValidator.LOCKED_FIELD_KIDS_REMOVED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus - .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage(DocumentRevisionsValidator - .LOCKED_FIELD_KIDS_ADDED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus.INVALID))); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); + if (continueValidationAfterFail) { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.LOCKED_FIELD_KIDS_REMOVED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus + .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage(DocumentRevisionsValidator + .LOCKED_FIELD_KIDS_ADDED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus.INVALID))); + } + else { + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.LOCKED_FIELD_KIDS_REMOVED, (i) => "rootField").WithStatus(ReportItem.ReportItemStatus + .INVALID))); + } } } [NUnit.Framework.Test] public virtual void RemovedLockedFieldTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removedLockedField.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.FIELD_MDP_CHECK).WithMessage (DocumentRevisionsValidator.LOCKED_FIELD_REMOVED, (i) => "textField").WithStatus(ReportItem.ReportItemStatus @@ -294,8 +360,8 @@ public virtual void RemovedLockedFieldTest() { public virtual void DanglingWidgetAnnotationTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "danglingWidgetAnnotation.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); // New widget annotation not included into the acroform was added to the 1st page. AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage @@ -309,8 +375,8 @@ public virtual void DanglingWidgetAnnotationTest() { [NUnit.Framework.Test] public virtual void RemoveAllThePageAnnotationsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeAllAnnots.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); // All the annotations on the 2nd page were removed. AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); NUnit.Framework.Assert.AreEqual(AccessPermissions.ANNOTATION_MODIFICATION, validator.GetAccessPermissions( @@ -321,8 +387,8 @@ public virtual void RemoveAllThePageAnnotationsTest() { [NUnit.Framework.Test] public virtual void RemoveAllTheFieldAnnotationsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeFieldAnnots.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); // All the annotations of the text field were removed. Note that Acrobat considers it invalid. AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)); NUnit.Framework.Assert.AreEqual(AccessPermissions.ANNOTATION_MODIFICATION, validator.GetAccessPermissions( @@ -333,8 +399,8 @@ public virtual void RemoveAllTheFieldAnnotationsTest() { [NUnit.Framework.Test] public virtual void RemoveUnnamedFieldTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeUnnamedField.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); - ValidationReport report = validator.ValidateAllDocumentRevisions(); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + ValidationReport report = validator.ValidateAllDocumentRevisions(validationContext, document); // Child field was removed, so parent field was modified. Both fields are unnamed. AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures (3).HasNumberOfLogs(3).HasLogItems(2, 2, (l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs index 141bb025dd..a274a7b46f 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs @@ -22,35 +22,70 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; +using System.Linq; using iText.Bouncycastleconnector; using iText.Commons.Bouncycastle; +using iText.Commons.Utils; using iText.Kernel.Pdf; using iText.Signatures; +using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; using iText.Test; namespace iText.Signatures.Validation.V1 { [NUnit.Framework.Category("BouncyCastleUnitTest")] + [NUnit.Framework.TestFixtureSource("CreateParametersTestFixtureData")] public class DocumentRevisionsValidatorTest : ExtendedITextTest { private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/"; private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory(); + private ValidatorChainBuilder builder; + + private readonly ValidationContext validationContext = new ValidationContext(ValidatorContext.DOCUMENT_REVISIONS_VALIDATOR + , CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT); + + private readonly bool continueValidationAfterFail; + [NUnit.Framework.OneTimeSetUp] public static void Before() { } + [NUnit.Framework.SetUp] + public virtual void SetUp() { + builder = new ValidatorChainBuilder(); + builder.GetProperties().SetContinueAfterFailure(ValidatorContexts.All(), CertificateSources.All(), continueValidationAfterFail + ); + } + + public DocumentRevisionsValidatorTest(Object continueValidationAfterFail) { + this.continueValidationAfterFail = (bool)continueValidationAfterFail; + } + + public DocumentRevisionsValidatorTest(Object[] array) + : this(array[0]) { + } + + public static IEnumerable CreateParameters() { + return JavaUtil.ArraysAsList(new Object[] { false }, new Object[] { true }); + } + + public static ICollection CreateParametersTestFixtureData() { + return CreateParameters().Select(array => new NUnit.Framework.TestFixtureData(array)).ToList(); + } + [NUnit.Framework.Test] public virtual void MultipleRevisionsDocumentLevel1Test() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Between these two revisions DSS and timestamp are added, which is allowed, // but there is unused entry in the xref table, which is an itext signature generation artifact. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID @@ -58,7 +93,8 @@ public virtual void MultipleRevisionsDocumentLevel1Test() { .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.UNEXPECTED_ENTRY_IN_XREF, (i) => 27).WithStatus (ReportItem.ReportItemStatus.INVALID))); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[1], documentRevisions[2], validationReport); + validator.ValidateRevision(documentRevisions[1], documentRevisions[2], document, validationReport, validationContext + ); // Between these two revisions only DSS is updated, which is allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID )); @@ -68,12 +104,13 @@ public virtual void MultipleRevisionsDocumentLevel1Test() { [NUnit.Framework.Test] public virtual void HugeDocumentTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "hugeDocument.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID )); } @@ -83,34 +120,39 @@ public virtual void HugeDocumentTest() { public virtual void ExtensionsModificationsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "extensionsModifications.pdf") )) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID )); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[1], documentRevisions[2], validationReport); + validator.ValidateRevision(documentRevisions[1], documentRevisions[2], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.DEVELOPER_EXTENSION_REMOVED, (i) => PdfName.ESIC ).WithStatus(ReportItem.ReportItemStatus.INVALID))); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[2], documentRevisions[3], validationReport); + validator.ValidateRevision(documentRevisions[2], documentRevisions[3], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.EXTENSION_LEVEL_DECREASED, (i) => PdfName.ESIC) .WithStatus(ReportItem.ReportItemStatus.INVALID))); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[3], documentRevisions[4], validationReport); + validator.ValidateRevision(documentRevisions[3], documentRevisions[4], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.DEVELOPER_EXTENSION_REMOVED, (i) => PdfName.ESIC ).WithStatus(ReportItem.ReportItemStatus.INVALID))); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[4], documentRevisions[5], validationReport); + validator.ValidateRevision(documentRevisions[4], documentRevisions[5], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.EXTENSIONS_REMOVED).WithStatus(ReportItem.ReportItemStatus @@ -122,12 +164,13 @@ public virtual void ExtensionsModificationsTest() { public virtual void CompletelyInvalidDocumentTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "completelyInvalidDocument.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.PAGES_MODIFIED).WithStatus(ReportItem.ReportItemStatus @@ -139,12 +182,13 @@ public virtual void CompletelyInvalidDocumentTest() { public virtual void MakeFontDirectAndIndirectTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "makeFontDirectAndIndirect.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Adobe Acrobat doesn't complain about such change. We consider this incorrect. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -153,7 +197,8 @@ public virtual void MakeFontDirectAndIndirectTest() { ).WithMessage(DocumentRevisionsValidator.NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus .INVALID))); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[1], documentRevisions[2], validationReport); + validator.ValidateRevision(documentRevisions[1], documentRevisions[2], document, validationReport, validationContext + ); // Adobe Acrobat doesn't complain about such change. We consider this incorrect. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -167,12 +212,13 @@ public virtual void MakeFontDirectAndIndirectTest() { [NUnit.Framework.Test] public virtual void RandomEntryAddedTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "randomEntryAdded.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Adobe Acrobat doesn't complain about such change. We consider this incorrect. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -185,12 +231,13 @@ public virtual void RandomEntryAddedTest() { public virtual void RandomEntryWithoutUsageTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "randomEntryWithoutUsage.pdf") )) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Adobe Acrobat doesn't complain about such change. We consider this incorrect. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -202,12 +249,13 @@ public virtual void RandomEntryWithoutUsageTest() { [NUnit.Framework.Test] public virtual void ChangeExistingFontTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "changeExistingFont.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.PAGE_MODIFIED).WithStatus(ReportItem.ReportItemStatus @@ -219,12 +267,13 @@ public virtual void ChangeExistingFontTest() { public virtual void ChangeExistingFontAndAddAsDssTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "changeExistingFontAndAddAsDss.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Adobe Acrobat doesn't complain about such change. We consider this incorrect. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -236,12 +285,13 @@ public virtual void ChangeExistingFontAndAddAsDssTest() { [NUnit.Framework.Test] public virtual void FillInFieldAtLevel1Test() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fillInField.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.NO_CHANGES_PERMITTED); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Between these two revisions forms were filled in, it is not allowed at docMDP level 1. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -255,22 +305,25 @@ public virtual void FillInFieldAtLevel1Test() { public virtual void MultipleRevisionsDocumentLevel2Test() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument2.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Between these two revisions forms were filled in, it is allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID ).HasNumberOfFailures(0).HasNumberOfLogs(0)); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[1], documentRevisions[2], validationReport); + validator.ValidateRevision(documentRevisions[1], documentRevisions[2], document, validationReport, validationContext + ); // Between these two revisions existing signature field was signed, it is allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID ).HasNumberOfFailures(0).HasNumberOfLogs(0)); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[2], documentRevisions[3], validationReport); + validator.ValidateRevision(documentRevisions[2], documentRevisions[3], document, validationReport, validationContext + ); // Between these two revisions newly added signature field was signed, it is allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID ).HasNumberOfFailures(0).HasNumberOfLogs(0)); @@ -280,13 +333,13 @@ public virtual void MultipleRevisionsDocumentLevel2Test() { [NUnit.Framework.Test] public virtual void RemovePermissionsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removePermissions.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions /Perms key was removed, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -298,13 +351,13 @@ public virtual void RemovePermissionsTest() { [NUnit.Framework.Test] public virtual void RemoveDSSTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeDSS.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions /DSS key was removed, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -316,13 +369,13 @@ public virtual void RemoveDSSTest() { [NUnit.Framework.Test] public virtual void RemoveAcroformTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeAcroform.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions /Acroform key was removed, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -334,13 +387,13 @@ public virtual void RemoveAcroformTest() { [NUnit.Framework.Test] public virtual void RemoveFieldTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeField.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions field was removed, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -352,13 +405,13 @@ public virtual void RemoveFieldTest() { [NUnit.Framework.Test] public virtual void RenameFieldTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "renameField.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions field was renamed, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -371,13 +424,13 @@ public virtual void RenameFieldTest() { [NUnit.Framework.Test] public virtual void AddTextFieldTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "addTextField.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions new field was added, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -392,13 +445,13 @@ public virtual void AddTextFieldTest() { public virtual void AddUnsignedSignatureFieldTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "addUnsignedSignatureField.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions new unsigned signature field was added, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -413,13 +466,13 @@ public virtual void AddUnsignedSignatureFieldTest() { public virtual void BrokenSignatureFieldDictionaryTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "brokenSignatureFieldDictionary.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions signature value was replaced by text, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(3).HasNumberOfLogs(3).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -434,13 +487,13 @@ public virtual void BrokenSignatureFieldDictionaryTest() { [NUnit.Framework.Test] public virtual void ModifyPageAnnotsTest() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "modifyPageAnnots.pdf"))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.FORM_FIELDS_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); validator.ValidateRevision(documentRevisions[documentRevisions.Count - 2], documentRevisions[documentRevisions - .Count - 1], validationReport); + .Count - 1], document, validationReport, validationContext); // Between these two revisions circle annotation was added to the first page, it is not allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator @@ -453,17 +506,19 @@ public virtual void ModifyPageAnnotsTest() { public virtual void MultipleRevisionsDocumentLevel3Test() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument3.pdf" ))) { - DocumentRevisionsValidator validator = new DocumentRevisionsValidator(document); + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); validator.SetAccessPermissions(AccessPermissions.ANNOTATION_MODIFICATION); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); IList documentRevisions = revisionsReader.GetAllRevisions(); ValidationReport validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[0], documentRevisions[1], validationReport); + validator.ValidateRevision(documentRevisions[0], documentRevisions[1], document, validationReport, validationContext + ); // Between these two revisions annotations were added and deleted, text field was filled-in. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID ).HasNumberOfFailures(0).HasNumberOfLogs(0)); validationReport = new ValidationReport(); - validator.ValidateRevision(documentRevisions[1], documentRevisions[2], validationReport); + validator.ValidateRevision(documentRevisions[1], documentRevisions[2], document, validationReport, validationContext + ); // Between these two revisions existed annotations were modified, it is allowed. AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID ).HasNumberOfFailures(0).HasNumberOfLogs(0)); diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs index c3326764db..f6d0c1a726 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs @@ -33,6 +33,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Testutils.Builder; using iText.Signatures.Testutils.Client; using iText.Signatures.Validation.V1.Context; +using iText.Signatures.Validation.V1.Mocks; using iText.Signatures.Validation.V1.Report; using iText.Test; diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs index 68f70ea2a6..44f37630a1 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs @@ -33,6 +33,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Testutils.Builder; using iText.Signatures.Testutils.Client; using iText.Signatures.Validation.V1.Context; +using iText.Signatures.Validation.V1.Mocks; using iText.Signatures.Validation.V1.Report; using iText.Test; @@ -307,7 +308,7 @@ public virtual void CrlEncodingErrorTest() { parameters.SetFreshness(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays (2)); RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator(); - validator.AddCrlClient(new _ICrlClient_398(crl)).Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME + validator.AddCrlClient(new _ICrlClient_401(crl)).Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME ); AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE ).HasLogItem((la) => la.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator @@ -315,8 +316,8 @@ public virtual void CrlEncodingErrorTest() { ).WithMessage(RevocationDataValidator.NO_REVOCATION_DATA))); } - private sealed class _ICrlClient_398 : ICrlClient { - public _ICrlClient_398(byte[] crl) { + private sealed class _ICrlClient_401 : ICrlClient { + public _ICrlClient_401(byte[] crl) { this.crl = crl; } diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs index b5086275ba..341b660740 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs @@ -32,6 +32,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Testutils.Builder; using iText.Signatures.Testutils.Client; using iText.Signatures.Validation.V1.Context; +using iText.Signatures.Validation.V1.Mocks; using iText.Signatures.Validation.V1.Report; using iText.Test; @@ -185,11 +186,13 @@ public virtual void ValidateMultipleSignaturesUsingLastKnownPoETest() { (trustedCerts)).WithRevocationDataValidator(new MockRevocationDataValidator()).BuildSignatureValidator (); ValidationReport report = signatureValidator.ValidateSignatures(document); - AssertValidationReport.AssertThat(report, (r) => r.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfLogs - (4).HasNumberOfFailures(0).HasLogItem((l) => l.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION + // Document contains invalid unused entry which is invalid according to DocumentRevisionsValidator. + AssertValidationReport.AssertThat(report, (r) => r.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfLogs + (5).HasNumberOfFailures(1).HasLogItem((l) => l.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION ).WithMessage(SignatureValidator.VALIDATING_SIGNATURE_NAME, (p) => "timestampSig1")).HasLogItem((l) => l.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION).WithMessage(SignatureValidator.VALIDATING_SIGNATURE_NAME - , (p) => "Signature1"))); + , (p) => "Signature1")).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage + (DocumentRevisionsValidator.UNEXPECTED_ENTRY_IN_XREF, (p) => "28"))); } } @@ -201,9 +204,9 @@ public virtual void StopAfterTimestampChainValidationFailureTest() { (), false)).WithRevocationDataValidator(new MockRevocationDataValidator()).BuildSignatureValidator(); ValidationReport report = signatureValidator.ValidateSignatures(document); AssertValidationReport.AssertThat(report, (r) => r.HasStatus(ValidationReport.ValidationResult.INDETERMINATE - ).HasNumberOfLogs(2).HasNumberOfFailures(1).HasLogItem((l) => l.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION - ).WithMessage(SignatureValidator.VALIDATING_SIGNATURE_NAME, (p) => "Signature1")).HasLogItem((l) => l. - WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE + ).HasNumberOfLogs(3).HasNumberOfFailures(2).HasLogItem((l) => l.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION + ).WithMessage(SignatureValidator.VALIDATING_SIGNATURE_NAME, (p) => "Signature1")).HasLogItems(2, (l) => + l.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE ))); } } diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs index 6ccc6c8b5a..9ba6cf2d86 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs @@ -34,6 +34,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Signatures.Testutils.Builder; using iText.Signatures.Testutils.Client; using iText.Signatures.Validation.V1.Context; +using iText.Signatures.Validation.V1.Mocks; using iText.Signatures.Validation.V1.Report; using iText.Test; @@ -58,6 +59,8 @@ public class SignatureValidatorTest : ExtendedITextTest { private MockChainValidator mockCertificateChainValidator; + private MockDocumentRevisionsValidator mockDocumentRevisionsValidator; + [NUnit.Framework.OneTimeSetUp] public static void Before() { } @@ -67,9 +70,10 @@ public virtual void SetUp() { mockCertificateChainValidator = new MockChainValidator(); parameters = new SignatureValidationProperties(); mockCertificateRetriever = new MockIssuingCertificateRetriever(); + mockDocumentRevisionsValidator = new MockDocumentRevisionsValidator(); builder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(mockCertificateRetriever).WithSignatureValidationProperties (parameters).WithCertificateChainValidator(mockCertificateChainValidator).WithRevocationDataValidator( - new MockRevocationDataValidator()); + new MockRevocationDataValidator()).WithDocumentRevisionsValidator(mockDocumentRevisionsValidator); } [NUnit.Framework.Test] @@ -287,6 +291,18 @@ public virtual void InvalidChainValidationLeadsToInvalidResultTest() { (1).HasLogItem((al) => al.WithCheckName("test").WithMessage("test"))); } + [NUnit.Framework.Test] + public virtual void InvalidRevisionsValidationLeadsToInvalidResultTest() { + mockDocumentRevisionsValidator.SetReportItemStatus(ReportItem.ReportItemStatus.INVALID); + ValidationReport report; + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDoc.pdf"))) { + SignatureValidator signatureValidator = builder.BuildSignatureValidator(); + report = signatureValidator.ValidateSignatures(document); + } + AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures + (1).HasLogItem((al) => al.WithCheckName("test").WithMessage("test"))); + } + [NUnit.Framework.Test] public virtual void ValidateMultipleSignatures() { using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "docWithMultipleSignaturesAndTimeStamp.pdf" diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/ValidationMetaInfoEventsTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/ValidationMetaInfoEventsTest.cs new file mode 100644 index 0000000000..11ab36b4e0 --- /dev/null +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/ValidationMetaInfoEventsTest.cs @@ -0,0 +1,137 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +using System; +using System.Collections.Generic; +using iText.Commons.Actions; +using iText.Commons.Actions.Confirmations; +using iText.Commons.Actions.Contexts; +using iText.Kernel.Actions.Events; +using iText.Kernel.Pdf; +using iText.Signatures.Validation.V1.Context; +using iText.Test; + +namespace iText.Signatures.Validation.V1 { + [NUnit.Framework.Category("IntegrationTest")] + public class ValidationMetaInfoEventsTest : ExtendedITextTest { + private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext + .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/ValidationMetaInfoEventsTest/"; + + private static ValidationMetaInfoEventsTest.StoreEventsHandler handler; + + private readonly ValidatorChainBuilder builder = new ValidatorChainBuilder(); + + private readonly ValidationContext validationContext = new ValidationContext(ValidatorContext.DOCUMENT_REVISIONS_VALIDATOR + , CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT); + + [NUnit.Framework.OneTimeSetUp] + public static void Before() { + } + + [NUnit.Framework.SetUp] + public virtual void SetUpHandler() { + handler = new ValidationMetaInfoEventsTest.StoreEventsHandler(UnknownContext.PERMISSIVE); + EventManager.GetInstance().Register(handler); + } + + [NUnit.Framework.TearDown] + public virtual void ResetHandler() { + EventManager.GetInstance().Unregister(handler); + } + + [NUnit.Framework.Test] + public virtual void DocumentRevisionsValidatorSingleEventTest() { + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument.pdf" + ))) { + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + validator.ValidateAllDocumentRevisions(validationContext, document); + } + IList events = handler.GetEvents(); + NUnit.Framework.Assert.AreEqual(2, events.Count); + NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); + ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; + NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); + // Only first iTextCoreProductEvent is confirmed. + NUnit.Framework.Assert.IsTrue(events[1] is ConfirmEvent); + ConfirmEvent confirmEvent = (ConfirmEvent)events[1]; + NUnit.Framework.Assert.AreEqual(iTextCoreProductEvent, confirmEvent.GetConfirmedEvent()); + } + + [NUnit.Framework.Test] + public virtual void DocumentRevisionsValidatorZeroEventsTest() { + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument.pdf" + ), new DocumentProperties().SetEventCountingMetaInfo(new ValidationMetaInfo()))) { + DocumentRevisionsValidator validator = builder.BuildDocumentRevisionsValidator(); + validator.SetEventCountingMetaInfo(new ValidationMetaInfo()); + validator.ValidateAllDocumentRevisions(validationContext, document); + } + IList events = handler.GetEvents(); + NUnit.Framework.Assert.AreEqual(0, events.Count); + } + + [NUnit.Framework.Test] + public virtual void SignatureValidatorSingleEventTest() { + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument.pdf" + ))) { + SignatureValidator validator = builder.BuildSignatureValidator(); + validator.ValidateSignatures(document); + } + IList events = handler.GetEvents(); + NUnit.Framework.Assert.AreEqual(2, events.Count); + NUnit.Framework.Assert.IsTrue(events[0] is ITextCoreProductEvent); + ITextCoreProductEvent iTextCoreProductEvent = (ITextCoreProductEvent)events[0]; + NUnit.Framework.Assert.AreEqual(ITextCoreProductEvent.PROCESS_PDF, iTextCoreProductEvent.GetEventType()); + // Only first iTextCoreProductEvent is confirmed. + NUnit.Framework.Assert.IsTrue(events[1] is ConfirmEvent); + ConfirmEvent confirmEvent = (ConfirmEvent)events[1]; + NUnit.Framework.Assert.AreEqual(iTextCoreProductEvent, confirmEvent.GetConfirmedEvent()); + } + + [NUnit.Framework.Test] + public virtual void SignatureValidatorZeroEventsTest() { + using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument.pdf" + ), new DocumentProperties().SetEventCountingMetaInfo(new ValidationMetaInfo()))) { + SignatureValidator validator = builder.BuildSignatureValidator(); + validator.SetEventCountingMetaInfo(new ValidationMetaInfo()); + validator.ValidateSignatures(document); + } + IList events = handler.GetEvents(); + NUnit.Framework.Assert.AreEqual(0, events.Count); + } + + private class StoreEventsHandler : AbstractContextBasedEventHandler { + private readonly IList events = new List(); + + protected internal StoreEventsHandler(IContext onUnknownContext) + : base(onUnknownContext) { + } + + public virtual IList GetEvents() { + return events; + } + + protected override void OnAcceptedEvent(AbstractContextBasedITextEvent @event) { + events.Add(@event); + } + } + } +} diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockChainValidator.cs similarity index 95% rename from itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs rename to itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockChainValidator.cs index 9e2d7c6efb..1c8666ba2f 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockChainValidator.cs @@ -23,17 +23,18 @@ You should have received a copy of the GNU Affero General Public License using System; using System.Collections.Generic; using iText.Commons.Bouncycastle.Cert; +using iText.Signatures.Validation.V1; using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; -namespace iText.Signatures.Validation.V1 { +namespace iText.Signatures.Validation.V1.Mocks { public class MockChainValidator : CertificateChainValidator { public IList verificationCalls = new List(); private Action onCallHandler; - internal MockChainValidator() + public MockChainValidator() : base(new ValidatorChainBuilder()) { } diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockCrlValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockCrlValidator.cs similarity index 95% rename from itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockCrlValidator.cs rename to itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockCrlValidator.cs index 595bccf057..0c5fca5a65 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockCrlValidator.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockCrlValidator.cs @@ -24,10 +24,11 @@ You should have received a copy of the GNU Affero General Public License using System.Collections.Generic; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Utils; +using iText.Signatures.Validation.V1; using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; -namespace iText.Signatures.Validation.V1 { +namespace iText.Signatures.Validation.V1.Mocks { public class MockCrlValidator : CRLValidator { public readonly IList calls = new List (); @@ -36,7 +37,7 @@ public class MockCrlValidator : CRLValidator { /// /// Creates new - /// + /// /// instance. /// public MockCrlValidator() diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockDocumentRevisionsValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockDocumentRevisionsValidator.cs new file mode 100644 index 0000000000..b623da3bcc --- /dev/null +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockDocumentRevisionsValidator.cs @@ -0,0 +1,49 @@ +/* +This file is part of the iText (R) project. +Copyright (c) 1998-2024 Apryse Group NV +Authors: Apryse Software. + +This program is offered under a commercial and under the AGPL license. +For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below. + +AGPL licensing: +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +using iText.Kernel.Pdf; +using iText.Signatures.Validation.V1; +using iText.Signatures.Validation.V1.Context; +using iText.Signatures.Validation.V1.Report; + +namespace iText.Signatures.Validation.V1.Mocks { + public class MockDocumentRevisionsValidator : DocumentRevisionsValidator { + private ReportItem.ReportItemStatus reportItemStatus = ReportItem.ReportItemStatus.INFO; + + public MockDocumentRevisionsValidator() + : base(new ValidatorChainBuilder()) { + } + + public override ValidationReport ValidateAllDocumentRevisions(ValidationContext context, PdfDocument document + ) { + ValidationReport report = new ValidationReport(); + if (reportItemStatus != ReportItem.ReportItemStatus.INFO) { + report.AddReportItem(new ReportItem("test", "test", reportItemStatus)); + } + return report; + } + + public virtual void SetReportItemStatus(ReportItem.ReportItemStatus reportItemStatus) { + this.reportItemStatus = reportItemStatus; + } + } +} diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockIssuingCertificateRetriever.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockIssuingCertificateRetriever.cs similarity index 99% rename from itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockIssuingCertificateRetriever.cs rename to itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockIssuingCertificateRetriever.cs index 9e3159f55d..2e8e4977f5 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockIssuingCertificateRetriever.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockIssuingCertificateRetriever.cs @@ -25,7 +25,7 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Cert; using iText.Signatures; -namespace iText.Signatures.Validation.V1 { +namespace iText.Signatures.Validation.V1.Mocks { public class MockIssuingCertificateRetriever : IssuingCertificateRetriever { public IList retrieveMissingCertificatesCalls = new List(); diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockOCSPValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockOCSPValidator.cs similarity index 95% rename from itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockOCSPValidator.cs rename to itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockOCSPValidator.cs index 854ea95230..b28273e727 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockOCSPValidator.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockOCSPValidator.cs @@ -26,10 +26,11 @@ You should have received a copy of the GNU Affero General Public License using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Cert.Ocsp; using iText.Commons.Utils; +using iText.Signatures.Validation.V1; using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; -namespace iText.Signatures.Validation.V1 { +namespace iText.Signatures.Validation.V1.Mocks { public class MockOCSPValidator : OCSPValidator { public readonly IList calls = new List(); @@ -38,7 +39,7 @@ public class MockOCSPValidator : OCSPValidator { /// /// Creates new - /// + /// /// instance. /// public MockOCSPValidator() diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockRevocationDataValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockRevocationDataValidator.cs similarity index 93% rename from itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockRevocationDataValidator.cs rename to itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockRevocationDataValidator.cs index c1fc20578f..d748596b96 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockRevocationDataValidator.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockRevocationDataValidator.cs @@ -24,10 +24,11 @@ You should have received a copy of the GNU Affero General Public License using System.Collections.Generic; using iText.Commons.Bouncycastle.Cert; using iText.Signatures; +using iText.Signatures.Validation.V1; using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; -namespace iText.Signatures.Validation.V1 { +namespace iText.Signatures.Validation.V1.Mocks { public class MockRevocationDataValidator : RevocationDataValidator { public IList crlClientsAdded = new List(); @@ -38,10 +39,10 @@ public class MockRevocationDataValidator : RevocationDataValidator { /// /// Creates new - /// + /// /// instance to validate certificate revocation data. /// - internal MockRevocationDataValidator() + public MockRevocationDataValidator() : base(new ValidatorChainBuilder()) { } diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockSignatureValidationProperties.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockSignatureValidationProperties.cs similarity index 89% rename from itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockSignatureValidationProperties.cs rename to itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockSignatureValidationProperties.cs index 5ef9d6ba52..6b2a18223c 100644 --- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockSignatureValidationProperties.cs +++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/mocks/MockSignatureValidationProperties.cs @@ -22,10 +22,11 @@ You should have received a copy of the GNU Affero General Public License */ using System; using System.Collections.Generic; +using iText.Signatures.Validation.V1; using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Extensions; -namespace iText.Signatures.Validation.V1 { +namespace iText.Signatures.Validation.V1.Mocks { /// This mock class wrapper a real SignatureValidationProperties instance. /// /// This mock class wrapper a real SignatureValidationProperties instance. @@ -100,25 +101,25 @@ public override SignatureValidationProperties.OnlineFetching GetRevocationOnline return wrappedProperties.GetRevocationOnlineFetching(validationContext); } - public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddContinueAfterFailureResponse + public virtual iText.Signatures.Validation.V1.Mocks.MockSignatureValidationProperties AddContinueAfterFailureResponse (bool value) { continueAfterFailureResponses.Add(value); return this; } - public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddFreshnessResponse(TimeSpan - freshness) { + public virtual iText.Signatures.Validation.V1.Mocks.MockSignatureValidationProperties AddFreshnessResponse + (TimeSpan freshness) { freshnessResponses.Add(freshness); return this; } - public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddRequiredExtensionsResponses + public virtual iText.Signatures.Validation.V1.Mocks.MockSignatureValidationProperties AddRequiredExtensionsResponses (IList requiredExtensions) { requiredExtensionsResponses.Add(requiredExtensions); return this; } - public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddRevocationOnlineFetchingResponse + public virtual iText.Signatures.Validation.V1.Mocks.MockSignatureValidationProperties AddRevocationOnlineFetchingResponse (SignatureValidationProperties.OnlineFetching value) { revocationOnlineFetchingResponses.Add(value); return this; diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/ValidationMetaInfoEventsTest/multipleRevisionsDocument.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/ValidationMetaInfoEventsTest/multipleRevisionsDocument.pdf new file mode 100644 index 0000000000..643f720011 Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/ValidationMetaInfoEventsTest/multipleRevisionsDocument.pdf differ diff --git a/itext/itext.sign/itext/signatures/validation/v1/CRLValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/CRLValidator.cs index d416c40f5e..ee0e164899 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/CRLValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/CRLValidator.cs @@ -92,7 +92,7 @@ public class CRLValidator { /// See /// /// - internal CRLValidator(ValidatorChainBuilder builder) { + protected internal CRLValidator(ValidatorChainBuilder builder) { this.certificateRetriever = builder.GetCertificateRetriever(); this.properties = builder.GetProperties(); this.builder = builder; diff --git a/itext/itext.sign/itext/signatures/validation/v1/CertificateChainValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/CertificateChainValidator.cs index 2a73e30223..3672a05c82 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/CertificateChainValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/CertificateChainValidator.cs @@ -68,7 +68,7 @@ public class CertificateChainValidator { /// See /// /// - internal CertificateChainValidator(ValidatorChainBuilder builder) { + protected internal CertificateChainValidator(ValidatorChainBuilder builder) { this.certificateRetriever = builder.GetCertificateRetriever(); this.properties = builder.GetProperties(); this.revocationDataValidator = builder.GetRevocationDataValidator(); @@ -244,8 +244,8 @@ private bool CheckIfCertIsTrusted(ValidationReport result, ValidationContext con } private bool StopValidation(ValidationReport result, ValidationContext context) { - return !properties.GetContinueAfterFailure(context) && result.GetValidationResult() != ValidationReport.ValidationResult - .VALID; + return !properties.GetContinueAfterFailure(context) && result.GetValidationResult() == ValidationReport.ValidationResult + .INVALID; } private void ValidateValidityPeriod(ValidationReport result, IX509Certificate certificate, DateTime validationDate diff --git a/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs index 9f2a9cad9f..4f4ef1a607 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs @@ -31,11 +31,13 @@ You should have received a copy of the GNU Affero General Public License using iText.IO.Source; using iText.Kernel.Pdf; using iText.Signatures; +using iText.Signatures.Validation.V1.Context; using iText.Signatures.Validation.V1.Report; namespace iText.Signatures.Validation.V1 { - /// Validator, which is responsible for document revisions validation according to doc-MDP rules. - internal class DocumentRevisionsValidator { + /// Validator, which is responsible for document revisions validation according to doc-MDP and field-MDP rules. + /// + public class DocumentRevisionsValidator { internal const String DOC_MDP_CHECK = "DocMDP check."; internal const String FIELD_MDP_CHECK = "FieldMDP check."; @@ -116,30 +118,38 @@ internal class DocumentRevisionsValidator { internal const String UNRECOGNIZED_ACTION = "Signature field lock dictionary contains unrecognized " + "\"Action\" value \"{0}\". \"All\" will be used instead."; + private readonly ICollection lockedFields = new HashSet(); + + private readonly SignatureValidationProperties properties; + private IMetaInfo metaInfo = new ValidationMetaInfo(); private AccessPermissions accessPermissions = AccessPermissions.ANNOTATION_MODIFICATION; private AccessPermissions requestedAccessPermissions = AccessPermissions.UNSPECIFIED; - private readonly ICollection lockedFields = new HashSet(); - - private readonly PdfDocument document; - private ICollection checkedAnnots; private ICollection newlyAddedFields; - internal DocumentRevisionsValidator(PdfDocument document) { - this.document = document; + /// + /// Creates new instance of + /// . + /// + /// + /// See + /// + /// + protected internal DocumentRevisionsValidator(ValidatorChainBuilder chainBuilder) { + this.properties = chainBuilder.GetProperties(); } /// /// Sets the /// - /// that will be used during + /// that will be used during new /// - /// creation. + /// creations. /// /// meta info to set /// @@ -174,17 +184,19 @@ public virtual iText.Signatures.Validation.V1.DocumentRevisionsValidator SetAcce return this; } - internal virtual AccessPermissions GetAccessPermissions() { - return requestedAccessPermissions == AccessPermissions.UNSPECIFIED ? accessPermissions : requestedAccessPermissions; - } - /// Validate all document revisions according to docMDP and fieldMDP transform methods. + /// the validation context in which to validate document revisions + /// the document to be validated /// /// /// /// which contains detailed validation results. /// - public virtual ValidationReport ValidateAllDocumentRevisions() { + public virtual ValidationReport ValidateAllDocumentRevisions(ValidationContext context, PdfDocument document + ) { + ResetClassFields(); + ValidationContext localContext = context.SetValidatorContext(ValidatorContext.DOCUMENT_REVISIONS_VALIDATOR + ); ValidationReport report = new ValidationReport(); PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader()); revisionsReader.SetEventCountingMetaInfo(metaInfo); @@ -207,8 +219,8 @@ public virtual ValidationReport ValidateAllDocumentRevisions() { bool signatureFound = false; bool certificationSignatureFound = false; PdfSignature currentSignature = signatureUtil.GetSignature(signatures[0]); - for (int i = 0; i < documentRevisions.Count - 1; i++) { - if (currentSignature != null && RevisionContainsSignature(documentRevisions[i], signatures[0])) { + for (int i = 0; i < documentRevisions.Count; i++) { + if (currentSignature != null && RevisionContainsSignature(documentRevisions[i], signatures[0], document)) { signatureFound = true; if (IsCertificationSignature(currentSignature)) { if (certificationSignatureFound) { @@ -223,7 +235,7 @@ public virtual ValidationReport ValidateAllDocumentRevisions() { UpdateApprovalSignatureAccessPermissions(signatureUtil.GetSignatureFormFieldDictionary(signatures[0]), report ); UpdateApprovalSignatureFieldLock(documentRevisions[i], signatureUtil.GetSignatureFormFieldDictionary(signatures - [0]), report); + [0]), document, report); signatures.JRemoveAt(0); if (signatures.IsEmpty()) { currentSignature = null; @@ -232,8 +244,11 @@ public virtual ValidationReport ValidateAllDocumentRevisions() { currentSignature = signatureUtil.GetSignature(signatures[0]); } } - if (signatureFound) { - ValidateRevision(documentRevisions[i], documentRevisions[i + 1], report); + if (signatureFound && i < documentRevisions.Count - 1) { + ValidateRevision(documentRevisions[i], documentRevisions[i + 1], document, report, localContext); + } + if (StopValidation(report, localContext)) { + break; } } if (!signatureFound) { @@ -243,13 +258,8 @@ public virtual ValidationReport ValidateAllDocumentRevisions() { return report; } - // - // - // Revisions validation util section: - // - // internal virtual void ValidateRevision(DocumentRevision previousRevision, DocumentRevision currentRevision - , ValidationReport validationReport) { + , PdfDocument document, ValidationReport validationReport, ValidationContext context) { try { using (Stream previousInputStream = CreateInputStreamFromRevision(document, previousRevision)) { using (PdfReader previousReader = new PdfReader(previousInputStream).SetStrictnessLevel(PdfReader.StrictnessLevel @@ -262,7 +272,7 @@ internal virtual void ValidateRevision(DocumentRevision previousRevision, Docume using (PdfDocument documentWithRevision = new PdfDocument(currentReader, new DocumentProperties().SetEventCountingMetaInfo (metaInfo))) { ICollection indirectReferences = currentRevision.GetModifiedObjects(); - if (!CompareCatalogs(documentWithoutRevision, documentWithRevision, validationReport)) { + if (!CompareCatalogs(documentWithoutRevision, documentWithRevision, validationReport, context)) { return; } ICollection currentAllowedReferences = CreateAllowedReferences(documentWithRevision); @@ -307,6 +317,15 @@ internal virtual void ValidateRevision(DocumentRevision previousRevision, Docume } } + // + // + // Revisions validation util section: + // + // + internal virtual AccessPermissions GetAccessPermissions() { + return requestedAccessPermissions == AccessPermissions.UNSPECIFIED ? accessPermissions : requestedAccessPermissions; + } + private static Stream CreateInputStreamFromRevision(PdfDocument originalDocument, DocumentRevision revision ) { RandomAccessFileOrArray raf = originalDocument.GetReader().GetSafeFile(); @@ -315,6 +334,11 @@ private static Stream CreateInputStreamFromRevision(PdfDocument originalDocument return new RASInputStream(source); } + private bool StopValidation(ValidationReport result, ValidationContext validationContext) { + return !properties.GetContinueAfterFailure(validationContext) && result.GetValidationResult() == ValidationReport.ValidationResult + .INVALID; + } + private void UpdateApprovalSignatureAccessPermissions(PdfDictionary signatureField, ValidationReport report ) { PdfDictionary fieldLock = signatureField.GetAsDictionary(PdfName.Lock); @@ -354,8 +378,8 @@ private void UpdateApprovalSignatureAccessPermissions(PdfDictionary signatureFie } } - private void UpdateApprovalSignatureFieldLock(DocumentRevision revision, PdfDictionary signatureField, ValidationReport - report) { + private void UpdateApprovalSignatureFieldLock(DocumentRevision revision, PdfDictionary signatureField, PdfDocument + document, ValidationReport report) { PdfDictionary fieldLock = signatureField.GetAsDictionary(PdfName.Lock); if (fieldLock == null || fieldLock.GetAsName(PdfName.Action) == null) { return; @@ -377,22 +401,22 @@ private void UpdateApprovalSignatureFieldLock(DocumentRevision revision, PdfDict IList excludedFields = JavaCollectionsUtil.EmptyList(); if (fields != null) { excludedFields = fields.SubList(0, fields.Size()).Select((field) => field is PdfString ? ((PdfString)field - ).ToUnicodeString() : "").ToList(); + ).ToUnicodeString() : null).ToList(); } - LockAllFormFields(revision, excludedFields, report); + LockAllFormFields(revision, excludedFields, document, report); } else { if (!PdfName.All.Equals(action)) { report.AddReportItem(new ReportItem(FIELD_MDP_CHECK, MessageFormatUtil.Format(UNRECOGNIZED_ACTION, action. GetValue()), ReportItem.ReportItemStatus.INVALID)); } - LockAllFormFields(revision, JavaCollectionsUtil.EmptyList(), report); + LockAllFormFields(revision, JavaCollectionsUtil.EmptyList(), document, report); } } } - private void LockAllFormFields(DocumentRevision revision, IList excludedFields, ValidationReport report - ) { + private void LockAllFormFields(DocumentRevision revision, IList excludedFields, PdfDocument document + , ValidationReport report) { try { using (Stream inputStream = CreateInputStreamFromRevision(document, revision)) { using (PdfReader reader = new PdfReader(inputStream)) { @@ -476,7 +500,7 @@ private bool IsCertificationSignature(PdfSignature signature) { return false; } - private bool RevisionContainsSignature(DocumentRevision revision, String signature) { + private bool RevisionContainsSignature(DocumentRevision revision, String signature, PdfDocument document) { try { using (Stream inputStream = CreateInputStreamFromRevision(document, revision)) { using (PdfReader reader = new PdfReader(inputStream)) { @@ -493,13 +517,18 @@ private bool RevisionContainsSignature(DocumentRevision revision, String signatu return false; } + private void ResetClassFields() { + lockedFields.Clear(); + accessPermissions = AccessPermissions.ANNOTATION_MODIFICATION; + } + // // // Compare catalogs section: // // private bool CompareCatalogs(PdfDocument documentWithoutRevision, PdfDocument documentWithRevision, ValidationReport - report) { + report, ValidationContext context) { PdfDictionary previousCatalog = documentWithoutRevision.GetCatalog().GetPdfObject(); PdfDictionary currentCatalog = documentWithRevision.GetCatalog().GetPdfObject(); PdfDictionary previousCatalogCopy = CopyCatalogEntriesToCompare(previousCatalog); @@ -509,12 +538,32 @@ private bool CompareCatalogs(PdfDocument documentWithoutRevision, PdfDocument do .INVALID)); return false; } - return CompareExtensions(previousCatalog.Get(PdfName.Extensions), currentCatalog.Get(PdfName.Extensions), - report) && ComparePermissions(previousCatalog.Get(PdfName.Perms), currentCatalog.Get(PdfName.Perms), report - ) && CompareDss(previousCatalog.Get(PdfName.DSS), currentCatalog.Get(PdfName.DSS), report) && CompareAcroFormsWithFieldMDP - (documentWithoutRevision, documentWithRevision, report) && CompareAcroForms(previousCatalog.GetAsDictionary - (PdfName.AcroForm), currentCatalog.GetAsDictionary(PdfName.AcroForm), report) && ComparePages(previousCatalog - .GetAsDictionary(PdfName.Pages), currentCatalog.GetAsDictionary(PdfName.Pages), report); + bool result = CompareExtensions(previousCatalog.Get(PdfName.Extensions), currentCatalog.Get(PdfName.Extensions + ), report); + if (StopValidation(report, context)) { + return result; + } + result = result && ComparePermissions(previousCatalog.Get(PdfName.Perms), currentCatalog.Get(PdfName.Perms + ), report); + if (StopValidation(report, context)) { + return result; + } + result = result && CompareDss(previousCatalog.Get(PdfName.DSS), currentCatalog.Get(PdfName.DSS), report); + if (StopValidation(report, context)) { + return result; + } + result = result && CompareAcroFormsWithFieldMDP(documentWithoutRevision, documentWithRevision, report); + if (StopValidation(report, context)) { + return result; + } + result = result && CompareAcroForms(previousCatalog.GetAsDictionary(PdfName.AcroForm), currentCatalog.GetAsDictionary + (PdfName.AcroForm), report); + if (StopValidation(report, context)) { + return result; + } + result = result && ComparePages(previousCatalog.GetAsDictionary(PdfName.Pages), currentCatalog.GetAsDictionary + (PdfName.Pages), report); + return result; } // Compare catalogs nested methods section: @@ -534,12 +583,13 @@ private bool CompareExtensions(PdfObject previousExtensions, PdfObject currentEx } PdfDictionary previousExtensionsDictionary = (PdfDictionary)previousExtensions; PdfDictionary currentExtensionsDictionary = (PdfDictionary)currentExtensions; + bool result = true; foreach (KeyValuePair previousExtension in previousExtensionsDictionary.EntrySet()) { PdfDictionary currentExtension = currentExtensionsDictionary.GetAsDictionary(previousExtension.Key); if (currentExtension == null) { report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DEVELOPER_EXTENSION_REMOVED, previousExtension .Key), ReportItem.ReportItemStatus.INVALID)); - return false; + result = false; } else { PdfDictionary currentExtensionCopy = new PdfDictionary(currentExtension); @@ -550,7 +600,8 @@ private bool CompareExtensions(PdfObject previousExtensions, PdfObject currentEx if (!ComparePdfObjects(previousExtensionCopy, currentExtensionCopy)) { report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DEVELOPER_EXTENSION_REMOVED, previousExtension .Key), ReportItem.ReportItemStatus.INVALID)); - return false; + result = false; + continue; } PdfNumber previousExtensionLevel = ((PdfDictionary)previousExtension.Value).GetAsNumber(PdfName.ExtensionLevel ); @@ -559,12 +610,12 @@ private bool CompareExtensions(PdfObject previousExtensions, PdfObject currentEx if (currentExtensionLevel == null || previousExtensionLevel.IntValue() > currentExtensionLevel.IntValue()) { report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(EXTENSION_LEVEL_DECREASED, previousExtension .Key), ReportItem.ReportItemStatus.INVALID)); - return false; + result = false; } } } } - return true; + return result; } private bool ComparePermissions(PdfObject previousPerms, PdfObject currentPerms, ValidationReport report) { @@ -582,23 +633,24 @@ private bool ComparePermissions(PdfObject previousPerms, PdfObject currentPerms, } PdfDictionary previousPermsDictionary = (PdfDictionary)previousPerms; PdfDictionary currentPermsDictionary = (PdfDictionary)currentPerms; + bool result = true; foreach (KeyValuePair previousPermission in previousPermsDictionary.EntrySet()) { PdfDictionary currentPermission = currentPermsDictionary.GetAsDictionary(previousPermission.Key); if (currentPermission == null) { report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(PERMISSION_REMOVED, previousPermission .Key), ReportItem.ReportItemStatus.INVALID)); - return false; + result = false; } else { // Perms dictionary is the signature dictionary. if (!CompareSignatureDictionaries(previousPermission.Value, currentPermission, report)) { report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(PERMISSION_REMOVED, previousPermission .Key), ReportItem.ReportItemStatus.INVALID)); - return false; + result = false; } } } - return true; + return result; } private bool CompareDss(PdfObject previousDss, PdfObject currentDss, ValidationReport report) { @@ -624,6 +676,7 @@ private bool CompareAcroFormsWithFieldMDP(PdfDocument documentWithoutRevision, P // In this case FieldMDP makes no sense, because related changes are forbidden anyway. return true; } + bool result = true; foreach (KeyValuePair previousField in previousAcroForm.GetAllFormFields()) { if (lockedFields.Contains(previousField.Key)) { // For locked form fields nothing can change, @@ -632,15 +685,16 @@ private bool CompareAcroFormsWithFieldMDP(PdfDocument documentWithoutRevision, P if (currentFormField == null) { report.AddReportItem(new ReportItem(FIELD_MDP_CHECK, MessageFormatUtil.Format(LOCKED_FIELD_REMOVED, previousField .Key), ReportItem.ReportItemStatus.INVALID)); - return false; + result = false; + continue; } if (!CompareFormFieldWithFieldMDP(previousField.Value.GetPdfObject(), currentFormField.GetPdfObject(), previousField .Key, report)) { - return false; + result = false; } } } - return true; + return result; } private bool CompareFormFieldWithFieldMDP(PdfDictionary previousField, PdfDictionary currentField, String diff --git a/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs index 8ece9e99b9..70b463fe04 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs @@ -75,7 +75,7 @@ public class OCSPValidator { /// See /// /// - internal OCSPValidator(ValidatorChainBuilder builder) { + protected internal OCSPValidator(ValidatorChainBuilder builder) { this.certificateRetriever = builder.GetCertificateRetriever(); this.properties = builder.GetProperties(); this.builder = builder; diff --git a/itext/itext.sign/itext/signatures/validation/v1/RevocationDataValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/RevocationDataValidator.cs index 6d40b4f3ae..f1978f7cd9 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/RevocationDataValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/RevocationDataValidator.cs @@ -75,7 +75,7 @@ public class RevocationDataValidator { /// See /// /// - internal RevocationDataValidator(ValidatorChainBuilder builder) { + protected internal RevocationDataValidator(ValidatorChainBuilder builder) { this.certificateRetriever = builder.GetCertificateRetriever(); this.properties = builder.GetProperties(); this.ocspValidator = builder.GetOCSPValidator(); diff --git a/itext/itext.sign/itext/signatures/validation/v1/SignatureValidationProperties.cs b/itext/itext.sign/itext/signatures/validation/v1/SignatureValidationProperties.cs index 2c65dd551d..9a5212f391 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/SignatureValidationProperties.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/SignatureValidationProperties.cs @@ -89,6 +89,7 @@ public virtual TimeSpan GetFreshness(ValidationContext validationContext) { /// /// Sets the freshness setting for the specified validator, /// time based and certificate source contexts in milliseconds. + /// This parameter specifies how old revocation data can be, compared to validation time, in order to be trustworthy. /// /// the validators for which to apply the setting /// the certificate sources to @@ -115,7 +116,11 @@ public virtual bool GetContinueAfterFailure(ValidationContext validationContext) (p) => p.GetContinueAfterFailure().GetValueOrDefault()); } - /// Sets the Continue after failure setting for the provided context. + /// + /// Sets the Continue after failure setting for the provided context. + /// This parameter specifies if validation is expected to continue after first failure is encountered. + /// Only is considered to be a failure. + /// /// the validators for which to set the Continue after failure setting /// the certificateSources for which to set the Continue after failure setting /// diff --git a/itext/itext.sign/itext/signatures/validation/v1/SignatureValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/SignatureValidator.cs index 1c951aa99c..a033d99332 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/SignatureValidator.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/SignatureValidator.cs @@ -23,6 +23,7 @@ You should have received a copy of the GNU Affero General Public License using System; using System.Collections.Generic; using System.IO; +using iText.Commons.Actions.Contexts; using iText.Commons.Bouncycastle.Asn1.Tsp; using iText.Commons.Bouncycastle.Cert; using iText.Commons.Bouncycastle.Security; @@ -59,14 +60,18 @@ internal class SignatureValidator { private readonly CertificateChainValidator certificateChainValidator; + private readonly DocumentRevisionsValidator documentRevisionsValidator; + private readonly IssuingCertificateRetriever certificateRetriever; private readonly SignatureValidationProperties properties; private DateTime lastKnownPoE = DateTimeUtil.GetCurrentUtcTime(); + private IMetaInfo metaInfo = new ValidationMetaInfo(); + /// - /// Create new instance of + /// Creates new instance of /// . /// /// @@ -77,10 +82,30 @@ internal SignatureValidator(ValidatorChainBuilder builder) { this.certificateRetriever = builder.GetCertificateRetriever(); this.properties = builder.GetProperties(); this.certificateChainValidator = builder.GetCertificateChainValidator(); + this.documentRevisionsValidator = builder.GetDocumentRevisionsValidator(); this.baseValidationContext = new ValidationContext(ValidatorContext.SIGNATURE_VALIDATOR, CertificateSource .SIGNER_CERT, TimeBasedContext.PRESENT); } + /// + /// Sets the + /// + /// that will be used during new + /// + /// creations. + /// + /// meta info to set + /// + /// the same + /// + /// instance + /// + public virtual iText.Signatures.Validation.V1.SignatureValidator SetEventCountingMetaInfo(IMetaInfo metaInfo + ) { + this.metaInfo = metaInfo; + return this; + } + /// Validate all signatures in the document /// the document to be validated /// @@ -90,14 +115,25 @@ internal SignatureValidator(ValidatorChainBuilder builder) { /// public virtual ValidationReport ValidateSignatures(PdfDocument document) { ValidationReport report = new ValidationReport(); + documentRevisionsValidator.SetEventCountingMetaInfo(metaInfo); + ValidationReport revisionsValidationReport = documentRevisionsValidator.ValidateAllDocumentRevisions(baseValidationContext + , document); + report.Merge(revisionsValidationReport); + if (StopValidation(report, baseValidationContext)) { + return report; + } SignatureUtil util = new SignatureUtil(document); IList signatureNames = util.GetSignatureNames(); JavaCollectionsUtil.Reverse(signatureNames); foreach (String fieldName in signatureNames) { try { - using (PdfDocument doc = new PdfDocument(new PdfReader(util.ExtractRevision(fieldName)))) { + using (PdfDocument doc = new PdfDocument(new PdfReader(util.ExtractRevision(fieldName)), new DocumentProperties + ().SetEventCountingMetaInfo(metaInfo))) { ValidationReport subReport = ValidateLatestSignature(doc); report.Merge(subReport); + if (StopValidation(report, baseValidationContext)) { + return report; + } } } catch (System.IO.IOException e) { @@ -235,8 +271,8 @@ private IList GetCertificatesFromDss(ValidationReport validati } private bool StopValidation(ValidationReport result, ValidationContext validationContext) { - return !properties.GetContinueAfterFailure(validationContext) && result.GetValidationResult() != ValidationReport.ValidationResult - .VALID; + return !properties.GetContinueAfterFailure(validationContext) && result.GetValidationResult() == ValidationReport.ValidationResult + .INVALID; } } } diff --git a/itext/itext.sign/itext/signatures/validation/v1/ValidatorChainBuilder.cs b/itext/itext.sign/itext/signatures/validation/v1/ValidatorChainBuilder.cs index 35d4c2f69d..052be5d987 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/ValidatorChainBuilder.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/ValidatorChainBuilder.cs @@ -42,6 +42,8 @@ public class ValidatorChainBuilder { private CRLValidator crlValidator; + private DocumentRevisionsValidator documentRevisionsValidator; + /// /// Create a new /// @@ -58,6 +60,22 @@ internal virtual SignatureValidator BuildSignatureValidator() { return new SignatureValidator(this); } + /// + /// Create a bew + /// + /// instance with the current configuration. + /// + /// + /// Create a bew + /// + /// instance with the current configuration. + /// This method can be used to create multiple validators. + /// + /// a new instance of a document revisions validator + public virtual DocumentRevisionsValidator BuildDocumentRevisionsValidator() { + return new DocumentRevisionsValidator(this); + } + /// /// Create a new /// @@ -117,6 +135,19 @@ public virtual CRLValidator BuildCRLValidator() { return new CRLValidator(this); } + /// + /// Use this instance of a + /// + /// in the validation chain. + /// + /// the document revisions validator instance to use + /// the current ValidatorChainBuilder + public virtual ValidatorChainBuilder WithDocumentRevisionsValidator(DocumentRevisionsValidator documentRevisionsValidator + ) { + this.documentRevisionsValidator = documentRevisionsValidator; + return this; + } + /// /// Use this instance of a /// @@ -217,6 +248,23 @@ public virtual ValidatorChainBuilder WithTrustedCertificates(ICollection + /// Retrieves the explicitly added or automatically created + /// + /// instance. + /// + /// + /// the explicitly added or automatically created + /// + /// instance + /// + internal virtual DocumentRevisionsValidator GetDocumentRevisionsValidator() { + if (documentRevisionsValidator == null) { + documentRevisionsValidator = BuildDocumentRevisionsValidator(); + } + return documentRevisionsValidator; + } + /// /// Retrieves the explicitly added or automatically created /// diff --git a/itext/itext.sign/itext/signatures/validation/v1/context/ValidatorContext.cs b/itext/itext.sign/itext/signatures/validation/v1/context/ValidatorContext.cs index 0d4b723b02..bee283cc5d 100644 --- a/itext/itext.sign/itext/signatures/validation/v1/context/ValidatorContext.cs +++ b/itext/itext.sign/itext/signatures/validation/v1/context/ValidatorContext.cs @@ -51,6 +51,12 @@ public enum ValidatorContext { /// CERTIFICATE_CHAIN_VALIDATOR, /// This value is expected to be used in SignatureValidator context. - SIGNATURE_VALIDATOR + SIGNATURE_VALIDATOR, + /// + /// This value is expected to be used in + /// + /// context. + /// + DOCUMENT_REVISIONS_VALIDATOR } } diff --git a/port-hash b/port-hash index e0884ab23e..0e912551f9 100644 --- a/port-hash +++ b/port-hash @@ -1 +1 @@ -aca706e52404f21ae3c591197cf5d07672bb27b4 +7d1b55eee5814d7c7ceff96b0313c8582e19a3fc