summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/ww8par.cxx
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2019-10-28 14:23:36 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2020-05-25 10:05:05 +0200
commitf1c1a4de8f17128191e1c6d26a737b88fcc31fc9 (patch)
treed1eb791c3903974aa7d75eadab6e69b4e7ca019e /sw/source/filter/ww8/ww8par.cxx
parentb9353394f46e46485fd148f2842f0c1e8e5322e3 (diff)
sw: add XPackageEncryption support for binary doc
This adds read support for API-based MS-CRYPTO algos. DRM encryption is implemented as a service and desrption will be called if we found corresponding streams inside binary OLE package. Change-Id: Ie1a5b0417e1e7851b24d410c8f41dc85dd9210f7 Reviewed-on: https://gerrit.libreoffice.org/81600 Reviewed-by: Vasily Melenchuk <vasily.melenchuk@cib.de> Tested-by: Vasily Melenchuk <vasily.melenchuk@cib.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/84437 Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'sw/source/filter/ww8/ww8par.cxx')
-rw-r--r--sw/source/filter/ww8/ww8par.cxx99
1 files changed, 98 insertions, 1 deletions
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 082f778dc984..ebb5bd5d66d5 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -25,12 +25,14 @@
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/packages/XPackageEncryption.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <i18nlangtag/languagetag.hxx>
#include <unotools/configmgr.hxx>
#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/streamwrap.hxx>
#include <rtl/random.h>
#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.hxx>
@@ -6329,6 +6331,95 @@ ErrCode WW8Reader::OpenMainStream( tools::SvRef<SotStorageStream>& rRef, sal_uIn
return nRet;
}
+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();
+ css::uno::Sequence< sal_Int8 > oData;
+ oData.realloc(nStreamSize);
+ sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize);
+ if (nStreamSize == nReadBytes)
+ aStreamsData[sStreamFullName] <<= oData;
+ }
+ }
+ }
+}
+
+ErrCode WW8Reader::DecryptDRMPackage()
+{
+ // We have DRM encrypted storage. We should try to decrypt it first, if we can
+ uno::Sequence< uno::Any > aArguments;
+ uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+ uno::Reference< packages::XPackageEncryption > xPackageEncryption(
+ xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), uno::UNO_QUERY);
+
+ if (!xPackageEncryption.is())
+ {
+ // We do not know how to decrypt this
+ return ERRCODE_IO_ACCESSDENIED;
+ }
+
+ comphelper::SequenceAsHashMap aStreamsData;
+ lcl_getListOfStreams(m_pStorage.get(), aStreamsData, "");
+
+ try {
+ uno::Sequence<beans::NamedValue> aStreams = aStreamsData.getAsConstNamedValueList();
+ if (!xPackageEncryption->readEncryptionInfo(aStreams))
+ {
+ // We failed with decryption
+ return ERRCODE_IO_ACCESSDENIED;
+ }
+
+ tools::SvRef<SotStorageStream> rContentStream = m_pStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL);
+ if (!rContentStream.is())
+ {
+ return ERRCODE_IO_NOTEXISTS;
+ }
+
+ mDecodedStream = std::make_shared<SvMemoryStream>();
+
+ uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false));
+ uno::Reference<io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*mDecodedStream));
+
+ if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream))
+ {
+ // We failed with decryption
+ return ERRCODE_IO_ACCESSDENIED;
+ }
+
+ mDecodedStream->Seek(0);
+
+ // Further reading is done from new document
+ m_pStorage = new SotStorage(*mDecodedStream);
+
+ // Set the media descriptor data
+ uno::Sequence<beans::NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData("");
+ m_pMedium->GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData)));
+ }
+ catch (const std::exception&)
+ {
+ return ERRCODE_IO_ACCESSDENIED;
+ }
+
+ return ERRCODE_NONE;
+}
+
ErrCode WW8Reader::Read(SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, const OUString & /* FileName */)
{
sal_uInt16 nOldBuffSize = 32768;
@@ -6360,7 +6451,13 @@ ErrCode WW8Reader::Read(SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, cons
if( m_pStorage.is() )
{
- nRet = OpenMainStream( refStrm, nOldBuffSize );
+ // Check if we have special encrypted content
+ tools::SvRef<SotStorageStream> rRef = m_pStorage->OpenSotStream("\006DataSpaces/DataSpaceInfo/\011DRMDataSpace", StreamMode::READ | StreamMode::SHARE_DENYALL);
+ if (rRef.is())
+ {
+ nRet = DecryptDRMPackage();
+ }
+ nRet = OpenMainStream(refStrm, nOldBuffSize);
pIn = refStrm.get();
}
else