summaryrefslogtreecommitdiff
path: root/xmlsecurity/source/pdfio/pdfdocument.cxx
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2020-09-04 17:17:48 +0200
committerGabor Kelemen <kelemen.gabor2@nisz.hu>2020-09-12 16:22:30 +0200
commit545cd5b8a7982a02a09dede03dd418afc6a5b6c8 (patch)
treed2eba0c4c3e97d6987289790fc5e031bb204db4f /xmlsecurity/source/pdfio/pdfdocument.cxx
parent2997c3b59856978321594314f672d273b8a72d7b (diff)
xmlsecurity: pdf incremental updates that are non-commenting are invalid
I.e. it's OK to add incremental updates for annotation/commenting purposes and that doesn't invalite existing signatures. Everything else does. (cherry picked from commit 61834cd574568613f0b0a2ee099a60fa5a8d9804) [ Also disable a pdfium assert on Windows, only on this branch, where it fails during CppunitTest_xmlsecurity_pdfsigning for reasons unclear to me. ] Conflicts: include/vcl/filter/PDFiumLibrary.hxx vcl/source/pdf/PDFiumLibrary.cxx Change-Id: I4607c242b3c6f6b01517b02407e9e7a095e2e069 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102325 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102432 Tested-by: Gabor Kelemen <kelemen.gabor2@nisz.hu> Reviewed-by: Gabor Kelemen <kelemen.gabor2@nisz.hu>
Diffstat (limited to 'xmlsecurity/source/pdfio/pdfdocument.cxx')
-rw-r--r--xmlsecurity/source/pdfio/pdfdocument.cxx69
1 files changed, 69 insertions, 0 deletions
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 7cf2c137c1c4..557180071a2c 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -12,6 +12,9 @@
#include <memory>
#include <vector>
+#include <config_features.h>
+
+#include <vcl/filter/PDFiumLibrary.hxx>
#include <rtl/string.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
@@ -20,6 +23,7 @@
#include <svl/sigstruct.hxx>
#include <svl/cryptosign.hxx>
#include <vcl/filter/pdfdocument.hxx>
+#include <vcl/bitmap.hxx>
using namespace com::sun::star;
@@ -133,6 +137,66 @@ bool IsCompleteSignature(SvStream& rStream, vcl::filter::PDFDocument& rDocument,
size_t nFileEnd = rStream.Tell();
return std::find(rAllEOFs.begin(), rAllEOFs.end(), nFileEnd) != rAllEOFs.end();
}
+
+/// Collects the checksum of each page of one version of the PDF.
+void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<BitmapChecksum>& rPageChecksums)
+{
+#if HAVE_FEATURE_PDFIUM
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ vcl::pdf::PDFiumDocument aPdfDocument(
+ FPDF_LoadMemDocument(rStream.GetData(), rStream.GetSize(), /*password=*/nullptr));
+
+ int nPageCount = aPdfDocument.getPageCount();
+ for (int nPage = 0; nPage < nPageCount; ++nPage)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage(aPdfDocument.openPage(nPage));
+ if (!pPdfPage)
+ {
+ return;
+ }
+
+ BitmapChecksum nPageChecksum = pPdfPage->getChecksum();
+ rPageChecksums.push_back(nPageChecksum);
+ }
+#else
+ (void)rStream;
+#endif
+}
+
+/**
+ * Checks if incremental updates after singing performed valid modifications only.
+ * Annotations/commenting is OK, other changes are not.
+ */
+bool IsValidSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignature)
+{
+ size_t nSignatureEOF = 0;
+ if (!GetEOFOfSignature(pSignature, nSignatureEOF))
+ {
+ return false;
+ }
+
+ SvMemoryStream aSignatureStream;
+ sal_uInt64 nPos = rStream.Tell();
+ rStream.Seek(0);
+ aSignatureStream.WriteStream(rStream, nSignatureEOF);
+ rStream.Seek(nPos);
+ aSignatureStream.Seek(0);
+ std::vector<BitmapChecksum> aSignedPages;
+ AnalyizeSignatureStream(aSignatureStream, aSignedPages);
+
+ SvMemoryStream aFullStream;
+ nPos = rStream.Tell();
+ rStream.Seek(0);
+ aFullStream.WriteStream(rStream);
+ rStream.Seek(nPos);
+ aFullStream.Seek(0);
+ std::vector<BitmapChecksum> aAllPages;
+ AnalyizeSignatureStream(aFullStream, aAllPages);
+
+ // Fail if any page looks different after signing and at the end. Annotations/commenting doesn't
+ // count, though.
+ return aSignedPages == aAllPages;
+}
}
namespace xmlsecurity
@@ -247,6 +311,11 @@ bool ValidateSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignat
return false;
}
rInformation.bPartialDocumentSignature = !IsCompleteSignature(rStream, rDocument, pSignature);
+ if (!IsValidSignature(rStream, pSignature))
+ {
+ SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: invalid incremental update detected");
+ return false;
+ }
// At this point there is no obviously missing info to validate the
// signature.