summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comphelper/source/misc/docpasswordhelper.cxx42
-rw-r--r--package/source/xstor/owriteablestream.cxx8
-rw-r--r--package/source/xstor/owriteablestream.hxx3
-rw-r--r--package/source/xstor/xstorage.cxx2
-rw-r--r--sfx2/source/appl/appopen.cxx16
5 files changed, 64 insertions, 7 deletions
diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx
index 949b53d38fbf..919e9d8b11e4 100644
--- a/comphelper/source/misc/docpasswordhelper.cxx
+++ b/comphelper/source/misc/docpasswordhelper.cxx
@@ -19,6 +19,7 @@
#include "comphelper/docpasswordhelper.hxx"
+#include <comphelper/storagehelper.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/storagehelper.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
@@ -352,6 +353,25 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
OUString aPassword;
DocPasswordVerifierResult eResult = DocPasswordVerifierResult_WRONG_PASSWORD;
+ sal_Int32 nMediaEncDataCount = rMediaEncData.getLength();
+
+ // tdf#93389: if the document is being restored from autorecovery, we need to add encryption
+ // data also for real document type.
+ // TODO: get real filter name here (from CheckPasswd_Impl), to only add necessary data
+ bool bForSalvage = false;
+ if (nMediaEncDataCount)
+ {
+ for (auto& val : rMediaEncData)
+ {
+ if (val.Name == "ForSalvage")
+ {
+ --nMediaEncDataCount; // don't consider this element below
+ val.Value >>= bForSalvage;
+ break;
+ }
+ }
+ }
+
// first, try provided default passwords
if( pbIsDefaultPassword )
*pbIsDefaultPassword = false;
@@ -376,7 +396,7 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
// try media encryption data (skip, if result is OK or ABORT)
if( eResult == DocPasswordVerifierResult_WRONG_PASSWORD )
{
- if( rMediaEncData.getLength() > 0 )
+ if (nMediaEncDataCount)
{
eResult = rVerifier.verifyEncryptionData( rMediaEncData );
if( eResult == DocPasswordVerifierResult_OK )
@@ -440,6 +460,26 @@ Sequence< sal_Int8 > DocPasswordHelper::GetXLHashAsSequence(
if (!bHasEncryptionData)
aEncData = comphelper::concatSequences(
aEncData, OStorageHelper::CreatePackageEncryptionData(aPassword));
+
+ if (bForSalvage)
+ {
+ // TODO: add individual methods for different target filter, and only call what's needed
+
+ // 1. Prepare binary MS formats encryption data
+ auto aUniqueID = GenerateRandomByteSequence(16);
+ auto aEnc97Key = GenerateStd97Key(aPassword.getStr(), aUniqueID);
+ // 2. Add MS binary and OOXML encryption data to result
+ uno::Sequence< beans::NamedValue > aContainer(3);
+ aContainer[0].Name = "STD97EncryptionKey";
+ aContainer[0].Value <<= aEnc97Key;
+ aContainer[1].Name = "STD97UniqueID";
+ aContainer[1].Value <<= aUniqueID;
+ aContainer[2].Name = "OOXPassword";
+ aContainer[2].Value <<= aPassword;
+
+ aEncData = comphelper::concatSequences(
+ aEncData, aContainer);
+ }
}
return (eResult == DocPasswordVerifierResult_OK) ? aEncData : uno::Sequence< beans::NamedValue >();
diff --git a/package/source/xstor/owriteablestream.cxx b/package/source/xstor/owriteablestream.cxx
index c3a25910cbe5..85571898fb8f 100644
--- a/package/source/xstor/owriteablestream.cxx
+++ b/package/source/xstor/owriteablestream.cxx
@@ -57,9 +57,11 @@ using namespace ::com::sun::star;
namespace package
{
-bool PackageEncryptionDatasEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 )
+bool PackageEncryptionDataLessOrEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 )
{
- bool bResult = ( aHash1.size() && aHash1.size() == aHash2.size() );
+ // tdf#93389: aHash2 may contain more than in aHash1, if it contains also data for other package
+ // formats (as in case of autorecovery)
+ bool bResult = !aHash1.empty() && aHash1.size() <= aHash2.size();
for ( ::comphelper::SequenceAsHashMap::const_iterator aIter = aHash1.begin();
bResult && aIter != aHash1.end();
++aIter )
@@ -1207,7 +1209,7 @@ uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMod
if ( m_bHasCachedEncryptionData )
{
- if ( !::package::PackageEncryptionDatasEqual( m_aEncryptionData, aEncryptionData ) )
+ if ( !::package::PackageEncryptionDataLessOrEqual( m_aEncryptionData, aEncryptionData ) )
throw packages::WrongPasswordException();
// the correct key must be set already
diff --git a/package/source/xstor/owriteablestream.hxx b/package/source/xstor/owriteablestream.hxx
index 22fcb3f83d06..edd6827366ac 100644
--- a/package/source/xstor/owriteablestream.hxx
+++ b/package/source/xstor/owriteablestream.hxx
@@ -67,7 +67,8 @@ namespace cppu {
namespace package {
void StaticAddLog( const OUString& aMessage );
- bool PackageEncryptionDatasEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 );
+ // all data in aHash1 is contained in aHash2
+ bool PackageEncryptionDataLessOrEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 );
}
struct WSInternalData_Impl
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index 8775561dde77..ad1dc1433335 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -914,7 +914,7 @@ void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
AddLog( OSL_LOG_PREFIX "No Encryption" );
}
- if ( bHasCommonEncryptionData && ::package::PackageEncryptionDatasEqual( pElement->m_pStream->GetCachedEncryptionData(), aCommonEncryptionData ) )
+ if (bHasCommonEncryptionData && ::package::PackageEncryptionDataLessOrEqual(pElement->m_pStream->GetCachedEncryptionData(), aCommonEncryptionData))
{
// If the stream can be opened with the common storage password
// it must be stored with the common storage password as well
diff --git a/sfx2/source/appl/appopen.cxx b/sfx2/source/appl/appopen.cxx
index e8e23c5d1a4c..cc72c1dcec92 100644
--- a/sfx2/source/appl/appopen.cxx
+++ b/sfx2/source/appl/appopen.cxx
@@ -49,6 +49,7 @@
#include <comphelper/sequenceasvector.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/string.hxx>
+#include <comphelper/sequence.hxx>
#include <comphelper/synchronousdispatch.hxx>
#include <vcl/wrkwin.hxx>
@@ -270,8 +271,21 @@ sal_uInt32 CheckPasswd_Impl
if ( pEncryptionDataItem )
pEncryptionDataItem->GetValue() >>= aEncryptionData;
- OUString aDocumentName = INetURLObject( pFile->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET );
+ // tdf#93389: if recoverying a document, encryption data should contain
+ // entries for the real filter, not only for recovery ODF, to keep it
+ // encrypted. Pass this in encryption data.
+ // TODO: pass here the real filter (from AutoRecovery::implts_openDocs)
+ // to marshal this to requestAndVerifyDocPassword
+ if (pSet->GetItemState(SID_DOC_SALVAGE, false) == SFX_ITEM_SET)
+ {
+ uno::Sequence< beans::NamedValue > aContainer(1);
+ aContainer[0].Name = "ForSalvage";
+ aContainer[0].Value <<= true;
+ aEncryptionData = comphelper::concatSequences(
+ aEncryptionData, aContainer);
+ }
+ OUString aDocumentName = INetURLObject( pFile->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET );
SfxDocPasswordVerifier aVerifier( xStorage );
aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
aVerifier, aEncryptionData, aPassword, xInteractionHandler, aDocumentName, comphelper::DocPasswordRequestType_STANDARD );