summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2019-10-28 14:23:36 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2019-12-04 17:13:37 +0100
commitb1d355f34a56c43514253f14e4565972bdf3869d (patch)
tree556276adde8475a5901c005662d6a09d918fedb9
parent43add4fcc0adf31342f47b8d27536223ec7f6e00 (diff)
sw: support for DRM encryption for binary doc formats
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>
-rw-r--r--sw/source/filter/ww8/ww8par.cxx99
-rw-r--r--sw/source/filter/ww8/ww8par.hxx4
2 files changed, 102 insertions, 1 deletions
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index aa596ad3ee2d..3c6a9d3307e7 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>
@@ -6292,6 +6294,95 @@ ErrCode WW8Reader::OpenMainStream( tools::SvRef<SotStorageStream>& rRef, sal_uIn
return nRet;
}
+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);
+ assert(rStream.is());
+
+ sal_Int32 nStreamSize = rStream->GetSize();
+ css::uno::Sequence< sal_Int8 > oData;
+ oData.realloc(nStreamSize);
+ sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize);
+ assert(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;
+ }
+
+ std::vector<OUString> aStreamsList;
+ comphelper::SequenceAsHashMap aStreamsData;
+ lcl_getListOfStreams(m_pStorage.get(), aStreamsData, OUString(""));
+
+ 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.reset(new SvMemoryStream());
+
+ uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false));
+ uno::Reference<io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*mDecodedStream.get()));
+
+ 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;
@@ -6323,7 +6414,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
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 6909a70c8847..1043b30eb959 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -131,9 +131,13 @@ struct WW8LFOInfo;
class WW8Reader : public StgReader
{
+ std::shared_ptr<SvStream> mDecodedStream;
virtual ErrCode Read(SwDoc &, const OUString& rBaseURL, SwPaM &, const OUString &) override;
ErrCode OpenMainStream( tools::SvRef<SotStorageStream>& rRef, sal_uInt16& rBuffSize );
+ ErrCode DecryptDRMPackage();
public:
+ WW8Reader() {}
+ ~WW8Reader() {}
virtual SwReaderType GetReaderType() override;
virtual bool HasGlossaries() const override;