[Libreoffice-commits] core.git: 4 commits - xmlsecurity/inc xmlsecurity/qa xmlsecurity/source
Miklos Vajna
vmiklos at collabora.co.uk
Wed Oct 26 18:10:17 UTC 2016
xmlsecurity/inc/pdfio/pdfdocument.hxx | 10 +
xmlsecurity/qa/unit/pdfsigning/data/2good.pdf |binary
xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx | 113 ++++++++++++++---
xmlsecurity/source/helper/documentsignaturemanager.cxx | 7 -
xmlsecurity/source/helper/pdfsignaturehelper.cxx | 3
xmlsecurity/source/pdfio/pdfdocument.cxx | 54 ++++++--
xmlsecurity/source/pdfio/pdfverify.cxx | 3
7 files changed, 155 insertions(+), 35 deletions(-)
New commits:
commit b6f98b71155d3c7af70bfc623cfaa7da0fbb905f
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Wed Oct 26 17:55:02 2016 +0200
xmlsecurity PDF verify: support SHA-256
And various other minor fixes.
Change-Id: Ifcccebf48aac8ad526406f2d7a402a840d3c91cd
diff --git a/xmlsecurity/inc/pdfio/pdfdocument.hxx b/xmlsecurity/inc/pdfio/pdfdocument.hxx
index f42350a..8ef7afd 100644
--- a/xmlsecurity/inc/pdfio/pdfdocument.hxx
+++ b/xmlsecurity/inc/pdfio/pdfdocument.hxx
@@ -75,6 +75,8 @@ public:
static size_t FindStartXRef(SvStream& rStream);
void ReadXRef(SvStream& rStream);
static void SkipWhitespace(SvStream& rStream);
+ /// Instead of all whitespace, just skip CR and NL characters.
+ static void SkipLineBreaks(SvStream& rStream);
size_t GetObjectOffset(size_t nIndex) const;
const std::vector< std::unique_ptr<PDFElement> >& GetElements();
std::vector<PDFObjectElement*> GetPages();
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index a1ac63c..df7a809 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -18,6 +18,7 @@
#include <comphelper/processfactory.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/string.hxx>
+#include <filter/msfilter/mscodec.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/string.hxx>
#include <sal/log.hxx>
@@ -784,7 +785,7 @@ bool PDFDocument::Tokenize(SvStream& rStream, bool bPartial)
return false;
}
- PDFDocument::SkipWhitespace(rStream);
+ PDFDocument::SkipLineBreaks(rStream);
m_aElements.push_back(std::unique_ptr<PDFElement>(new PDFStreamElement(nLength)));
if (!m_aElements.back()->Read(rStream))
return false;
@@ -822,7 +823,7 @@ bool PDFDocument::Tokenize(SvStream& rStream, bool bPartial)
}
else
{
- SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Tokenize: unexpected '" << aKeyword << "' keyword");
+ SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Tokenize: unexpected '" << aKeyword << "' keyword at byte position " << rStream.Tell());
return false;
}
}
@@ -830,7 +831,7 @@ bool PDFDocument::Tokenize(SvStream& rStream, bool bPartial)
{
if (!isspace(ch))
{
- SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Tokenize: unexpected character: " << ch);
+ SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Tokenize: unexpected character: " << ch << " at byte position " << rStream.Tell());
return false;
}
}
@@ -1034,6 +1035,24 @@ void PDFDocument::SkipWhitespace(SvStream& rStream)
}
}
+void PDFDocument::SkipLineBreaks(SvStream& rStream)
+{
+ char ch = 0;
+
+ while (true)
+ {
+ rStream.ReadChar(ch);
+ if (rStream.IsEof())
+ break;
+
+ if (ch != '\n' && ch != '\r')
+ {
+ rStream.SeekRel(-1);
+ return;
+ }
+ }
+}
+
size_t PDFDocument::GetObjectOffset(size_t nIndex) const
{
auto it = m_aXRef.find(nIndex);
@@ -1388,7 +1407,10 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
switch (SECOID_FindOIDTag(&aAlgorithm))
{
case SEC_OID_SHA1:
- nMaxResultLen = 20;
+ nMaxResultLen = msfilter::SHA1_HASH_LENGTH;
+ break;
+ case SEC_OID_SHA256:
+ nMaxResultLen = msfilter::SHA256_HASH_LENGTH;
break;
default:
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: unrecognized algorithm");
@@ -1519,14 +1541,14 @@ bool PDFNumberElement::Read(SvStream& rStream)
m_nOffset = rStream.Tell();
char ch;
rStream.ReadChar(ch);
- if (!isdigit(ch) && ch != '-')
+ if (!isdigit(ch) && ch != '-' && ch != '.')
{
rStream.SeekRel(-1);
return false;
}
while (!rStream.IsEof())
{
- if (!isdigit(ch) && ch != '-')
+ if (!isdigit(ch) && ch != '-' && ch != '.')
{
rStream.SeekRel(-1);
m_nLength = rStream.Tell() - m_nOffset;
@@ -1599,25 +1621,28 @@ const OString& PDFHexStringElement::GetValue() const
bool PDFLiteralStringElement::Read(SvStream& rStream)
{
- char ch;
+ char nPrevCh = 0;
+ char ch = 0;
rStream.ReadChar(ch);
if (ch != '(')
{
SAL_INFO("xmlsecurity.pdfio", "PDFHexStringElement::Read: expected '(' as first character");
return false;
}
+ nPrevCh = ch;
rStream.ReadChar(ch);
OStringBuffer aBuf;
while (!rStream.IsEof())
{
- if (ch == ')')
+ if (ch == ')' && nPrevCh != '\\')
{
m_aValue = aBuf.makeStringAndClear();
SAL_INFO("xmlsecurity.pdfio", "PDFLiteralStringElement::Read: m_aValue is '" << m_aValue << "'");
return true;
}
aBuf.append(ch);
+ nPrevCh = ch;
rStream.ReadChar(ch);
}
commit fc56d31c094f1e01adc5eca69b414e984c7e4baf
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Wed Oct 26 17:54:26 2016 +0200
xmlsecurity PDF verify: fix handling of non-imported certs
Previously we only managed to verify a signature in case the certificate
was already imported in the local NSS db. Don't depend on that by
(temporarily) importing certificates from the PDF signature.
Also adjust a test file that failed previously (the test DB has only an
"Alice" cert imported, intentionally sign the file as "Bob" as well).
Change-Id: Id8440acc31915f5a1718ea48129b950bb67e7486
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
index af668fc..10528c5 100644
Binary files a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf and b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 4442ac5..1f9ef83 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -214,6 +214,9 @@ void PDFSigningTest::testPDFRemoveAll()
aManager.mxSignatureStream = xStream;
aManager.read(/*bUseTempStream=*/false);
std::vector<SignatureInformation>& rInformations = aManager.maCurrentSignatureInformations;
+ // This was 1 when NSS_CMSSignerInfo_GetSigningCertificate() failed, which
+ // means that we only used the locally imported certificates for
+ // verification, not the ones provided in the PDF signature data.
CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
// Request removal of the first signature, should imply removal of the
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 20bbbbf..a1ac63c 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -1334,6 +1334,13 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
return false;
}
+ // Import certificates from the signed data temporarily, so it'll be
+ // possible to verify the signature, even if we didn't have the certificate
+ // perviously.
+ std::vector<CERTCertificate*> aDocumentCertificates;
+ for (size_t i = 0; pCMSSignedData->rawCerts[i]; ++i)
+ aDocumentCertificates.push_back(CERT_NewTempCertificate(CERT_GetDefaultCertDB(), pCMSSignedData->rawCerts[i], nullptr, 0, 0));
+
NSSCMSSignerInfo* pCMSSignerInfo = NSS_CMSSignedData_GetSignerInfo(pCMSSignedData, 0);
if (!pCMSSignerInfo)
{
@@ -1456,6 +1463,8 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
PORT_Free(pActualResultBuffer);
HASH_Destroy(pHASHContext);
NSS_CMSSignerInfo_Destroy(pCMSSignerInfo);
+ for (auto pDocumentCertificate : aDocumentCertificates)
+ CERT_DestroyCertificate(pDocumentCertificate);
return true;
#else
commit 23ca39a7c2cd5b33ac6361282432c6f34c458366
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Wed Oct 26 17:53:04 2016 +0200
xmlsecurity PDF sign: fix removing non-last signatures
PDF signatures are always chained, so when removing a signature not only
the item at a given position should be removed on the UI, but the whole
position-last range.
Change-Id: I76b14308885267cdac994fa957218a8b7df6b3cf
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
new file mode 100644
index 0000000..af668fc
Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index a2980db..4442ac5 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -12,7 +12,10 @@
#include <comphelper/processfactory.hxx>
#include <osl/file.hxx>
#include <test/bootstrapfixture.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <documentsignaturemanager.hxx>
#include <pdfio/pdfdocument.hxx>
using namespace com::sun::star;
@@ -42,13 +45,16 @@ public:
void testPDFAdd();
/// Test signing a previously unsigned file twice.
void testPDFAdd2();
- /// Test remove a signature from a previously signed file.
+ /// Test removing a signature from a previously signed file.
void testPDFRemove();
+ /// Test removing all signatures from a previously multi-signed file.
+ void testPDFRemoveAll();
CPPUNIT_TEST_SUITE(PDFSigningTest);
CPPUNIT_TEST(testPDFAdd);
CPPUNIT_TEST(testPDFAdd2);
CPPUNIT_TEST(testPDFRemove);
+ CPPUNIT_TEST(testPDFRemoveAll);
CPPUNIT_TEST_SUITE_END();
};
@@ -187,6 +193,38 @@ void PDFSigningTest::testPDFRemove()
}
#endif
}
+
+void PDFSigningTest::testPDFRemoveAll()
+{
+#ifndef _WIN32
+ // Make sure that good2.pdf has 2 valid signatures. Unlike in
+ // testPDFRemove(), here intentionally test DocumentSignatureManager and
+ // PDFSignatureHelper code as well.
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext = xSEInitializer->createSecurityContext(OUString());
+
+ // Copy the test document to a temporary file, as it'll be modified.
+ OUString aTargetDir = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_signing.test.user/");
+ OUString aOutURL = aTargetDir + "remove-all.pdf";
+ CPPUNIT_ASSERT_EQUAL(osl::File::RC::E_None, osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "2good.pdf", aOutURL));
+ // Load the test document as a storage and read its two signatures.
+ DocumentSignatureManager aManager(mxComponentContext, SignatureModeDocumentContent);
+ SvStream* pStream = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READ | StreamMode::WRITE);
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStream));
+ aManager.mxSignatureStream = xStream;
+ aManager.read(/*bUseTempStream=*/false);
+ std::vector<SignatureInformation>& rInformations = aManager.maCurrentSignatureInformations;
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+
+ // Request removal of the first signature, should imply removal of the
+ // second chained signature as well.
+ aManager.remove(0);
+ // This was 2, Manager didn't write anything to disk when removal succeeded
+ // (instead of doing that when removal failed).
+ // Then this was 1, when the chained signature wasn't removed.
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), rInformations.size());
+#endif
+}
CPPUNIT_TEST_SUITE_REGISTRATION(PDFSigningTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
index 0a5568f..dee86c8 100644
--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -317,14 +317,15 @@ void DocumentSignatureManager::remove(sal_uInt16 nPosition)
{
// Something not ZIP based, try PDF.
uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
- if (PDFSignatureHelper::RemoveSignature(xInputStream, nPosition))
+ if (!PDFSignatureHelper::RemoveSignature(xInputStream, nPosition))
{
SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::RemoveSignature() failed");
return;
}
- // Only erase when the removal was successfull, it may fail for PDF.
- maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition);
+ // Only erase when the removal was successful, it may fail for PDF.
+ // Also, erase the requested and all following signatures, as PDF signatures are always chained.
+ maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition, maCurrentSignatureInformations.end());
return;
}
commit f45ace2897dca1dd8f3553e46415df4fe7ad62d8
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Wed Oct 26 17:52:28 2016 +0200
xmlsecurity PDF signing: fix byte range check for multiple signatures
We can mandate that the byte range end is the end of the file for the
last signature only.
With this, signing a previously unsigned file multiple times works, so
add a matching testcase for that as well.
Change-Id: I8fe5482890fca4dab8da6305aa7fc7f60df612d8
diff --git a/xmlsecurity/inc/pdfio/pdfdocument.hxx b/xmlsecurity/inc/pdfio/pdfdocument.hxx
index 59c7f5d..f42350a 100644
--- a/xmlsecurity/inc/pdfio/pdfdocument.hxx
+++ b/xmlsecurity/inc/pdfio/pdfdocument.hxx
@@ -88,8 +88,12 @@ public:
/// Serializes the contents of the edit buffer.
bool Write(SvStream& rStream);
std::vector<PDFObjectElement*> GetSignatureWidgets();
- /// Return value is about if we can determine a result, rInformation is about the actual result.
- static bool ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, SignatureInformation& rInformation);
+ /**
+ * @param rInformation The actual result.
+ * @param bLast If this is the last signature in the file, so it covers the whole file physically.
+ * @return If we can determinate a result.
+ */
+ static bool ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, SignatureInformation& rInformation, bool bLast);
/// Remove the nth signature from read document in the edit buffer.
bool RemoveSignature(size_t nPosition);
};
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 6a3800f..a2980db 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -29,17 +29,25 @@ class PDFSigningTest : public test::BootstrapFixture
{
uno::Reference<uno::XComponentContext> mxComponentContext;
+ /**
+ * Sign rInURL once and save the result as rOutURL, asserting that rInURL
+ * had nOriginalSignatureCount signatures.
+ */
+ void sign(const OUString& rInURL, const OUString& rOutURL, size_t nOriginalSignatureCount);
public:
PDFSigningTest();
void setUp() override;
/// Test adding a new signature to a previously unsigned file.
void testPDFAdd();
+ /// Test signing a previously unsigned file twice.
+ void testPDFAdd2();
/// Test remove a signature from a previously signed file.
void testPDFRemove();
CPPUNIT_TEST_SUITE(PDFSigningTest);
CPPUNIT_TEST(testPDFAdd);
+ CPPUNIT_TEST(testPDFAdd2);
CPPUNIT_TEST(testPDFRemove);
CPPUNIT_TEST_SUITE_END();
};
@@ -67,25 +75,20 @@ void PDFSigningTest::setUp()
#endif
}
-void PDFSigningTest::testPDFAdd()
+void PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL, size_t nOriginalSignatureCount)
{
-#ifndef _WIN32
- // Make sure that no.pdf has no signatures.
+ // Make sure that input has nOriginalSignatureCount signatures.
uno::Reference<xml::crypto::XSEInitializer> xSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext = xSEInitializer->createSecurityContext(OUString());
xmlsecurity::pdfio::PDFDocument aDocument;
{
- OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
- OUString aInURL = aSourceDir + "no.pdf";
- SvFileStream aStream(aInURL, StreamMode::READ);
+ SvFileStream aStream(rInURL, StreamMode::READ);
CPPUNIT_ASSERT(aDocument.Read(aStream));
std::vector<xmlsecurity::pdfio::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets();
- CPPUNIT_ASSERT(aSignatures.empty());
+ CPPUNIT_ASSERT_EQUAL(nOriginalSignatureCount, aSignatures.size());
}
- // Sign it and write out the result as add.pdf.
- OUString aTargetDir = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_signing.test.user/");
- OUString aOutURL = aTargetDir + "add.pdf";
+ // Sign it and write out the result.
{
uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment = xSecurityContext->getSecurityEnvironment();
uno::Sequence<uno::Reference<security::XCertificate>> aCertificates = xSecurityEnvironment->getPersonalCertificates();
@@ -95,21 +98,54 @@ void PDFSigningTest::testPDFAdd()
return;
}
CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test"));
- SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC);
+ SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC);
CPPUNIT_ASSERT(aDocument.Write(aOutStream));
}
// Read back the signed pdf and make sure that it has one valid signature.
{
- SvFileStream aStream(aOutURL, StreamMode::READ);
+ SvFileStream aStream(rOutURL, StreamMode::READ);
xmlsecurity::pdfio::PDFDocument aVerifyDocument;
CPPUNIT_ASSERT(aVerifyDocument.Read(aStream));
std::vector<xmlsecurity::pdfio::PDFObjectElement*> aSignatures = aVerifyDocument.GetSignatureWidgets();
- // This was 0 when PDFDocument::Sign() silently returned success, without doing anything.
- CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aSignatures.size());
- SignatureInformation aInfo(0);
- CPPUNIT_ASSERT(xmlsecurity::pdfio::PDFDocument::ValidateSignature(aStream, aSignatures[0], aInfo));
+ // This was nOriginalSignatureCount when PDFDocument::Sign() silently returned success, without doing anything.
+ CPPUNIT_ASSERT_EQUAL(nOriginalSignatureCount + 1, aSignatures.size());
+ for (size_t i = 0; i < aSignatures.size(); ++i)
+ {
+ SignatureInformation aInfo(i);
+ bool bLast = i == aSignatures.size() - 1;
+ CPPUNIT_ASSERT(xmlsecurity::pdfio::PDFDocument::ValidateSignature(aStream, aSignatures[i], aInfo, bLast));
+ }
}
+}
+
+void PDFSigningTest::testPDFAdd()
+{
+#ifndef _WIN32
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "no.pdf";
+ OUString aTargetDir = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_signing.test.user/");
+ OUString aOutURL = aTargetDir + "add.pdf";
+ sign(aInURL, aOutURL, 0);
+#endif
+}
+
+void PDFSigningTest::testPDFAdd2()
+{
+#ifndef _WIN32
+ // Sign.
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "no.pdf";
+ OUString aTargetDir = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_signing.test.user/");
+ OUString aOutURL = aTargetDir + "add.pdf";
+ sign(aInURL, aOutURL, 0);
+
+ // Sign again.
+ aInURL = aTargetDir + "add.pdf";
+ aOutURL = aTargetDir + "add2.pdf";
+ // This failed with "second range end is not the end of the file" for the
+ // first signature.
+ sign(aInURL, aOutURL, 1);
#endif
}
@@ -128,7 +164,7 @@ void PDFSigningTest::testPDFRemove()
std::vector<xmlsecurity::pdfio::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aSignatures.size());
SignatureInformation aInfo(0);
- CPPUNIT_ASSERT(xmlsecurity::pdfio::PDFDocument::ValidateSignature(aStream, aSignatures[0], aInfo));
+ CPPUNIT_ASSERT(xmlsecurity::pdfio::PDFDocument::ValidateSignature(aStream, aSignatures[0], aInfo, /*bLast=*/true));
}
// Remove the signature and write out the result as remove.pdf.
diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx
index a1b1d20..859a479 100644
--- a/xmlsecurity/source/helper/pdfsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx
@@ -58,7 +58,8 @@ bool PDFSignatureHelper::ReadAndVerifySignature(const uno::Reference<io::XInputS
{
SignatureInformation aInfo(i);
- if (!xmlsecurity::pdfio::PDFDocument::ValidateSignature(*pStream, aSignatures[i], aInfo))
+ bool bLast = i == aSignatures.size() - 1;
+ if (!xmlsecurity::pdfio::PDFDocument::ValidateSignature(*pStream, aSignatures[i], aInfo, bLast))
{
SAL_WARN("xmlsecurity.helper", "failed to determine digest match");
continue;
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 7b8cea0..20bbbbf 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -1188,7 +1188,7 @@ std::vector<unsigned char> PDFDocument::DecodeHexString(PDFHexStringElement* pEl
return aRet;
}
-bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, SignatureInformation& rInformation)
+bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, SignatureInformation& rInformation, bool bLast)
{
PDFObjectElement* pValue = pSignature->LookupObject("V");
if (!pValue)
@@ -1285,7 +1285,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
}
rStream.Seek(STREAM_SEEK_TO_END);
size_t nFileEnd = rStream.Tell();
- if ((aByteRanges[1].first + aByteRanges[1].second) != nFileEnd)
+ if (bLast && (aByteRanges[1].first + aByteRanges[1].second) != nFileEnd)
{
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: second range end is not the end of the file");
return false;
diff --git a/xmlsecurity/source/pdfio/pdfverify.cxx b/xmlsecurity/source/pdfio/pdfverify.cxx
index f980db8..8e4ba42 100644
--- a/xmlsecurity/source/pdfio/pdfverify.cxx
+++ b/xmlsecurity/source/pdfio/pdfverify.cxx
@@ -113,7 +113,8 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc, pArgv)
for (size_t i = 0; i < aSignatures.size(); ++i)
{
SignatureInformation aInfo(i);
- if (!xmlsecurity::pdfio::PDFDocument::ValidateSignature(aStream, aSignatures[i], aInfo))
+ bool bLast = i == aSignatures.size() - 1;
+ if (!xmlsecurity::pdfio::PDFDocument::ValidateSignature(aStream, aSignatures[i], aInfo, bLast))
{
SAL_WARN("xmlsecurity.pdfio", "failed to determine digest match");
return 1;
More information about the Libreoffice-commits
mailing list