[Libreoffice-commits] core.git: sw/source

Vasily Melenchuk (via logerrit) logerrit at kemper.freedesktop.org
Mon May 25 08:05:58 UTC 2020


 sw/source/filter/ww8/ww8par.cxx |   99 +++++++++++++++++++++++++++++++++++++++-
 sw/source/filter/ww8/ww8par.hxx |    3 +
 2 files changed, 101 insertions(+), 1 deletion(-)

New commits:
commit f1c1a4de8f17128191e1c6d26a737b88fcc31fc9
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Mon Oct 28 14:23:36 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 25 10:05:05 2020 +0200

    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 at cib.de>
    Tested-by: Vasily Melenchuk <vasily.melenchuk at cib.de>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/84437
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

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
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index ce2b8803f12f..679c56a01ad5 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -132,9 +132,12 @@ 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() {}
     virtual SwReaderType GetReaderType() override;
 
     virtual bool HasGlossaries() const override;


More information about the Libreoffice-commits mailing list