poppler/Array.cc | 2 +- poppler/Array.h | 2 +- poppler/Catalog.cc | 21 ++++++++++++++++++--- poppler/Page.cc | 2 +- poppler/Stream.cc | 8 ++++++++ poppler/Stream.h | 7 +++++-- poppler/XRef.cc | 29 +++++++++++++++++++++++++++++ poppler/XRef.h | 4 ++++ 8 files changed, 67 insertions(+), 8 deletions(-)
New commits: commit 6dc7ff20af627de8576bf6aaad8e3ea4ef43ba52 Author: Albert Astals Cid <[email protected]> Date: Sun Dec 8 23:38:13 2019 +0100 Update (C) diff --git a/poppler/Array.cc b/poppler/Array.cc index f32dc38a..7f1fcdda 100644 --- a/poppler/Array.cc +++ b/poppler/Array.cc @@ -18,7 +18,7 @@ // Copyright (C) 2013 Thomas Freitag <[email protected]> // Copyright (C) 2013, 2017, 2019 Albert Astals Cid <[email protected]> // Copyright (C) 2017 Adrian Johnson <[email protected]> -// Copyright (C) 2018 Adam Reichold <[email protected]> +// Copyright (C) 2018, 2019 Adam Reichold <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git diff --git a/poppler/Array.h b/poppler/Array.h index 9232423a..ce84c3a7 100644 --- a/poppler/Array.h +++ b/poppler/Array.h @@ -18,7 +18,7 @@ // Copyright (C) 2013 Thomas Freitag <[email protected]> // Copyright (C) 2017-2019 Albert Astals Cid <[email protected]> // Copyright (C) 2017 Adrian Johnson <[email protected]> -// Copyright (C) 2018 Adam Reichold <[email protected]> +// Copyright (C) 2018, 2019 Adam Reichold <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git diff --git a/poppler/Page.cc b/poppler/Page.cc index f642018a..87621ca2 100644 --- a/poppler/Page.cc +++ b/poppler/Page.cc @@ -29,7 +29,7 @@ // Copyright (C) 2013 Jason Crain <[email protected]> // Copyright (C) 2013, 2017 Adrian Johnson <[email protected]> // Copyright (C) 2015 Philipp Reinkemeier <[email protected]> -// Copyright (C) 2018 Adam Reichold <[email protected]> +// Copyright (C) 2018, 2019 Adam Reichold <[email protected]> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git commit ce81e411086342af083e04f53dfd90d9e3628922 Author: Albert Astals Cid <[email protected]> Date: Sat Dec 7 00:18:53 2019 +0100 Make sure Base URI is encrypted if the document is before using it Otherwise we may be being targetted by a link content exfiltration diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc index ba4ec060..45115b8a 100644 --- a/poppler/Catalog.cc +++ b/poppler/Catalog.cc @@ -101,11 +101,26 @@ Catalog::Catalog(PDFDoc *docA) { acroForm = catDict.dictLookup("AcroForm"); // read base URI - Object obj = catDict.dictLookup("URI"); + // Before using the base URI we need to make sure the string is encrypted, for that we need to check the last Ref to it, that + // it can be either the String itself, the URI dict if the Base string is inside the URI dict or the Catalog dict if + // the Base string is inside the URI dict that is inside the Catalog dict + Ref refToCheck = xref->getRoot(); + Ref auxRef; + Object obj = catDict.getDict()->lookup("URI", &auxRef); if (obj.isDict()) { - Object obj2 = obj.dictLookup("Base"); + if (auxRef != Ref::INVALID()) { + refToCheck = auxRef; + } + Object obj2 = obj.getDict()->lookup("Base", &auxRef); if (obj2.isString()) { - baseURI = obj2.getString()->copy(); + if (auxRef != Ref::INVALID()) { + refToCheck = auxRef; + } + if (!xref->isEncrypted() || xref->isRefEncrypted(refToCheck)) { + baseURI = obj2.getString()->copy(); + } else { + error(errSyntaxError, -1, "Base URI is not encrypted and the document is. This may be a hacking attempt"); + } } } diff --git a/poppler/Stream.cc b/poppler/Stream.cc index 76a542af..3cf464c1 100644 --- a/poppler/Stream.cc +++ b/poppler/Stream.cc @@ -175,6 +175,14 @@ Stream *Stream::addFilters(Dict *dict, int recursion) { return str; } +bool Stream::isEncrypted() const { + for (const Stream *str = this; str != nullptr; str = str->getNextStream()) { + if (str->getKind() == strCrypt) + return true; + } + return false; +} + class BaseStreamStream : public Stream { public: diff --git a/poppler/Stream.h b/poppler/Stream.h index 46f2b375..4f606325 100644 --- a/poppler/Stream.h +++ b/poppler/Stream.h @@ -219,12 +219,15 @@ public: StreamColorSpaceMode * /*csMode*/) {} // Return the next stream in the "stack". - virtual Stream *getNextStream() { return nullptr; } + virtual Stream *getNextStream() const { return nullptr; } // Add filters to this stream according to the parameters in <dict>. // Returns the new stream. Stream *addFilters(Dict *dict, int recursion = 0); + // Returns true if this stream includes a crypt filter. + bool isEncrypted() const; + private: friend class Object; // for incRef/decRef @@ -344,7 +347,7 @@ public: Stream *getUndecodedStream() override { return str->getUndecodedStream(); } Dict *getDict() override { return str->getDict(); } Object *getDictObject() override { return str->getDictObject(); } - Stream *getNextStream() override { return str; } + Stream *getNextStream() const override { return str; } int getUnfilteredChar () override { return str->getUnfilteredChar(); } void unfilteredReset () override { str->unfilteredReset(); } diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 8f9dd7fe..b123ad23 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -1012,6 +1012,35 @@ void XRef::getEncryptionParameters(unsigned char **fileKeyA, CryptAlgorithm *enc } } +bool XRef::isRefEncrypted(Ref r) +{ + xrefLocker(); + + const XRefEntry *e = getEntry(r.num); + if (!e->obj.isNull()) { //check for updated object + return false; + } + + switch (e->type) { + case xrefEntryUncompressed: + { + return encrypted && !e->getFlag(XRefEntry::Unencrypted); + } + + case xrefEntryCompressed: + { + const Object objStr = fetch(e->offset, 0); + return objStr.getStream()->isEncrypted(); + } + + default: + { + } + } + + return false; +} + bool XRef::okToPrint(bool ignoreOwnerPW) const { return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint); } diff --git a/poppler/XRef.h b/poppler/XRef.h index 2e72ae54..8950980b 100644 --- a/poppler/XRef.h +++ b/poppler/XRef.h @@ -128,6 +128,9 @@ public: // Is the file encrypted? bool isEncrypted() const { return encrypted; } + // Is the given Ref encrypted? + bool isRefEncrypted(Ref r); + // Check various permissions. bool okToPrint(bool ignoreOwnerPW = false) const; bool okToPrintHighRes(bool ignoreOwnerPW = false) const; @@ -163,6 +166,7 @@ public: // Return the catalog object reference. int getRootNum() const { return rootNum; } int getRootGen() const { return rootGen; } + Ref getRoot() const { return { rootNum, rootGen }; } // Get end position for a stream in a damaged file. // Returns false if unknown or file is not damaged. _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
