xmlsecurity: reject a few dangerous annotation types during pdf sig verify
Change-Id: I950b49a6e7181639daf27348ddfa0f36586baa65 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105312 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
This commit is contained in:
parent
d261356266
commit
f231dacde9
BIN
xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf
Normal file
BIN
xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf
Normal file
Binary file not shown.
@ -402,6 +402,21 @@ CPPUNIT_TEST_FIXTURE(PDFSigningTest, testBadCertP1)
|
|||||||
rInformation.nStatus);
|
rInformation.nStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPPUNIT_TEST_FIXTURE(PDFSigningTest, testBadCertP3Stamp)
|
||||||
|
{
|
||||||
|
std::vector<SignatureInformation> aInfos
|
||||||
|
= verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p3-stamp.pdf", 1);
|
||||||
|
CPPUNIT_ASSERT(!aInfos.empty());
|
||||||
|
SignatureInformation& rInformation = aInfos[0];
|
||||||
|
|
||||||
|
// Without the accompanying fix in place, this test would have failed with:
|
||||||
|
// - Expected: 0 (SecurityOperationStatus_UNKNOWN)
|
||||||
|
// - Actual : 1 (SecurityOperationStatus_OPERATION_SUCCEEDED)
|
||||||
|
// i.e. adding a stamp annotation was not considered as a bad modification.
|
||||||
|
CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN,
|
||||||
|
rInformation.nStatus);
|
||||||
|
}
|
||||||
|
|
||||||
/// Test writing a PAdES signature.
|
/// Test writing a PAdES signature.
|
||||||
CPPUNIT_TEST_FIXTURE(PDFSigningTest, testSigningCertificateAttribute)
|
CPPUNIT_TEST_FIXTURE(PDFSigningTest, testSigningCertificateAttribute)
|
||||||
{
|
{
|
||||||
|
@ -226,8 +226,30 @@ bool IsCompleteSignature(SvStream& rStream, vcl::filter::PDFDocument& rDocument,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_FEATURE_PDFIUM
|
#if HAVE_FEATURE_PDFIUM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains checksums of a PDF page, which is rendered without annotations. It also contains
|
||||||
|
* the geometry of a few dangerous annotation types.
|
||||||
|
*/
|
||||||
|
struct PageChecksum
|
||||||
|
{
|
||||||
|
BitmapChecksum m_nPageContent;
|
||||||
|
std::vector<basegfx::B2DRectangle> m_aAnnotations;
|
||||||
|
bool operator==(const PageChecksum& rChecksum) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool PageChecksum::operator==(const PageChecksum& rChecksum) const
|
||||||
|
{
|
||||||
|
if (m_nPageContent != rChecksum.m_nPageContent)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_aAnnotations == rChecksum.m_aAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
/// Collects the checksum of each page of one version of the PDF.
|
/// Collects the checksum of each page of one version of the PDF.
|
||||||
void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<BitmapChecksum>& rPageChecksums,
|
void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<PageChecksum>& rPageChecksums,
|
||||||
int nMDPPerm)
|
int nMDPPerm)
|
||||||
{
|
{
|
||||||
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
||||||
@ -247,8 +269,25 @@ void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<BitmapChecksum
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitmapChecksum nPageChecksum = pPdfPage->getChecksum(nMDPPerm);
|
PageChecksum aPageChecksum;
|
||||||
rPageChecksums.push_back(nPageChecksum);
|
aPageChecksum.m_nPageContent = pPdfPage->getChecksum(nMDPPerm);
|
||||||
|
for (int i = 0; i < pPdfPage->getAnnotationCount(); ++i)
|
||||||
|
{
|
||||||
|
std::unique_ptr<vcl::pdf::PDFiumAnnotation> pPdfAnnotation = pPdfPage->getAnnotation(i);
|
||||||
|
vcl::pdf::PDFAnnotationSubType eType = pPdfAnnotation->getSubType();
|
||||||
|
switch (eType)
|
||||||
|
{
|
||||||
|
case vcl::pdf::PDFAnnotationSubType::Unknown:
|
||||||
|
case vcl::pdf::PDFAnnotationSubType::FreeText:
|
||||||
|
case vcl::pdf::PDFAnnotationSubType::Stamp:
|
||||||
|
case vcl::pdf::PDFAnnotationSubType::Redact:
|
||||||
|
aPageChecksum.m_aAnnotations.push_back(pPdfAnnotation->getRectangle());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rPageChecksums.push_back(aPageChecksum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -272,7 +311,7 @@ bool IsValidSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignatu
|
|||||||
aSignatureStream.WriteStream(rStream, nSignatureEOF);
|
aSignatureStream.WriteStream(rStream, nSignatureEOF);
|
||||||
rStream.Seek(nPos);
|
rStream.Seek(nPos);
|
||||||
aSignatureStream.Seek(0);
|
aSignatureStream.Seek(0);
|
||||||
std::vector<BitmapChecksum> aSignedPages;
|
std::vector<PageChecksum> aSignedPages;
|
||||||
AnalyizeSignatureStream(aSignatureStream, aSignedPages, nMDPPerm);
|
AnalyizeSignatureStream(aSignatureStream, aSignedPages, nMDPPerm);
|
||||||
|
|
||||||
SvMemoryStream aFullStream;
|
SvMemoryStream aFullStream;
|
||||||
@ -281,7 +320,7 @@ bool IsValidSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignatu
|
|||||||
aFullStream.WriteStream(rStream);
|
aFullStream.WriteStream(rStream);
|
||||||
rStream.Seek(nPos);
|
rStream.Seek(nPos);
|
||||||
aFullStream.Seek(0);
|
aFullStream.Seek(0);
|
||||||
std::vector<BitmapChecksum> aAllPages;
|
std::vector<PageChecksum> aAllPages;
|
||||||
AnalyizeSignatureStream(aFullStream, aAllPages, nMDPPerm);
|
AnalyizeSignatureStream(aFullStream, aAllPages, nMDPPerm);
|
||||||
|
|
||||||
// Fail if any page looks different after signing and at the end. Annotations/commenting doesn't
|
// Fail if any page looks different after signing and at the end. Annotations/commenting doesn't
|
||||||
|
Loading…
x
Reference in New Issue
Block a user