diff options
author | Vasily Melenchuk <vasily.melenchuk@cib.de> | 2019-11-08 21:00:12 +0300 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2020-05-25 10:07:26 +0200 |
commit | 1e18f22c6f497f269fe3226bc00afc3c8874049d (patch) | |
tree | 97425fbeffc342c551199b00c340f85215667838 /sd | |
parent | addb6099b85e1d15d8699856a626d48a8cf59f0a (diff) |
sd: add XPackageEncryption support for binary ppt
This adds read support for API-based MS-CRYPTO algos.
DRM encryption is implemented as a service and description
will be called if we found corresponding streams inside
binary OLE package.
Change-Id: Ib91538d53ee1f53a3cd14a44d47fd6f6136c0472
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/84441
Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'sd')
-rw-r--r-- | sd/source/filter/sdpptwrp.cxx | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx index edc21c482d45..08d897f6acfd 100644 --- a/sd/source/filter/sdpptwrp.cxx +++ b/sd/source/filter/sdpptwrp.cxx @@ -19,14 +19,21 @@ #include <sfx2/docfile.hxx> #include <sfx2/docfilt.hxx> +#include <sfx2/sfxsids.hrc> #include <filter/msfilter/msoleexp.hxx> #include <svx/svxerr.hxx> #include <unotools/fltrcfg.hxx> +#include <unotools/streamwrap.hxx> #include <sot/storage.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/processfactory.hxx> + +#include <com/sun/star/packages/XPackageEncryption.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <sdpptwrp.hxx> #include <DrawDocShell.hxx> - +#include <sfx2/frame.hxx> using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; @@ -67,9 +74,101 @@ SdPPTFilter::~SdPPTFilter() delete pBas; // deleting the compressed basic storage } +static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix) +{ + SvStorageInfoList aElements; + pStorage->FillInfoList(&aElements); + for (const auto & aElement : aElements) + { + OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName(); + if (aElement.IsStorage()) + { + SotStorage * pSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL); + lcl_getListOfStreams(pSubStorage, aStreamsData, sStreamFullName); + } + else + { + // Read stream + tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL); + if (rStream.is()) + { + sal_Int32 nStreamSize = rStream->GetSize(); + Sequence< sal_Int8 > oData; + oData.realloc(nStreamSize); + sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); + if (nStreamSize == nReadBytes) + aStreamsData[sStreamFullName] <<= oData; + } + } + } +} + +static tools::SvRef<SotStorage> lcl_DRMDecrypt(SfxMedium& rMedium, tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm) +{ + tools::SvRef<SotStorage> aNewStorage; + + // We have DRM encrypted storage. We should try to decrypt it first, if we can + Sequence< Any > aArguments; + Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + Reference< css::packages::XPackageEncryption > xPackageEncryption( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), UNO_QUERY); + + if (!xPackageEncryption.is()) + { + // We do not know how to decrypt this + return aNewStorage; + } + + comphelper::SequenceAsHashMap aStreamsData; + lcl_getListOfStreams(rStorage.get(), aStreamsData, ""); + + try { + Sequence<NamedValue> aStreams = aStreamsData.getAsConstNamedValueList(); + if (!xPackageEncryption->readEncryptionInfo(aStreams)) + { + // We failed with decryption + return aNewStorage; + } + + tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL); + if (!rContentStream.is()) + { + return aNewStorage; + } + + rNewStorageStrm = std::make_shared<SvMemoryStream>(); + + Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); + Reference<css::io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm)); + + if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream)) + { + // We failed with decryption + return aNewStorage; + } + + rNewStorageStrm->Seek(0); + + // Further reading is done from new document + aNewStorage = new SotStorage(*rNewStorageStrm); + + // Set the media descriptor data + Sequence<NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData(""); + rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData))); + } + catch (const std::exception&) + { + return aNewStorage; + } + + return aNewStorage; +} + bool SdPPTFilter::Import() { bool bRet = false; + std::shared_ptr<SvStream> aDecryptedStorageStrm; tools::SvRef<SotStorage> pStorage = new SotStorage( mrMedium.GetInStream(), false ); if( !pStorage->GetError() ) { @@ -82,6 +181,12 @@ bool SdPPTFilter::Import() xDualStorage = pStorage->OpenSotStorage( sDualStorage, StreamMode::STD_READ ); pStorage = xDualStorage; } + OUString sDRMContent("\011DRMContent"); + if (pStorage->IsContained(sDRMContent)) + { + // Document is DRM encrypted + pStorage = lcl_DRMDecrypt(mrMedium, pStorage, aDecryptedStorageStrm); + } std::unique_ptr<SvStream> pDocStream(pStorage->OpenSotStream( "PowerPoint Document" , StreamMode::STD_READ )); if( pDocStream ) { |