summaryrefslogtreecommitdiff
path: root/sd/source
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2019-11-08 21:00:12 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2020-05-25 10:07:26 +0200
commit1e18f22c6f497f269fe3226bc00afc3c8874049d (patch)
tree97425fbeffc342c551199b00c340f85215667838 /sd/source
parentaddb6099b85e1d15d8699856a626d48a8cf59f0a (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/source')
-rw-r--r--sd/source/filter/sdpptwrp.cxx107
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 )
{