Rebased ref, commits from common ancestor: commit d24199ab2c401866c4f5e48cb99ecf0e45ac5d55 Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Thu Sep 26 22:09:56 2019 +0200 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:55 2019 +0100
external/breakpad: glibc 2.30 declares tgkill ...so building against glibc-headers-2.30-4.fc31.x86_64 fails with > src/client/linux/handler/exception_handler.cc:109:12: error: static declaration of 'tgkill' follows non-static declaration > static int tgkill(pid_t tgid, pid_t tid, int sig) { > ^ > /usr/include/bits/signal_ext.h:29:12: note: previous declaration is here > extern int tgkill (__pid_t __tgid, __pid_t __tid, int __signal); > ^ > 1 error generated. Upstream commit <https://chromium.googlesource.com/breakpad/breakpad/+/ 7e3c165000d44fa153a3270870ed500bc8bbb461%5E%21/> "Fix double declaration of tgkill when using Android NDK Headers" looks like the perfect fit. Change-Id: I1b4805886fb7c770cf9733f34a31296e6b859d92 Reviewed-on: https://gerrit.libreoffice.org/79661 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> (cherry picked from commit 55556a4cebbb35f15e7989bf0a6e276db99944e3) diff --git a/external/breakpad/0001-Fix-double-declaration-of-tgkill-when-using-Android-.patch.1 b/external/breakpad/0001-Fix-double-declaration-of-tgkill-when-using-Android-.patch.1 new file mode 100644 index 000000000000..7c8a68c2451a --- /dev/null +++ b/external/breakpad/0001-Fix-double-declaration-of-tgkill-when-using-Android-.patch.1 @@ -0,0 +1,49 @@ +From 7e3c165000d44fa153a3270870ed500bc8bbb461 Mon Sep 17 00:00:00 2001 +From: Nicholas Baldwin <baldw...@google.com> +Date: Fri, 27 Oct 2017 11:44:36 -0700 +Subject: [PATCH] Fix double declaration of tgkill when using Android NDK + Headers. + +As of Android API level 16 tgkill is declared in the NDK version of +signal.h, which conflicts with the static definition found in +src/client/linux/handler/exception_handler.cc. This change removes +the static tgkill definition and replaces its use with sys_tgkill +from the linux syscall support library. + +Bug: +Change-Id: Ic70addd8a064cfa36345d86b7e36409e2089e909 +Reviewed-on: https://chromium-review.googlesource.com/738912 +Reviewed-by: Mike Frysinger <vap...@chromium.org> +--- + src/client/linux/handler/exception_handler.cc | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc +index 95005209..cd94e3b5 100644 +--- a/src/client/linux/handler/exception_handler.cc ++++ b/src/client/linux/handler/exception_handler.cc +@@ -105,12 +105,6 @@ + #define PR_SET_PTRACER 0x59616d61 + #endif + +-// A wrapper for the tgkill syscall: send a signal to a specific thread. +-static int tgkill(pid_t tgid, pid_t tid, int sig) { +- return syscall(__NR_tgkill, tgid, tid, sig); +- return 0; +-} +- + namespace google_breakpad { + + namespace { +@@ -400,7 +394,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { + // In order to retrigger it, we have to queue a new signal by calling + // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is + // due to the kernel sending a SIGABRT from a user request via SysRQ. +- if (tgkill(getpid(), syscall(__NR_gettid), sig) < 0) { ++ if (sys_tgkill(getpid(), syscall(__NR_gettid), sig) < 0) { + // If we failed to kill ourselves (e.g. because a sandbox disallows us + // to do so), we instead resort to terminating our process. This will + // result in an incorrect exit code. +-- +2.23.0 + diff --git a/external/breakpad/UnpackedTarball_breakpad.mk b/external/breakpad/UnpackedTarball_breakpad.mk index b70510234e38..633574cd34a7 100644 --- a/external/breakpad/UnpackedTarball_breakpad.mk +++ b/external/breakpad/UnpackedTarball_breakpad.mk @@ -23,6 +23,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,breakpad,\ external/breakpad/breakpad-stackwalk.patch.1 \ external/breakpad/ucontext.patch \ external/breakpad/0001-Handle-race-between-ExceptionHandler-SignalHandler-a.patch.1 \ + external/breakpad/0001-Fix-double-declaration-of-tgkill-when-using-Android-.patch.1 \ )) ifeq ($(COM_IS_CLANG),TRUE) commit 296d4f852c9184150c2772998faa268511ed9942 Author: Thorsten Behrens <thorsten.behr...@cib.de> AuthorDate: Wed Dec 4 06:24:26 2019 +0100 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:55 2019 +0100 Update default branch Change-Id: I5bed5207db18747539ce8398ed85619385d51249 diff --git a/.gitreview b/.gitreview index 042036087fed..fd925839a944 100644 --- a/.gitreview +++ b/.gitreview @@ -3,5 +3,5 @@ host=gerrit.libreoffice.org port=29418 project=core defaultremote=logerrit -defaultbranch=libreoffice-6-3-0 +defaultbranch=feature/cib_contract3756b commit 026ed9616710d5fcc72006f05f209f69284451f8 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Nov 29 13:07:57 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 tdf#118639: store ODF encryption data for autorecovery When saving autorecovery information, ODF is used. If the original document is password-protected, its autorecovery is also generated password-protected (since ef87ff6680f79362a431db6e7ef2f40cfc576219). But when the stored encryption data for non-ODF document does not contain "PackageSHA256UTF8EncryptionKey" value, following ZipPackage::GetEncryptionKey fails, so the whole save fails. So just generate and append ODF encryption keys where we still have user password. Change-Id: I776e28de784489521e4941d1075690f90c056014 Reviewed-on: https://gerrit.libreoffice.org/84052 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Conflicts: sfx2/source/dialog/filedlghelper.cxx diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx index 9134e7d050a2..af3741347344 100644 --- a/comphelper/source/misc/docpasswordhelper.cxx +++ b/comphelper/source/misc/docpasswordhelper.cxx @@ -422,6 +422,7 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( bool* pbIsDefaultPassword ) { css::uno::Sequence< css::beans::NamedValue > aEncData; + OUString aPassword; DocPasswordVerifierResult eResult = DocPasswordVerifierResult::WrongPassword; // first, try provided default passwords @@ -435,8 +436,12 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( if( !rPassword.isEmpty() ) { eResult = rVerifier.verifyPassword( rPassword, aEncData ); - if( pbIsDefaultPassword ) - *pbIsDefaultPassword = eResult == DocPasswordVerifierResult::OK; + if (eResult == DocPasswordVerifierResult::OK) + { + aPassword = rPassword; + if (pbIsDefaultPassword) + *pbIsDefaultPassword = true; + } if( eResult != DocPasswordVerifierResult::WrongPassword ) break; } @@ -458,7 +463,11 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( if( eResult == DocPasswordVerifierResult::WrongPassword ) { if( !rMediaPassword.isEmpty() ) + { eResult = rVerifier.verifyPassword( rMediaPassword, aEncData ); + if (eResult == DocPasswordVerifierResult::OK) + aPassword = rMediaPassword; + } } // request a password (skip, if result is OK or ABORT) @@ -474,6 +483,8 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( { if( !pRequest->getPassword().isEmpty() ) eResult = rVerifier.verifyPassword( pRequest->getPassword(), aEncData ); + if (eResult == DocPasswordVerifierResult::OK) + aPassword = pRequest->getPassword(); } else { @@ -486,6 +497,21 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( { } + if (eResult == DocPasswordVerifierResult::OK && !aPassword.isEmpty()) + { + if (std::find_if(std::cbegin(aEncData), std::cend(aEncData), + [](const css::beans::NamedValue& val) { + return val.Name == PACKAGE_ENCRYPTIONDATA_SHA256UTF8; + }) + == std::cend(aEncData)) + { + // tdf#118639: We need ODF encryption data for autorecovery, where password + // will already be unavailable, so generate and append it here + aEncData = comphelper::concatSequences( + aEncData, OStorageHelper::CreatePackageEncryptionData(aPassword)); + } + } + return (eResult == DocPasswordVerifierResult::OK) ? aEncData : uno::Sequence< beans::NamedValue >(); } diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx index 28f7d1179824..a2167c3a255b 100644 --- a/sfx2/source/dialog/filedlghelper.cxx +++ b/sfx2/source/dialog/filedlghelper.cxx @@ -2727,6 +2727,8 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter, { if ( pPasswordRequest->getPassword().getLength() ) { + css::uno::Sequence< css::beans::NamedValue > aEncryptionData; + // TODO/LATER: The filters should show the password dialog themself in future if ( bMSType ) { @@ -2736,7 +2738,7 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter, ::comphelper::SequenceAsHashMap aHashData; aHashData[ OUString( "OOXPassword" ) ] <<= pPasswordRequest->getPassword(); aHashData[ OUString( "CryptoType" ) ] <<= OUString( "Standard" ); - pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) ); + aEncryptionData = aHashData.getAsConstNamedValueList(); } else { @@ -2749,7 +2751,7 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter, aHashData[ OUString( "STD97EncryptionKey" ) ] <<= aEncryptionKey; aHashData[ OUString( "STD97UniqueID" ) ] <<= aUniqueID; - pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aHashData.getAsConstNamedValueList() ) ) ); + aEncryptionData = aHashData.getAsConstNamedValueList(); } else { @@ -2757,10 +2759,14 @@ ErrCode RequestPassword(const std::shared_ptr<const SfxFilter>& pCurrentFilter, } } } - else - { - pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( ::comphelper::OStorageHelper::CreatePackageEncryptionData( pPasswordRequest->getPassword() ) ) ) ); - } + + // tdf#118639: We need ODF encryption data for autorecovery where password will already + // be unavailable, even for non-ODF documents, so append it here unconditionally + pSet->Put(SfxUnoAnyItem( + SID_ENCRYPTIONDATA, + uno::makeAny(comphelper::concatSequences( + aEncryptionData, comphelper::OStorageHelper::CreatePackageEncryptionData( + pPasswordRequest->getPassword()))))); } if ( pPasswordRequest->getRecommendReadOnly() ) commit 643f2e6d8176e5700eef29c64806efc6ba478671 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 29 11:57:51 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 oox: fixes for cang errors after refactoring: Change-Id: I6c0ff55e3a6d3edbac78aa6e806da4a290af142d diff --git a/include/oox/crypto/DocumentDecryption.hxx b/include/oox/crypto/DocumentDecryption.hxx index d1754c791a4a..d188336a07d6 100644 --- a/include/oox/crypto/DocumentDecryption.hxx +++ b/include/oox/crypto/DocumentDecryption.hxx @@ -35,10 +35,10 @@ namespace crypto { class OOX_DLLPUBLIC DocumentDecryption { private: + css::uno::Reference< css::uno::XComponentContext > mxContext; oox::ole::OleStorage& mrOleStorage; css::uno::Sequence<css::beans::NamedValue> maStreamsSequence; css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption; - css::uno::Reference< css::uno::XComponentContext > mxContext; public: DocumentDecryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext, oox::ole::OleStorage& rOleStorage); diff --git a/include/oox/crypto/DocumentEncryption.hxx b/include/oox/crypto/DocumentEncryption.hxx index 8b9f8b89f7f0..5b45b5f53f8b 100644 --- a/include/oox/crypto/DocumentEncryption.hxx +++ b/include/oox/crypto/DocumentEncryption.hxx @@ -21,6 +21,7 @@ namespace com { namespace sun { namespace star { namespace io { class XStream; } namespace packages { class XPackageEncryption; } + namespace beans { struct NamedValue; } } } } namespace oox { namespace ole { class OleStorage; } } @@ -31,11 +32,11 @@ namespace crypto { class OOX_DLLPUBLIC DocumentEncryption { private: + css::uno::Reference< css::uno::XComponentContext > mxContext; css::uno::Reference< css::io::XStream > mxDocumentStream; oox::ole::OleStorage& mrOleStorage; css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption; const css::uno::Sequence< css::beans::NamedValue >& mMediaEncData; - css::uno::Reference< css::uno::XComponentContext > mxContext; public: DocumentEncryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext, diff --git a/include/oox/crypto/StrongEncryptionDataSpace.hxx b/include/oox/crypto/StrongEncryptionDataSpace.hxx index d3eb76a2c1a8..966185c94612 100644 --- a/include/oox/crypto/StrongEncryptionDataSpace.hxx +++ b/include/oox/crypto/StrongEncryptionDataSpace.hxx @@ -12,6 +12,7 @@ #define INCLUDED_OOX_CRYPTO_STRONGENCRYPTINDATASPACE_HXX #include <oox/dllapi.h> +#include <cppuhelper/implbase.hxx> #include <com/sun/star/packages/XPackageEncryption.hpp> #include <com/sun/star/io/XInputStream.hpp> #include <oox/crypto/CryptoEngine.hxx> commit 30efa3c975755a7b8cc22b207944bcded4aeb9f0 Author: Thorsten Behrens <thorsten.behr...@cib.de> AuthorDate: Wed Dec 4 13:29:21 2019 +0100 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 oox: more encryption engines refactoring Make cryto tests build again. Change-Id: Id72eb461f5f04eecc0a5bdd9c9e7f2d94df7c8ab diff --git a/oox/qa/unit/CryptoTest.cxx b/oox/qa/unit/CryptoTest.cxx index 47d567fab34b..dd2c7c6ad8bb 100644 --- a/oox/qa/unit/CryptoTest.cxx +++ b/oox/qa/unit/CryptoTest.cxx @@ -19,6 +19,7 @@ #include <oox/crypto/AgileEngine.hxx> #include <oox/helper/binaryinputstream.hxx> #include <oox/helper/binaryoutputstream.hxx> +#include <oox/crypto/CryptTools.hxx> using namespace css; @@ -66,7 +67,7 @@ void CryptoTest::testCryptoHash() aContentString.getStr() + aContentString.getLength()); std::vector<sal_uInt8> aKey = { 'k', 'e', 'y' }; { - oox::core::CryptoHash aCryptoHash(aKey, oox::core::CryptoHashType::SHA1); + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA1); aCryptoHash.update(aContent); std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); CPPUNIT_ASSERT_EQUAL(std::string("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"), @@ -74,7 +75,7 @@ void CryptoTest::testCryptoHash() } { - oox::core::CryptoHash aCryptoHash(aKey, oox::core::CryptoHashType::SHA256); + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA256); aCryptoHash.update(aContent); std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); CPPUNIT_ASSERT_EQUAL( @@ -83,7 +84,7 @@ void CryptoTest::testCryptoHash() } { - oox::core::CryptoHash aCryptoHash(aKey, oox::core::CryptoHashType::SHA512); + oox::crypto::CryptoHash aCryptoHash(aKey, oox::crypto::CryptoHashType::SHA512); aCryptoHash.update(aContent); std::vector<sal_uInt8> aHash = aCryptoHash.finalize(); CPPUNIT_ASSERT_EQUAL( commit 09102a425d9412558d31f9f4625ab6b8d7bc4b8c Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Tue Nov 26 11:08:14 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 oox: encryption engines refactoring Restore original state of Agile and Standard 2007 engines. Instead of standalone services for each of them use newly introduced wrapper service. Change-Id: Icc32a4e0ce215090c3b739f1dcaa0654b36b7f08 Conflicts: include/oox/crypto/AgileEngine.hxx include/oox/crypto/Standard2007Engine.hxx diff --git a/include/oox/crypto/AgileEngine.hxx b/include/oox/crypto/AgileEngine.hxx index de3836ffdb19..7c923c0f2cd6 100644 --- a/include/oox/crypto/AgileEngine.hxx +++ b/include/oox/crypto/AgileEngine.hxx @@ -15,19 +15,17 @@ #include <oox/dllapi.h> #include <oox/crypto/CryptTools.hxx> +#include <oox/crypto/CryptoEngine.hxx> #include <rtl/ustring.hxx> #include <sal/types.h> -#include <com/sun/star/packages/XPackageEncryption.hpp> namespace oox { class BinaryXInputStream; class BinaryXOutputStream; } -namespace com::sun::star::uno { class XComponentContext; } - namespace oox { -namespace core { +namespace crypto { struct OOX_DLLPUBLIC AgileEncryptionInfo { @@ -76,15 +74,11 @@ enum class AgileEncryptionPreset AES_256_SHA512, }; -class OOX_DLLPUBLIC AgileEngine : public cppu::WeakImplHelper<css::packages::XPackageEncryption> +class OOX_DLLPUBLIC AgileEngine : public CryptoEngine { private: - std::vector<sal_uInt8> mKey; AgileEncryptionInfo mInfo; AgileEncryptionPreset meEncryptionPreset; - css::uno::Reference< css::uno::XComponentContext > mxContext; - - css::uno::Reference<css::io::XInputStream> getStream(const css::uno::Sequence<css::beans::NamedValue> & rStreams, const OUString sStreamName); void calculateHashFinal(const OUString& rPassword, std::vector<sal_uInt8>& aHashFinal); @@ -102,58 +96,52 @@ private: static Crypto::CryptoType cryptoType(const AgileEncryptionInfo& rInfo); - // Decryption - - bool decryptHmacKey(); - bool decryptHmacValue(); +public: + AgileEngine(); - AgileEncryptionInfo& getInfo() { return mInfo; } + AgileEncryptionInfo& getInfo() { return mInfo;} void setPreset(AgileEncryptionPreset ePreset) { meEncryptionPreset = ePreset; } + // Decryption + void decryptEncryptionKey(OUString const & rPassword); bool decryptAndCheckVerifierHash(OUString const & rPassword); - // Encryption - - bool encryptHmacKey(); - bool encryptHmacValue(); - - bool generateAndEncryptVerifierHash(OUString const & rPassword); - - bool encryptEncryptionKey(OUString const & rPassword); - void setupEncryptionParameters(AgileEncryptionParameters const & rAgileEncryptionParameters); - bool setupEncryptionKey(OUString const & rPassword); - - css::uno::Sequence<sal_Int8> writeEncryptionInfo(); - css::uno::Sequence<sal_Int8> writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream>& rxInputStream); + bool generateEncryptionKey(OUString const & rPassword) override; + bool readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) override; + bool decrypt(BinaryXInputStream& aInputStream, + BinaryXOutputStream& aOutputStream) override; -public: - AgileEngine(const css::uno::Reference< css::uno::XComponentContext >& rxContext); + bool checkDataIntegrity() override; - // Decryption + bool decryptHmacKey(); + bool decryptHmacValue(); - virtual sal_Bool SAL_CALL generateEncryptionKey(const OUString & rPassword) override; - virtual sal_Bool SAL_CALL readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) override; - virtual sal_Bool SAL_CALL decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, - css::uno::Reference<css::io::XOutputStream>& rxOutputStream) override; + // Encryption + void writeEncryptionInfo(BinaryXOutputStream& rStream) override; - virtual sal_Bool SAL_CALL checkDataIntegrity() override; + void encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, + css::uno::Reference<css::io::XOutputStream>& rxOutputStream, + sal_uInt32 nSize) override; - // Encryption + bool setupEncryption(OUString const & rPassword) override; - virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream) override; + bool generateAndEncryptVerifierHash(OUString const & rPassword); - virtual sal_Bool SAL_CALL setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) override; + bool encryptHmacKey(); + bool encryptHmacValue(); - virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL createEncryptionData(const OUString& rPassword) override; + bool encryptEncryptionKey(OUString const & rPassword); + void setupEncryptionParameters(AgileEncryptionParameters const & rAgileEncryptionParameters); + bool setupEncryptionKey(OUString const & rPassword); }; -} // namespace core +} // namespace crypto } // namespace oox #endif diff --git a/include/oox/crypto/CryptTools.hxx b/include/oox/crypto/CryptTools.hxx index 80d52cbeed74..2489cafe3c9c 100644 --- a/include/oox/crypto/CryptTools.hxx +++ b/include/oox/crypto/CryptTools.hxx @@ -28,7 +28,7 @@ #include <memory> namespace oox { -namespace core { +namespace crypto { /** Rounds up the input to the nearest multiple * @@ -115,7 +115,7 @@ public: }; -} // namespace core +} // namespace crypto } // namespace oox #endif diff --git a/include/oox/crypto/CryptoEngine.hxx b/include/oox/crypto/CryptoEngine.hxx new file mode 100644 index 000000000000..72bde8920dfc --- /dev/null +++ b/include/oox/crypto/CryptoEngine.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_OOX_CRYPTO_CRYPTOENGINE_HXX +#define INCLUDED_OOX_CRYPTO_CRYPTOENGINE_HXX + +#include <vector> + +#include <rtl/ustring.hxx> +#include <sal/types.h> + +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> + +namespace oox { + class BinaryXInputStream; + class BinaryXOutputStream; +} + +namespace oox { +namespace crypto { + +class CryptoEngine +{ +protected: + std::vector<sal_uInt8> mKey; + +public: + CryptoEngine() + {} + + virtual ~CryptoEngine() + {} + + // Decryption + virtual bool readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) = 0; + + virtual bool generateEncryptionKey(const OUString& rPassword) = 0; + + virtual bool decrypt( + BinaryXInputStream& aInputStream, + BinaryXOutputStream& aOutputStream) = 0; + + // Encryption + virtual void writeEncryptionInfo(BinaryXOutputStream & rStream) = 0; + + virtual bool setupEncryption(const OUString& rPassword) = 0; + + virtual void encrypt(const css::uno::Reference<css::io::XInputStream> & rxInputStream, + css::uno::Reference<css::io::XOutputStream> & rxOutputStream, + sal_uInt32 nSize) = 0; + + virtual bool checkDataIntegrity() = 0; +}; + +} // namespace crypto +} // namespace oox + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/oox/crypto/DocumentDecryption.hxx b/include/oox/crypto/DocumentDecryption.hxx index fdea2c25f9f7..d1754c791a4a 100644 --- a/include/oox/crypto/DocumentDecryption.hxx +++ b/include/oox/crypto/DocumentDecryption.hxx @@ -30,7 +30,7 @@ namespace com { namespace sun { namespace star { namespace oox { namespace ole { class OleStorage; } } namespace oox { -namespace core { +namespace crypto { class OOX_DLLPUBLIC DocumentDecryption { @@ -40,8 +40,6 @@ private: css::uno::Reference< css::packages::XPackageEncryption > mxPackageEncryption; css::uno::Reference< css::uno::XComponentContext > mxContext; - void readStrongEncryptionInfo(); - public: DocumentDecryption(const css::uno::Reference< css::uno::XComponentContext >& rxContext, oox::ole::OleStorage& rOleStorage); @@ -53,7 +51,7 @@ public: }; -} // namespace core +} // namespace crypto } // namespace oox #endif diff --git a/include/oox/crypto/DocumentEncryption.hxx b/include/oox/crypto/DocumentEncryption.hxx index 106fe287b28f..8b9f8b89f7f0 100644 --- a/include/oox/crypto/DocumentEncryption.hxx +++ b/include/oox/crypto/DocumentEncryption.hxx @@ -26,7 +26,7 @@ namespace com { namespace sun { namespace star { namespace oox { namespace ole { class OleStorage; } } namespace oox { -namespace core { +namespace crypto { class OOX_DLLPUBLIC DocumentEncryption { @@ -47,7 +47,7 @@ public: }; -} // namespace core +} // namespace crypto } // namespace oox #endif diff --git a/include/oox/crypto/Standard2007Engine.hxx b/include/oox/crypto/Standard2007Engine.hxx index d1ab8039d772..fef8fc55bab0 100644 --- a/include/oox/crypto/Standard2007Engine.hxx +++ b/include/oox/crypto/Standard2007Engine.hxx @@ -12,7 +12,7 @@ #define INCLUDED_OOX_CRYPTO_STANDARD2007ENGINE_HXX #include <oox/dllapi.h> -#include <com/sun/star/packages/XPackageEncryption.hpp> +#include <oox/crypto/CryptoEngine.hxx> #include <filter/msfilter/mscodec.hxx> #include <rtl/digest.h> #include <rtl/ustring.hxx> @@ -23,47 +23,40 @@ namespace oox { class BinaryXOutputStream; } -namespace com::sun::star::uno { class XComponentContext; } - namespace oox { -namespace core { +namespace crypto { -class OOX_DLLPUBLIC Standard2007Engine : public cppu::WeakImplHelper<css::packages::XPackageEncryption> +class OOX_DLLPUBLIC Standard2007Engine : public CryptoEngine { msfilter::StandardEncryptionInfo mInfo; - std::vector<sal_uInt8> mKey; - css::uno::Reference< css::uno::XComponentContext > mxContext; bool generateVerifier(); bool calculateEncryptionKey(const OUString& rPassword); - css::uno::Reference<css::io::XInputStream> getStream(const css::uno::Sequence<css::beans::NamedValue> & rStreams, const OUString sStreamName); - css::uno::Sequence<sal_Int8> writeEncryptionInfo(); - css::uno::Sequence<sal_Int8> writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream>& rxInputStream); - public: - Standard2007Engine(const css::uno::Reference<css::uno::XComponentContext>& rxContext); + Standard2007Engine() = default; - // Decryption + bool readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) override; - virtual sal_Bool SAL_CALL generateEncryptionKey(const OUString & rPassword) override; - virtual sal_Bool SAL_CALL readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) override; - virtual sal_Bool SAL_CALL decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, - css::uno::Reference<css::io::XOutputStream>& rxOutputStream) override; + virtual bool generateEncryptionKey(OUString const & rPassword) override; + virtual bool decrypt( + BinaryXInputStream& aInputStream, + BinaryXOutputStream& aOutputStream) override; - virtual sal_Bool SAL_CALL checkDataIntegrity() override; + bool checkDataIntegrity() override; - // Encryption + void encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, + css::uno::Reference<css::io::XOutputStream>& rxOutputStream, + sal_uInt32 nSize) override; - virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream) override; + virtual void writeEncryptionInfo(BinaryXOutputStream& rStream) override; - virtual sal_Bool SAL_CALL setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) override; + virtual bool setupEncryption(OUString const & rPassword) override; - virtual css::uno::Sequence<css::beans::NamedValue> SAL_CALL createEncryptionData(const OUString& rPassword) override; }; -} // namespace core +} // namespace crypto } // namespace oox #endif diff --git a/include/oox/crypto/StrongEncryptionDataSpace.hxx b/include/oox/crypto/StrongEncryptionDataSpace.hxx new file mode 100644 index 000000000000..d3eb76a2c1a8 --- /dev/null +++ b/include/oox/crypto/StrongEncryptionDataSpace.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_OOX_CRYPTO_STRONGENCRYPTINDATASPACE_HXX +#define INCLUDED_OOX_CRYPTO_STRONGENCRYPTINDATASPACE_HXX + +#include <oox/dllapi.h> +#include <com/sun/star/packages/XPackageEncryption.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <oox/crypto/CryptoEngine.hxx> + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace oox +{ +namespace crypto +{ +class OOX_DLLPUBLIC StrongEncryptionDataSpace final + : public cppu::WeakImplHelper<css::packages::XPackageEncryption> +{ + css::uno::Reference<css::uno::XComponentContext> mxContext; + std::unique_ptr<CryptoEngine> mCryptoEngine; + + css::uno::Reference<css::io::XInputStream> + getStream(const css::uno::Sequence<css::beans::NamedValue>& rStreams, + const rtl::OUString sStreamName); + +public: + StrongEncryptionDataSpace(const css::uno::Reference<css::uno::XComponentContext>& rxContext); + + // Decryption + + virtual sal_Bool SAL_CALL generateEncryptionKey(const OUString& rPassword) override; + virtual sal_Bool SAL_CALL + readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) override; + virtual sal_Bool SAL_CALL + decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, + css::uno::Reference<css::io::XOutputStream>& rxOutputStream) override; + + virtual sal_Bool SAL_CALL checkDataIntegrity() override; + + // Encryption + + virtual css::uno::Sequence<css::beans::NamedValue> + SAL_CALL encrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream) override; + + virtual sal_Bool SAL_CALL + setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) override; + + virtual css::uno::Sequence<css::beans::NamedValue> + SAL_CALL createEncryptionData(const OUString& rPassword) override; +}; + +} // namespace crypto +} // namespace oox + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk index 2d4718a320cb..51b61a931cd1 100644 --- a/oox/Library_oox.mk +++ b/oox/Library_oox.mk @@ -102,6 +102,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\ oox/source/crypto/DocumentEncryption \ oox/source/crypto/DocumentDecryption \ oox/source/crypto/Standard2007Engine \ + oox/source/crypto/StrongEncryptionDataSpace \ oox/source/docprop/docprophandler \ oox/source/docprop/ooxmldocpropimport \ oox/source/drawingml/chart/axiscontext \ diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx index f59b15c56df9..565ac9c8d9a6 100644 --- a/oox/source/core/filterdetect.cxx +++ b/oox/source/core/filterdetect.cxx @@ -250,16 +250,16 @@ bool lclIsZipPackage( const Reference< XComponentContext >& rxContext, const Ref class PasswordVerifier : public IDocPasswordVerifier { public: - explicit PasswordVerifier( DocumentDecryption& aDecryptor ); + explicit PasswordVerifier( crypto::DocumentDecryption& aDecryptor ); virtual DocPasswordVerifierResult verifyPassword( const OUString& rPassword, Sequence<NamedValue>& rEncryptionData ) override; virtual DocPasswordVerifierResult verifyEncryptionData( const Sequence<NamedValue>& rEncryptionData ) override; private: - DocumentDecryption& mDecryptor; + crypto::DocumentDecryption& mDecryptor; }; -PasswordVerifier::PasswordVerifier( DocumentDecryption& aDecryptor ) : +PasswordVerifier::PasswordVerifier( crypto::DocumentDecryption& aDecryptor ) : mDecryptor(aDecryptor) {} @@ -308,7 +308,7 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript { try { - DocumentDecryption aDecryptor(mxContext, aOleStorage); + crypto::DocumentDecryption aDecryptor(mxContext, aOleStorage); if( aDecryptor.readEncryptionInfo() ) { diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx index fe7e541de4b3..91be91736911 100644 --- a/oox/source/core/xmlfilterbase.cxx +++ b/oox/source/core/xmlfilterbase.cxx @@ -908,7 +908,7 @@ bool XmlFilterBase::implFinalizeExport( MediaDescriptor& rMediaDescriptor ) Reference< XStream> xDocumentStream (FilterBase::implGetOutputStream(rMediaDescriptor)); oox::ole::OleStorage aOleStorage( getComponentContext(), xDocumentStream, true ); - DocumentEncryption encryptor( getComponentContext(), getMainDocumentStream(), aOleStorage, aMediaEncData ); + crypto::DocumentEncryption encryptor( getComponentContext(), getMainDocumentStream(), aOleStorage, aMediaEncData ); bRet = encryptor.encrypt(); if (bRet) aOleStorage.commit(); diff --git a/oox/source/crypto/AgileEngine.cxx b/oox/source/crypto/AgileEngine.cxx index fea1498cc8b9..e232a7ef94c3 100644 --- a/oox/source/crypto/AgileEngine.cxx +++ b/oox/source/crypto/AgileEngine.cxx @@ -21,7 +21,6 @@ #include <comphelper/processfactory.hxx> #include <comphelper/base64.hxx> #include <comphelper/sequence.hxx> -#include <comphelper/sequenceashashmap.hxx> #include <filter/msfilter/mscodec.hxx> #include <tools/stream.hxx> @@ -29,8 +28,6 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/io/XStream.hpp> -#include <com/sun/star/io/SequenceInputStream.hpp> -#include <com/sun/star/io/XSequenceOutputStream.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/xml/sax/XFastParser.hpp> #include <com/sun/star/xml/sax/XFastTokenHandler.hpp> @@ -46,15 +43,7 @@ using namespace css::xml::sax; using namespace css::xml; namespace oox { -namespace core { - -extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* - com_sun_star_comp_oox_crypto_Agile_get_implementation( - XComponentContext* pCtx, Sequence<Any> const& /*arguments*/) -{ - return cppu::acquire(new AgileEngine(pCtx/*, arguments*/)); -} - +namespace crypto { namespace { @@ -159,13 +148,13 @@ public: comphelper::Base64::decode(encryptedKeyValue, rAttribute.Value); mInfo.encryptedKeyValue = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(encryptedKeyValue); } - else if (rAttrLocalName == "encryptedHmacKey") + if (rAttrLocalName == "encryptedHmacKey") { Sequence<sal_Int8> aValue; comphelper::Base64::decode(aValue, rAttribute.Value); mInfo.hmacEncryptedKey = comphelper::sequenceToContainer<std::vector<sal_uInt8>>(aValue); } - else if (rAttrLocalName == "encryptedHmacValue") + if (rAttrLocalName == "encryptedHmacValue") { Sequence<sal_Int8> aValue; comphelper::Base64::decode(aValue, rAttribute.Value); @@ -229,9 +218,8 @@ CryptoHashType cryptoHashTypeFromString(OUString const & sAlgorithm) } // namespace -AgileEngine::AgileEngine(const Reference< XComponentContext >& rxContext) : - meEncryptionPreset(AgileEncryptionPreset::AES_256_SHA512), - mxContext(rxContext) +AgileEngine::AgileEngine() + : meEncryptionPreset(AgileEncryptionPreset::AES_256_SHA512) {} Crypto::CryptoType AgileEngine::cryptoType(const AgileEncryptionInfo& rInfo) @@ -358,7 +346,7 @@ void AgileEngine::decryptEncryptionKey(OUString const & rPassword) } // TODO: Rename -sal_Bool AgileEngine::generateEncryptionKey(OUString const & rPassword) +bool AgileEngine::generateEncryptionKey(OUString const & rPassword) { bool bResult = decryptAndCheckVerifierHash(rPassword); @@ -422,7 +410,7 @@ bool AgileEngine::decryptHmacValue() return true; } -sal_Bool AgileEngine::checkDataIntegrity() +bool AgileEngine::checkDataIntegrity() { bool bResult = (mInfo.hmacHash.size() == mInfo.hmacCalculatedHash.size() && std::equal(mInfo.hmacHash.begin(), mInfo.hmacHash.end(), mInfo.hmacCalculatedHash.begin())); @@ -430,14 +418,11 @@ sal_Bool AgileEngine::checkDataIntegrity() return bResult; } -sal_Bool AgileEngine::decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, - css::uno::Reference<css::io::XOutputStream>& rxOutputStream) +bool AgileEngine::decrypt(BinaryXInputStream& aInputStream, + BinaryXOutputStream& aOutputStream) { CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm)); - BinaryXInputStream aInputStream(rxInputStream, true); - BinaryXOutputStream aOutputStream(rxOutputStream, true); - sal_uInt32 totalSize = aInputStream.readuInt32(); // Document unencrypted size - 4 bytes // account for size in HMAC std::vector<sal_uInt8> aSizeBytes(sizeof(sal_uInt32)); @@ -495,39 +480,17 @@ sal_Bool AgileEngine::decrypt(const css::uno::Reference<css::io::XInputStream>& mInfo.hmacCalculatedHash = aCryptoHash.finalize(); - rxOutputStream->flush(); - return true; } -uno::Reference<io::XInputStream> AgileEngine::getStream(const Sequence<NamedValue> & rStreams, const OUString sStreamName) +bool AgileEngine::readEncryptionInfo(uno::Reference<io::XInputStream> & rxInputStream) { - for (const auto & aStream : rStreams) - { - if (aStream.Name == sStreamName) - { - css::uno::Sequence<sal_Int8> aSeq; - aStream.Value >>= aSeq; - Reference<XInputStream> aStream(io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq), UNO_QUERY_THROW); - return aStream; - } - } - return nullptr; -} - -sal_Bool AgileEngine::readEncryptionInfo(const Sequence<NamedValue>& aStreams) -{ - uno::Reference<io::XInputStream> xEncryptionInfo = getStream(aStreams, "EncryptionInfo"); - - BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true); - aBinaryInputStream.readuInt32(); // Version - // Check reserved value std::vector<sal_uInt8> aExpectedReservedBytes(sizeof(sal_uInt32)); ByteOrderConverter::writeLittleEndian(aExpectedReservedBytes.data(), msfilter::AGILE_ENCRYPTION_RESERVED); uno::Sequence<sal_Int8> aReadReservedBytes(sizeof(sal_uInt32)); - xEncryptionInfo->readBytes(aReadReservedBytes, aReadReservedBytes.getLength()); + rxInputStream->readBytes(aReadReservedBytes, aReadReservedBytes.getLength()); if (!std::equal(aReadReservedBytes.begin(), aReadReservedBytes.end(), aExpectedReservedBytes.begin())) return false; @@ -547,7 +510,7 @@ sal_Bool AgileEngine::readEncryptionInfo(const Sequence<NamedValue>& aStreams) xParser->setTokenHandler(xFastTokenHandler); InputSource aInputSource; - aInputSource.aInputStream = xEncryptionInfo; + aInputSource.aInputStream = rxInputStream; xParser->parseStream(aInputSource); // CHECK info data @@ -619,7 +582,7 @@ bool AgileEngine::encryptHmacKey() return false; // Encrypted salt must be multiple of block size - sal_Int32 nEncryptedSaltSize = oox::core::roundUp(mInfo.hashSize, mInfo.blockSize); + sal_Int32 nEncryptedSaltSize = oox::crypto::roundUp(mInfo.hashSize, mInfo.blockSize); // We need to extend hmacSalt to multiple of block size, padding with 0x36 std::vector<sal_uInt8> extendedSalt(mInfo.hmacKey); @@ -695,33 +658,14 @@ bool AgileEngine::encryptEncryptionKey(OUString const & rPassword) return true; } -sal_Bool AgileEngine::setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) +bool AgileEngine::setupEncryption(OUString const & rPassword) { if (meEncryptionPreset == AgileEncryptionPreset::AES_128_SHA1) setupEncryptionParameters({ 100000, 16, 128, 20, 16, OUString("AES"), OUString("ChainingModeCBC"), OUString("SHA1") }); else setupEncryptionParameters({ 100000, 16, 256, 64, 16, OUString("AES"), OUString("ChainingModeCBC"), OUString("SHA512") }); - OUString sPassword; - for (int i = 0; i < rMediaEncData.getLength(); i++) - { - if (rMediaEncData[i].Name == "OOXPassword") - { - OUString sCryptoType; - rMediaEncData[i].Value >>= sPassword; - } - } - - return setupEncryptionKey(sPassword); -} - -uno::Sequence<beans::NamedValue> AgileEngine::createEncryptionData(const OUString & rPassword) -{ - comphelper::SequenceAsHashMap aEncryptionData; - aEncryptionData["OOXPassword"] <<= rPassword; - aEncryptionData["CryptoType"] <<= OUString("AgileEngine"); - - return aEncryptionData.getAsConstNamedValueList(); + return setupEncryptionKey(rPassword); } void AgileEngine::setupEncryptionParameters(AgileEncryptionParameters const & rAgileEncryptionParameters) @@ -755,13 +699,8 @@ bool AgileEngine::setupEncryptionKey(OUString const & rPassword) return true; } -css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptionInfo() +void AgileEngine::writeEncryptionInfo(BinaryXOutputStream & rStream) { - Reference<XOutputStream> aEncryptionInfoStream( - mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext), - UNO_QUERY); - BinaryXOutputStream rStream(aEncryptionInfoStream, false); - rStream.WriteUInt32(msfilter::VERSION_INFO_AGILE); rStream.WriteUInt32(msfilter::AGILE_ENCRYPTION_RESERVED); @@ -815,29 +754,19 @@ css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptionInfo() aXmlWriter.endDocument(); } rStream.writeMemory(aMemStream.GetData(), aMemStream.GetSize()); - - rStream.close(); - aEncryptionInfoStream->flush(); - - Reference<XSequenceOutputStream> aEncryptionInfoSequenceStream(aEncryptionInfoStream, UNO_QUERY); - return aEncryptionInfoSequenceStream->getWrittenBytes(); } -css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream>& rxInputStream) +void AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> & rxInputStream, + css::uno::Reference<css::io::XOutputStream> & rxOutputStream, + sal_uInt32 nSize) { CryptoHash aCryptoHash(mInfo.hmacKey, cryptoHashTypeFromString(mInfo.hashAlgorithm)); - Reference<XOutputStream> aOutputStream( - mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext), - UNO_QUERY); - BinaryXOutputStream aBinaryOutputStream(aOutputStream, false); - + BinaryXOutputStream aBinaryOutputStream(rxOutputStream, false); BinaryXInputStream aBinaryInputStream(rxInputStream, false); - Reference<XSeekable> xSeekable(rxInputStream, UNO_QUERY); - sal_uInt32 nLength = xSeekable->getLength(); std::vector<sal_uInt8> aSizeBytes(sizeof(sal_uInt32)); - ByteOrderConverter::writeLittleEndian(aSizeBytes.data(), nLength); + ByteOrderConverter::writeLittleEndian(aSizeBytes.data(), nSize); aBinaryOutputStream.writeMemory(aSizeBytes.data(), aSizeBytes.size()); // size aCryptoHash.update(aSizeBytes, aSizeBytes.size()); @@ -867,7 +796,7 @@ css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptedDocument(const css::uno: while ((inputLength = aBinaryInputStream.readMemory(inputBuffer.data(), inputBuffer.size())) > 0) { sal_uInt32 correctedInputLength = inputLength % mInfo.blockSize == 0 ? - inputLength : oox::core::roundUp(inputLength, sal_uInt32(mInfo.blockSize)); + inputLength : oox::crypto::roundUp(inputLength, sal_uInt32(mInfo.blockSize)); // Update Key sal_uInt8* segmentBegin = reinterpret_cast<sal_uInt8*>(&nSegment); @@ -888,21 +817,9 @@ css::uno::Sequence<sal_Int8> AgileEngine::writeEncryptedDocument(const css::uno: } mInfo.hmacHash = aCryptoHash.finalize(); encryptHmacValue(); - - Reference<XSequenceOutputStream> aSequenceStream(aOutputStream, UNO_QUERY); - return aSequenceStream->getWrittenBytes(); -} - - -css::uno::Sequence<css::beans::NamedValue> AgileEngine::encrypt(const css::uno::Reference<css::io::XInputStream> & rxInputStream) -{ - comphelper::SequenceAsHashMap aStreams; - aStreams["EncryptedPackage"] <<= writeEncryptedDocument(rxInputStream); - aStreams["EncryptionInfo"] <<= writeEncryptionInfo(); - return aStreams.getAsConstNamedValueList(); } -} // namespace core +} // namespace crypto } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/CryptTools.cxx b/oox/source/crypto/CryptTools.cxx index 96290e0dc5fc..f1c2b6bbb2ee 100644 --- a/oox/source/crypto/CryptTools.cxx +++ b/oox/source/crypto/CryptTools.cxx @@ -25,7 +25,7 @@ #endif // USE_TLS_NSS namespace oox { -namespace core { +namespace crypto { #if USE_TLS_OPENSSL struct CryptoImpl @@ -481,7 +481,7 @@ std::vector<sal_uInt8> CryptoHash::finalize() return aHash; } -} // namespace core +} // namespace crypto } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/DocumentDecryption.cxx b/oox/source/crypto/DocumentDecryption.cxx index 8c8c52dd4a42..198d2f3e5c1f 100644 --- a/oox/source/crypto/DocumentDecryption.cxx +++ b/oox/source/crypto/DocumentDecryption.cxx @@ -9,6 +9,7 @@ */ #include <oox/crypto/DocumentDecryption.hxx> +#include <oox/helper/binaryinputstream.hxx> #include <comphelper/sequenceashashmap.hxx> #include <cppuhelper/implbase.hxx> @@ -21,6 +22,15 @@ #include <oox/ole/olestorage.hxx> #include <filter/msfilter/mscodec.hxx> +#include <com/sun/star/task/PasswordRequestMode.hpp> +#include <comphelper/docpasswordrequest.hxx> +#include <comphelper/stillreadwriteinteraction.hxx> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/task/PasswordContainer.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> + +#include <sal/log.hxx> + namespace { void lcl_getListOfStreams(oox::StorageBase* pStorage, std::vector<OUString>& rElementNames) @@ -47,7 +57,7 @@ void lcl_getListOfStreams(oox::StorageBase* pStorage, std::vector<OUString>& rEl } namespace oox { -namespace core { +namespace crypto { using namespace css; @@ -84,33 +94,6 @@ bool DocumentDecryption::generateEncryptionKey(const OUString& rPassword) return false; } -void DocumentDecryption::readStrongEncryptionInfo() -{ - uno::Reference<io::XInputStream> xEncryptionInfo = mrOleStorage.openInputStream("EncryptionInfo"); - - BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true); - sal_uInt32 aVersion = aBinaryInputStream.readuInt32(); - - uno::Sequence< uno::Any > aArguments; - - switch (aVersion) - { - case msfilter::VERSION_INFO_2007_FORMAT: - case msfilter::VERSION_INFO_2007_FORMAT_SP2: - mxPackageEncryption.set( - mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( - "com.sun.star.comp.oox.crypto.Standard2007Engine", aArguments, mxContext), css::uno::UNO_QUERY); - break; - case msfilter::VERSION_INFO_AGILE: - mxPackageEncryption.set( - mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( - "com.sun.star.comp.oox.crypto.AgileEngine", aArguments, mxContext), css::uno::UNO_QUERY); - break; - default: - break; - } -} - bool DocumentDecryption::readEncryptionInfo() { if (!mrOleStorage.isStorage()) @@ -118,6 +101,8 @@ bool DocumentDecryption::readEncryptionInfo() // Read 0x6DataSpaces/DataSpaceMap uno::Reference<io::XInputStream> xDataSpaceMap = mrOleStorage.openInputStream("\006DataSpaces/DataSpaceMap"); + OUString sDataSpaceName; + if (xDataSpaceMap.is()) { BinaryXInputStream aDataSpaceStream(xDataSpaceMap, true); @@ -126,7 +111,6 @@ bool DocumentDecryption::readEncryptionInfo() sal_uInt32 aEntryCount = aDataSpaceStream.readuInt32(); SAL_WARN_IF(aEntryCount != 1, "oox", "DataSpaceMap contains more than one entry. Some content may be skipped"); - OUString sDataSpaceName; // Read each DataSpaceMapEntry (MS-OFFCRYPTO 2.1.6.1) for (sal_uInt32 i = 0; i < aEntryCount; i++) { @@ -147,25 +131,20 @@ bool DocumentDecryption::readEncryptionInfo() sDataSpaceName = aDataSpaceStream.readUnicodeArray(aDataSpaceNameLength / 2); aDataSpaceStream.skip((4 - (aDataSpaceNameLength & 3)) & 3); // Skip padding } - - uno::Sequence< uno::Any > aArguments; - mxPackageEncryption.set( - mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( - "com.sun.star.comp.oox.crypto." + sDataSpaceName, aArguments, mxContext), css::uno::UNO_QUERY); - - if (!mxPackageEncryption.is() && sDataSpaceName == "StrongEncryptionDataSpace") - { - readStrongEncryptionInfo(); - } } else { // Fallback for documents generated by LO: they sometimes do not have all // required by MS-OFFCRYPTO specification streams (0x6DataSpaces/DataSpaceMap and others) SAL_WARN("oox", "Encrypted package does not contain DataSpaceMap"); - readStrongEncryptionInfo(); + sDataSpaceName = "StrongEncryptionDataSpace"; } + uno::Sequence< uno::Any > aArguments; + mxPackageEncryption.set( + mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto." + sDataSpaceName, aArguments, mxContext), css::uno::UNO_QUERY); + if (!mxPackageEncryption.is()) { // we do not know how to decrypt this document @@ -210,7 +189,7 @@ bool DocumentDecryption::decrypt(const uno::Reference<io::XStream>& xDocumentStr return bResult; } -} // namespace core +} // namespace crypto } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/DocumentEncryption.cxx b/oox/source/crypto/DocumentEncryption.cxx index 70b7f2a3a4e9..026f767fafa0 100644 --- a/oox/source/crypto/DocumentEncryption.cxx +++ b/oox/source/crypto/DocumentEncryption.cxx @@ -16,10 +16,12 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/packages/XPackageEncryption.hpp> +#include <oox/helper/binaryoutputstream.hxx> #include <oox/ole/olestorage.hxx> +#include <sal/log.hxx> namespace oox { -namespace core { +namespace crypto { using namespace css::io; using namespace css::uno; @@ -43,7 +45,7 @@ DocumentEncryption::DocumentEncryption(const Reference< XComponentContext >& rxC rMediaEncData[i].Value >>= sCryptoType; if (sCryptoType == "Standard") - sCryptoType = "Standard2007Engine"; + sCryptoType = "StrongEncryptionDataSpace"; Sequence<Any> aArguments; mxPackageEncryption.set( @@ -96,7 +98,7 @@ bool DocumentEncryption::encrypt() return true; } -} // namespace core +} // namespace crypto } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/Standard2007Engine.cxx b/oox/source/crypto/Standard2007Engine.cxx index 9ddde339b1d5..f89b29f48ccb 100644 --- a/oox/source/crypto/Standard2007Engine.cxx +++ b/oox/source/crypto/Standard2007Engine.cxx @@ -10,10 +10,6 @@ #include <oox/crypto/Standard2007Engine.hxx> -#include <com/sun/star/io/XStream.hpp> -#include <com/sun/star/io/XSeekable.hpp> -#include <com/sun/star/io/SequenceInputStream.hpp> -#include <com/sun/star/io/XSequenceOutputStream.hpp> #include <oox/crypto/CryptTools.hxx> #include <oox/helper/binaryinputstream.hxx> #include <oox/helper/binaryoutputstream.hxx> @@ -21,20 +17,9 @@ #include <rtl/random.h> #include <comphelper/hash.hxx> -#include <comphelper/sequenceashashmap.hxx> - -using namespace css::io; -using namespace css::uno; namespace oox { -namespace core { - -extern "C" SAL_DLLPUBLIC_EXPORT XInterface* - com_sun_star_comp_oox_crypto_Standard2007_get_implementation( - XComponentContext* pCtx, Sequence<Any> const& /*arguments*/) -{ - return cppu::acquire(new Standard2007Engine(pCtx/*, arguments*/)); -} +namespace crypto { /* =========================================================================== */ /* Kudos to Caolan McNamara who provided the core decryption implementations. */ @@ -54,12 +39,6 @@ constexpr const sal_uInt32 AES128Size = 16; } // end anonymous namespace -Standard2007Engine::Standard2007Engine(const css::uno::Reference<css::uno::XComponentContext>& rxContext) - : mxContext(rxContext) -{ - -} - bool Standard2007Engine::generateVerifier() { // only support key of size 128 bit (16 byte) @@ -138,7 +117,7 @@ bool Standard2007Engine::calculateEncryptionKey(const OUString& rPassword) return true; } -sal_Bool Standard2007Engine::generateEncryptionKey(const OUString& password) +bool Standard2007Engine::generateEncryptionKey(const OUString& password) { mKey.clear(); /* @@ -180,12 +159,9 @@ sal_Bool Standard2007Engine::generateEncryptionKey(const OUString& password) return std::equal(hash.begin(), hash.end(), verifierHash.begin()); } -sal_Bool Standard2007Engine::decrypt(const css::uno::Reference<css::io::XInputStream>& rxInputStream, - css::uno::Reference<css::io::XOutputStream>& rxOutputStream) +bool Standard2007Engine::decrypt(BinaryXInputStream& aInputStream, + BinaryXOutputStream& aOutputStream) { - BinaryXInputStream aInputStream(rxInputStream, true); - BinaryXOutputStream aOutputStream(rxOutputStream, true); - sal_uInt32 totalSize = aInputStream.readuInt32(); // Document unencrypted size - 4 bytes aInputStream.skip(4); // Reserved 4 Bytes @@ -204,27 +180,15 @@ sal_Bool Standard2007Engine::decrypt(const css::uno::Reference<css::io::XInputSt aOutputStream.writeMemory(outputBuffer.data(), writeLength); remaining -= outputLength; } - - rxOutputStream->flush(); - return true; } -sal_Bool Standard2007Engine::checkDataIntegrity() +bool Standard2007Engine::checkDataIntegrity() { return true; } -css::uno::Sequence<css::beans::NamedValue> Standard2007Engine::createEncryptionData(const OUString& rPassword) -{ - comphelper::SequenceAsHashMap aEncryptionData; - aEncryptionData["OOXPassword"] <<= rPassword; - aEncryptionData["CryptoType"] <<= OUString("Standard2007Engine"); - - return aEncryptionData.getAsConstNamedValueList(); -} - -sal_Bool Standard2007Engine::setupEncryption(const css::uno::Sequence<css::beans::NamedValue>& rMediaEncData) +bool Standard2007Engine::setupEncryption(OUString const & password) { mInfo.header.flags = msfilter::ENCRYPTINFO_AES | msfilter::ENCRYPTINFO_CRYPTOAPI; mInfo.header.algId = msfilter::ENCRYPT_ALGO_AES128; @@ -238,17 +202,7 @@ sal_Bool Standard2007Engine::setupEncryption(const css::uno::Sequence<css::beans mKey.clear(); mKey.resize(keyLength, 0); - OUString sPassword; - for (int i = 0; i < rMediaEncData.getLength(); i++) - { - if (rMediaEncData[i].Name == "OOXPassword") - { - OUString sCryptoType; - rMediaEncData[i].Value >>= sPassword; - } - } - - if (!calculateEncryptionKey(sPassword)) + if (!calculateEncryptionKey(password)) return false; if (!generateVerifier()) @@ -257,13 +211,8 @@ sal_Bool Standard2007Engine::setupEncryption(const css::uno::Sequence<css::beans return true; } -css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptionInfo() +void Standard2007Engine::writeEncryptionInfo(BinaryXOutputStream& rStream) { - Reference<XOutputStream> aEncryptionInfoStream( - mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext), - UNO_QUERY); - BinaryXOutputStream rStream(aEncryptionInfoStream, false); - rStream.WriteUInt32(msfilter::VERSION_INFO_2007_FORMAT); sal_uInt32 cspNameSize = (lclCspName.getLength() * 2) + 2; @@ -279,25 +228,19 @@ css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptionInfo() rStream.WriteUInt16(0); rStream.writeMemory(&mInfo.verifier, sizeof(msfilter::EncryptionVerifierAES)); - - rStream.close(); - aEncryptionInfoStream->flush(); - - Reference<XSequenceOutputStream> aEncryptionInfoSequenceStream(aEncryptionInfoStream, UNO_QUERY); - return aEncryptionInfoSequenceStream->getWrittenBytes(); } -css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptedDocument(const css::uno::Reference<css::io::XInputStream> & rxInputStream) +void Standard2007Engine::encrypt(const css::uno::Reference<css::io::XInputStream> & rxInputStream, + css::uno::Reference<css::io::XOutputStream> & rxOutputStream, + sal_uInt32 nSize) { - Reference<XOutputStream> aOutputStream( - mxContext->getServiceManager()->createInstanceWithContext("com.sun.star.io.SequenceOutputStream", mxContext), - UNO_QUERY); - BinaryXOutputStream aBinaryOutputStream(aOutputStream, false); + if (mKey.empty()) + return; + BinaryXOutputStream aBinaryOutputStream(rxOutputStream, false); BinaryXInputStream aBinaryInputStream(rxInputStream, false); - Reference<XSeekable> xSeekable(rxInputStream, UNO_QUERY); - aBinaryOutputStream.WriteUInt32(xSeekable->getLength()); // size + aBinaryOutputStream.WriteUInt32(nSize); // size aBinaryOutputStream.WriteUInt32(0U); // reserved std::vector<sal_uInt8> inputBuffer(1024); @@ -317,43 +260,11 @@ css::uno::Sequence<sal_Int8> Standard2007Engine::writeEncryptedDocument(const cs outputLength = aEncryptor.update(outputBuffer, inputBuffer, inputLength); aBinaryOutputStream.writeMemory(outputBuffer.data(), outputLength); } - - Reference<XSequenceOutputStream> aSequenceStream(aOutputStream, UNO_QUERY); - return aSequenceStream->getWrittenBytes(); -} - -css::uno::Sequence<css::beans::NamedValue> Standard2007Engine::encrypt(const css::uno::Reference<css::io::XInputStream> & rxInputStream) -{ - if (mKey.empty()) - return css::uno::Sequence<css::beans::NamedValue>(); - - comphelper::SequenceAsHashMap aStreams; - - aStreams["EncryptedPackage"] <<= writeEncryptedDocument(rxInputStream); - aStreams["EncryptionInfo"] <<= writeEncryptionInfo(); - return aStreams.getAsConstNamedValueList(); -} - -css::uno::Reference<css::io::XInputStream> Standard2007Engine::getStream(const css::uno::Sequence<css::beans::NamedValue> & rStreams, const OUString sStreamName) -{ - for (const auto & aStream : rStreams) - { - if (aStream.Name == sStreamName) - { - css::uno::Sequence<sal_Int8> aSeq; - aStream.Value >>= aSeq; - Reference<XInputStream> aStream(css::io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq), UNO_QUERY_THROW); - return aStream; - } - } - return nullptr; } -sal_Bool Standard2007Engine::readEncryptionInfo(const css::uno::Sequence<css::beans::NamedValue>& aStreams) +bool Standard2007Engine::readEncryptionInfo(css::uno::Reference<css::io::XInputStream> & rxInputStream) { - Reference<css::io::XInputStream> rxInputStream = getStream(aStreams, "EncryptionInfo"); BinaryXInputStream aBinaryStream(rxInputStream, false); - aBinaryStream.readuInt32(); // Version mInfo.header.flags = aBinaryStream.readuInt32(); if (getFlag(mInfo.header.flags, msfilter::ENCRYPTINFO_EXTERNAL)) @@ -407,7 +318,7 @@ sal_Bool Standard2007Engine::readEncryptionInfo(const css::uno::Sequence<css::be return !aBinaryStream.isEof(); } -} // namespace core +} // namespace crypto } // namespace oox /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/crypto/StrongEncryptionDataSpace.cxx b/oox/source/crypto/StrongEncryptionDataSpace.cxx new file mode 100644 index 000000000000..cfcab3cd4a59 --- /dev/null +++ b/oox/source/crypto/StrongEncryptionDataSpace.cxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <oox/crypto/StrongEncryptionDataSpace.hxx> +#include <oox/crypto/AgileEngine.hxx> +#include <oox/crypto/Standard2007Engine.hxx> +#include <oox/helper/binaryoutputstream.hxx> +#include <oox/helper/binaryinputstream.hxx> +#include <com/sun/star/io/SequenceInputStream.hpp> +#include <com/sun/star/io/XSequenceOutputStream.hpp> + +#include <comphelper/sequenceashashmap.hxx> + +using namespace css; +using namespace css::beans; +using namespace css::io; +using namespace css::lang; +using namespace css::uno; + +namespace oox +{ +namespace crypto +{ +StrongEncryptionDataSpace::StrongEncryptionDataSpace(const Reference<XComponentContext>& rxContext) + : mxContext(rxContext) + , mCryptoEngine(new Standard2007Engine()) +{ +} + +sal_Bool StrongEncryptionDataSpace::generateEncryptionKey(const OUString& rPassword) +{ + if (!mCryptoEngine) + return false; + + return mCryptoEngine->generateEncryptionKey(rPassword); +} + +sal_Bool StrongEncryptionDataSpace::checkDataIntegrity() +{ + if (!mCryptoEngine) + return false; + + return mCryptoEngine->checkDataIntegrity(); +} + +sal_Bool StrongEncryptionDataSpace::decrypt(const Reference<XInputStream>& rxInputStream, + Reference<XOutputStream>& rxOutputStream) +{ + if (!mCryptoEngine) + return false; + + BinaryXInputStream aInputStream(rxInputStream, true); + BinaryXOutputStream aOutputStream(rxOutputStream, true); + + mCryptoEngine->decrypt(aInputStream, aOutputStream); + + rxOutputStream->flush(); + return true; +} + +Reference<XInputStream> StrongEncryptionDataSpace::getStream(const Sequence<NamedValue>& rStreams, + const OUString sStreamName) +{ + for (const auto& aStream : rStreams) + { + if (aStream.Name == sStreamName) + { + Sequence<sal_Int8> aSeq; + aStream.Value >>= aSeq; + Reference<XInputStream> aStream( + io::SequenceInputStream::createStreamFromSequence(mxContext, aSeq), + UNO_QUERY_THROW); + return aStream; + } + } + return nullptr; +} + +sal_Bool StrongEncryptionDataSpace::readEncryptionInfo(const Sequence<NamedValue>& aStreams) +{ + Reference<XInputStream> xEncryptionInfo = getStream(aStreams, "EncryptionInfo"); + if (!xEncryptionInfo.is()) + return false; + + BinaryXInputStream aBinaryInputStream(xEncryptionInfo, true); + sal_uInt32 aVersion = aBinaryInputStream.readuInt32(); + + Sequence<Any> aArguments; + + switch (aVersion) + { + case msfilter::VERSION_INFO_2007_FORMAT: + case msfilter::VERSION_INFO_2007_FORMAT_SP2: + mCryptoEngine.reset(new Standard2007Engine()); + break; + case msfilter::VERSION_INFO_AGILE: + mCryptoEngine.reset(new AgileEngine()); + break; + default: + break; + } + + if (!mCryptoEngine) + return false; + + return mCryptoEngine->readEncryptionInfo(xEncryptionInfo); +} + +sal_Bool StrongEncryptionDataSpace::setupEncryption(const Sequence<NamedValue>& rMediaEncData) +{ + if (!mCryptoEngine) + return false; + + OUString sPassword; + for (const auto& aParam : rMediaEncData) + { + if (aParam.Name == "OOXPassword") + { + aParam.Value >>= sPassword; + } + } + + return mCryptoEngine->setupEncryption(sPassword); +} + +Sequence<NamedValue> StrongEncryptionDataSpace::createEncryptionData(const OUString& rPassword) +{ + comphelper::SequenceAsHashMap aEncryptionData; + aEncryptionData["OOXPassword"] <<= rPassword; + aEncryptionData["CryptoType"] <<= OUString("StrongEncryptionDataSpace"); + + return aEncryptionData.getAsConstNamedValueList(); +} + +Sequence<NamedValue> +StrongEncryptionDataSpace::encrypt(const Reference<XInputStream>& rxInputStream) +{ + if (!mCryptoEngine) + return Sequence<NamedValue>(); + + Reference<XSeekable> xSeekable(rxInputStream, UNO_QUERY); + if (!xSeekable.is()) + return Sequence<NamedValue>(); + + sal_uInt32 aLength = xSeekable->getLength(); // check length of the stream + + Reference<XOutputStream> xOutputStream( + mxContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.io.SequenceOutputStream", mxContext), + UNO_QUERY); + + mCryptoEngine->encrypt(rxInputStream, xOutputStream, aLength); + + comphelper::SequenceAsHashMap aStreams; + + Reference<XSequenceOutputStream> xEncodedFileSequenceStream(xOutputStream, UNO_QUERY); + aStreams["EncryptedPackage"] <<= xEncodedFileSequenceStream->getWrittenBytes(); + + Reference<XOutputStream> aEncryptionInfoStream( + mxContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.io.SequenceOutputStream", mxContext), + UNO_QUERY); + BinaryXOutputStream rStream(aEncryptionInfoStream, false); + mCryptoEngine->writeEncryptionInfo(rStream); + aEncryptionInfoStream->flush(); + Reference<XSequenceOutputStream> aEncryptionInfoSequenceStream(aEncryptionInfoStream, + UNO_QUERY); + + aStreams["EncryptionInfo"] <<= aEncryptionInfoSequenceStream->getWrittenBytes(); + + return aStreams.getAsConstNamedValueList(); +} + +} // namespace crypto +} // namespace oox + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_comp_oox_crypto_StrongEncryptionDataSpace_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new oox::crypto::StrongEncryptionDataSpace(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/util/oox.component b/oox/util/oox.component index d7167545b2be..cf3a2d4b16f1 100644 --- a/oox/util/oox.component +++ b/oox/util/oox.component @@ -40,12 +40,8 @@ constructor="com_sun_star_comp_oox_ShapeContextHandler_get_implementation"> <service name="com.sun.star.xml.sax.FastShapeContextHandler"/> </implementation> - <implementation name="com.sun.star.comp.oox.crypto.Standard2007Engine" - constructor="com_sun_star_comp_oox_crypto_Standard2007_get_implementation"> - <service name="com.sun.star.packages.XPackageEncryption"/> - </implementation> - <implementation name="com.sun.star.comp.oox.crypto.AgileEngine" - constructor="com_sun_star_comp_oox_crypto_Agile_get_implementation"> + <implementation name="com.sun.star.comp.oox.crypto.StrongEncryptionDataSpace" + constructor="com_sun_star_comp_oox_crypto_StrongEncryptionDataSpace_get_implementation"> <service name="com.sun.star.packages.XPackageEncryption"/> </implementation> </component> commit b64ab30695c5e26d880192dbdde11a8c5ae9ef7f Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Thu Nov 21 21:11:02 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 oox: exception on password veryfy attempt is ending loop If we receive an exception on createEncryptionData() there is no reason to ask user for another password. Change-Id: I7fa0949c737af20396ae7958e0e80d97af7cfe10 diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx index 7e72d28482df..f59b15c56df9 100644 --- a/oox/source/core/filterdetect.cxx +++ b/oox/source/core/filterdetect.cxx @@ -265,8 +265,16 @@ PasswordVerifier::PasswordVerifier( DocumentDecryption& aDecryptor ) : comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OUString& rPassword, Sequence<NamedValue>& rEncryptionData ) { - if(mDecryptor.generateEncryptionKey(rPassword)) - rEncryptionData = mDecryptor.createEncryptionData(rPassword); + try + { + if (mDecryptor.generateEncryptionKey(rPassword)) + rEncryptionData = mDecryptor.createEncryptionData(rPassword); + } + catch (...) + { + // Any exception is a reason to abort + return comphelper::DocPasswordVerifierResult::Abort; + } return rEncryptionData.hasElements() ? comphelper::DocPasswordVerifierResult::OK : comphelper::DocPasswordVerifierResult::WrongPassword; } commit d505e72051d3e9a92e94c5c40a9bbb8bb3052dd5 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Mon Nov 18 11:26:23 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 package: ignore unknown encryption parameters. Do not throw an exception if there are encryption parameters, but they are not supported in current output format. Change-Id: I21e4cf2f73d7c218ab5444b2016e838695163ca3 Conflicts: package/source/zippackage/ZipPackage.cxx diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index 78627441b506..a66e3a63b22f 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -1646,11 +1646,6 @@ const uno::Sequence< sal_Int8 > ZipPackage::GetEncryptionKey() for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ ) if ( m_aStorageEncryptionKeys[nInd].Name == aNameToFind ) m_aStorageEncryptionKeys[nInd].Value >>= aResult; - - // empty keys are not allowed here - // so it is not important whether there is no key, or the key is empty, it is an error - if ( !aResult.hasElements() ) - throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" ); } else aResult = m_aEncryptionKey; commit 204b7d65f3cee79ec07d911d7d398bf4fc52be67 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Wed Nov 13 09:19:42 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:54 2019 +0100 ms doc: pass additional arguments to encryption service XPackageEncryption mplementation should distingush types of files fo possibility to encrypt them in a different way. So additional parameter is provided to resolve this issue. Change-Id: I3cdff6c6b85f2483138ad5ddba7799fb7bf8be95 diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index 2e4015e34569..463afe74b90a 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -261,7 +261,8 @@ static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument, if (sCryptoType.getLength()) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); - uno::Sequence<uno::Any> aArguments; + uno::Sequence<uno::Any> aArguments(1); + aArguments[0] = uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true))); xPackageEncryption.set( xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY); diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx index f2ec9038c7b1..1678a1f04451 100644 --- a/sd/source/filter/sdpptwrp.cxx +++ b/sd/source/filter/sdpptwrp.cxx @@ -268,7 +268,8 @@ bool SdPPTFilter::Export() if (sCryptoType.getLength()) { Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); - Sequence<Any> aArguments; + Sequence<Any> aArguments(1); + aArguments[0] = makeAny(NamedValue("Binary", makeAny(true))); xPackageEncryption.set( xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), UNO_QUERY); diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx index 04f770ea858c..c65fb7298aa3 100644 --- a/sw/source/filter/ww8/wrtww8.cxx +++ b/sw/source/filter/ww8/wrtww8.cxx @@ -3561,7 +3561,8 @@ ErrCode SwWW8Writer::WriteStorage() if (sCryptoType.getLength()) { uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); - uno::Sequence<uno::Any> aArguments; + uno::Sequence<uno::Any> aArguments(1); + aArguments[0] = uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true))); xPackageEncryption.set( xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY); commit 97ac37b02a80508a0ef4b35285d768dc06d50767 Author: Thorsten Behrens <thorsten.behr...@cib.de> AuthorDate: Wed Dec 4 13:34:57 2019 +0100 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:19:50 2019 +0100 Fixup Add document-level option for lock-downs Change-Id: I52dda76fd779e7b5afce6599b1d8deb25056fb9b diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx index 218dc2eab259..117a9f77346d 100644 --- a/sfx2/source/doc/sfxbasemodel.cxx +++ b/sfx2/source/doc/sfxbasemodel.cxx @@ -1061,48 +1061,41 @@ void SAL_CALL SfxBaseModel::setArgs(const Sequence<beans::PropertyValue>& aArgs) for (int i = 0; i < aArgs.getLength(); i++) { OUString sValue; - aArgs[i].Value >>= sValue; bool bValue; + aArgs[i].Value >>= sValue; + aArgs[i].Value >>= bValue; if (aArgs[i].Name == "SuggestedSaveAsName") { - rArg.Value >>= sValue; pMedium->GetItemSet()->Put(SfxStringItem(SID_SUGGESTEDSAVEASNAME, sValue)); } else if (aArgs[i].Name == "SuggestedSaveAsDir") { - rArg.Value >>= sValue; pMedium->GetItemSet()->Put(SfxStringItem(SID_SUGGESTEDSAVEASDIR, sValue)); } - else if (rArg.Name == "LockContentExtraction") + else if (aArgs[i].Name == "LockContentExtraction") { - rArg.Value >>= bValue; pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_CONTENT_EXTRACTION, bValue)); } - else if (rArg.Name == "LockExport") + else if (aArgs[i].Name == "LockExport") { - rArg.Value >>= bValue; pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_EXPORT, bValue)); } - else if (rArg.Name == "LockPrint") + else if (aArgs[i].Name == "LockPrint") { - rArg.Value >>= bValue; pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_PRINT, bValue)); } - else if (rArg.Name == "LockSave") + else if (aArgs[i].Name == "LockSave") { - rArg.Value >>= bValue; pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_SAVE, bValue)); } - else if (rArg.Name == "LockEditDoc") + else if (aArgs[i].Name == "LockEditDoc") { - rArg.Value >>= bValue; pMedium->GetItemSet()->Put(SfxBoolItem(SID_LOCK_EDITDOC, bValue)); } - else if (rArg.Name == "EncryptionData") + else if (aArgs[i].Name == "EncryptionData") { - rArg.Value >>= bValue; - pMedium->GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, rArg.Value)); + pMedium->GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, aArgs[i].Value)); } else { commit a52f2a82ca33d31ef7491f57bfa0a306a8235ed1 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 21:17:10 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:13:37 2019 +0100 sd: support for DRM encryption during saving to ppt Change-Id: Id82f8b3fa7ea045b00d7d81e2c9ce5e130c8060c diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx index bb42b9d4bc11..f2ec9038c7b1 100644 --- a/sd/source/filter/sdpptwrp.cxx +++ b/sd/source/filter/sdpptwrp.cxx @@ -19,17 +19,21 @@ #include <sfx2/docfile.hxx> #include <sfx2/docfilt.hxx> +#include <sfx2/frame.hxx> #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/sfxsids.hrc> using namespace ::com::sun::star::uno; @@ -219,8 +223,6 @@ bool SdPPTFilter::Export() if( mxModel.is() ) { - tools::SvRef<SotStorage> xStorRef = new SotStorage( mrMedium.GetOutStream(), false ); - #ifdef DISABLE_DYNLOADING ExportPPTPointer PPTExport = ExportPPT; #else @@ -228,7 +230,7 @@ bool SdPPTFilter::Export() SdFilter::GetLibrarySymbol(mrMedium.GetFilter()->GetUserData(), "ExportPPT")); #endif - if( PPTExport && xStorRef.is() ) + if( PPTExport) { sal_uInt32 nCnvrtFlags = 0; const SvtFilterOptions& rFilterOptions = SvtFilterOptions::Get(); @@ -252,8 +254,105 @@ bool SdPPTFilter::Export() aProperty.Value <<= mrMedium.GetBaseURL( true ); aProperties.push_back( aProperty ); - bRet = PPTExport( aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags ); - xStorRef->Commit(); + SvStream * pOutputStrm = mrMedium.GetOutStream(); + + Sequence< NamedValue > aEncryptionData; + Reference< css::packages::XPackageEncryption > xPackageEncryption; + const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mrMedium.GetItemSet(), SID_ENCRYPTIONDATA, false); + std::shared_ptr<SvStream> pMediaStrm; + if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData)) + { + ::comphelper::SequenceAsHashMap aHashData(aEncryptionData); + OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString()); + + if (sCryptoType.getLength()) + { + Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + Sequence<Any> aArguments; + xPackageEncryption.set( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), UNO_QUERY); + + if (xPackageEncryption.is()) + { + // We have an encryptor. Export document into memory stream and encrypt it later + pMediaStrm.reset(new SvMemoryStream()); + pOutputStrm = pMediaStrm.get(); + + // Temp removal of EncryptionData to avoid password protection triggering + mrMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA); + } + } + } + + tools::SvRef<SotStorage> xStorRef = new SotStorage(pOutputStrm, false); + + if (xStorRef.is()) + { + bRet = PPTExport(aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags); + xStorRef->Commit(); + + if (xPackageEncryption.is()) + { + // Perform DRM encryption + pOutputStrm->Seek(0); + + xPackageEncryption->setupEncryption(aEncryptionData); + + Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pOutputStrm, false)); + Sequence<NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream); + + tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(mrMedium.GetOutStream(), false); + for (const NamedValue & aStreamData : aStreams) + { + // To avoid long paths split and open substorages recursively + // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09 + SotStorage * pStorage = xEncryptedRootStrg.get(); + OUString sFileName; + sal_Int32 idx = 0; + do + { + OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx); + if (!sPathElem.isEmpty()) + { + if (idx < 0) + { + sFileName = sPathElem; + } + else + { + pStorage = pStorage->OpenSotStorage(sPathElem); + } + } + } while (pStorage && idx >= 0); + + if (!pStorage) + { + bRet = false; + break; + } + + SotStorageStream* pStream = pStorage->OpenSotStream(sFileName); + if (!pStream) + { + bRet = false; + break; + } + Sequence<sal_Int8> aStreamContent; + aStreamData.Value >>= aStreamContent; + size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength()); + if (nBytesWritten != (size_t)aStreamContent.getLength()) + { + bRet = false; + break; + } + } + xEncryptedRootStrg->Commit(); + + // Restore encryption data + mrMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData))); + } + } } } commit 0a9c0a330d7bebee358ee26207c798f437a0caa3 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 21:00:12 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:13:37 2019 +0100 sd: support of DRM encrypted ppt files reading Change-Id: Ib91538d53ee1f53a3cd14a44d47fd6f6136c0472 diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx index edc21c482d45..bb42b9d4bc11 100644 --- a/sd/source/filter/sdpptwrp.cxx +++ b/sd/source/filter/sdpptwrp.cxx @@ -23,6 +23,10 @@ #include <svx/svxerr.hxx> #include <unotools/fltrcfg.hxx> #include <sot/storage.hxx> +#include <comphelper/sequenceashashmap.hxx> + +#include <com/sun/star/packages/XPackageEncryption.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <sdpptwrp.hxx> #include <DrawDocShell.hxx> @@ -67,9 +71,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); + assert(rStream.is()); + + sal_Int32 nStreamSize = rStream->GetSize(); + Sequence< sal_Int8 > oData; + oData.realloc(nStreamSize); + sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); + assert(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; + } + + std::vector<OUString> aStreamsList; + comphelper::SequenceAsHashMap aStreamsData; + lcl_getListOfStreams(rStorage.get(), aStreamsData, OUString("")); + + 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.reset(new SvMemoryStream()); + + Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); + Reference<css::io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm.get())); + + 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 +178,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 ) { commit 94d4c5b2bee411a9307889ad1cf1c9f58fcb51f2 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 18:28:41 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:13:37 2019 +0100 calc: support for writing DRM encrypted xls files Change-Id: I5faf885cf494becca2838c6493413bcc56e91826 diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index 56adce29a061..2e4015e34569 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -24,7 +24,7 @@ #include <sot/exchange.hxx> #include <filter/msfilter/classids.hxx> #include <tools/globname.hxx> -#include <com/sun/star/packages/XPAckageEncryption.hpp> +#include <com/sun/star/packages/XPackageEncryption.hpp> #include <com/sun/star/ucb/ContentCreationException.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <unotools/streamwrap.hxx> @@ -248,6 +248,36 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument, SvStream* pMedStrm, bool bBiff8, rtl_TextEncoding eNach ) { + uno::Reference< packages::XPackageEncryption > xPackageEncryption; + uno::Sequence< beans::NamedValue > aEncryptionData; + const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(rMedium.GetItemSet(), SID_ENCRYPTIONDATA, false); + SvStream* pOriginalMediaStrm = pMedStrm; + std::shared_ptr<SvStream> pMediaStrm; + if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData)) + { + ::comphelper::SequenceAsHashMap aHashData(aEncryptionData); + OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString()); + + if (sCryptoType.getLength()) + { + uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + uno::Sequence<uno::Any> aArguments; + xPackageEncryption.set( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY); + + if (xPackageEncryption.is()) + { + // We have an encryptor. Export document into memory stream and encrypt it later + pMediaStrm.reset(new SvMemoryStream()); + pMedStrm = pMediaStrm.get(); + + // Temp removal of EncryptionData to avoid password protection triggering + rMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA); + } + } + } + // try to open an OLE storage tools::SvRef<SotStorage> xRootStrg = new SotStorage( pMedStrm, false ); if( xRootStrg->GetError() ) return SCERR_IMPORT_OPEN; @@ -296,6 +326,67 @@ static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument, xStrgStrm->Commit(); xRootStrg->Commit(); + if (xPackageEncryption.is()) + { + // Perform DRM encryption + pMedStrm->Seek(0); + + xPackageEncryption->setupEncryption(aEncryptionData); + + uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pMedStrm, false)); + uno::Sequence<beans::NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream); + + tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(pOriginalMediaStrm, false); + for (const beans::NamedValue & aStreamData : aStreams) + { + // To avoid long paths split and open substorages recursively + // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09 + SotStorage * pStorage = xEncryptedRootStrg.get(); + OUString sFileName; + sal_Int32 idx = 0; + do + { + OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx); + if (!sPathElem.isEmpty()) + { + if (idx < 0) + { + sFileName = sPathElem; + } + else + { + pStorage = pStorage->OpenSotStorage(sPathElem); + } + } + } while (pStorage && idx >= 0); + + if (!pStorage) + { + eRet = ERRCODE_IO_GENERAL; + break; + } + + SotStorageStream* pStream = pStorage->OpenSotStream(sFileName); + if (!pStream) + { + eRet = ERRCODE_IO_GENERAL; + break; + } + uno::Sequence<sal_Int8> aStreamContent; + aStreamData.Value >>= aStreamContent; + size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength()); + if (nBytesWritten != aStreamContent.getLength()) + { + eRet = ERRCODE_IO_CANTWRITE; + break; + } + } + xEncryptedRootStrg->Commit(); + + // Restore encryption data + rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData))); + } + return eRet; } commit 31fdf71cb23c9c5c843ef88815a437fbaa979429 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 17:53:30 2019 +0300 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Wed Dec 4 17:13:37 2019 +0100 calc: support for reading DRM encrypted xls files DRM encryption is implemented as an optional service, so just use it when available. Change-Id: Ie580e5c12c48ccf99f9a932b1c66eb35866b7ef4 diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index ca87efc2988c..56adce29a061 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -24,7 +24,9 @@ #include <sot/exchange.hxx> #include <filter/msfilter/classids.hxx> #include <tools/globname.hxx> +#include <com/sun/star/packages/XPAckageEncryption.hpp> #include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <unotools/streamwrap.hxx> #include <osl/diagnose.h> #include <filter.hxx> @@ -32,6 +34,8 @@ #include <xistream.hxx> #include <xltools.hxx> #include <docoptio.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/processfactory.hxx> #include <docsh.hxx> #include <scerrors.hxx> @@ -42,6 +46,99 @@ #include <memory> +using namespace css; + +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); + assert(rStream.is()); + + sal_Int32 nStreamSize = rStream->GetSize(); + uno::Sequence< sal_Int8 > oData; + oData.realloc(nStreamSize); + sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); + assert(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 + 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 aNewStorage; + } + + std::vector<OUString> aStreamsList; + comphelper::SequenceAsHashMap aStreamsData; + lcl_getListOfStreams(rStorage.get(), aStreamsData, OUString("")); + + try { + uno::Sequence<beans::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.reset(new SvMemoryStream()); + + uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits