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, 65 insertions, 6 deletions
diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx
index f75997cfe440..1a4f29755c36 100644
--- a/comphelper/source/misc/docpasswordhelper.cxx
+++ b/comphelper/source/misc/docpasswordhelper.cxx
@@ -25,6 +25,7 @@
#include <comphelper/storagehelper.hxx>
#include <comphelper/hash.hxx>
#include <comphelper/base64.hxx>
+#include <comphelper/propertysequence.hxx>
#include <comphelper/sequence.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/task/XInteractionHandler.hpp>
@@ -429,6 +430,25 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
OUString aPassword;
DocPasswordVerifierResult eResult = DocPasswordVerifierResult::WrongPassword;
+ 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;
@@ -453,7 +473,7 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
// try media encryption data (skip, if result is OK or ABORT)
if( eResult == DocPasswordVerifierResult::WrongPassword )
{
- if( rMediaEncData.getLength() > 0 )
+ if (nMediaEncDataCount)
{
eResult = rVerifier.verifyEncryptionData( rMediaEncData );
if( eResult == DocPasswordVerifierResult::OK )
@@ -512,6 +532,26 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
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 2f49e497dd47..19e28e9dcb33 100644
--- a/package/source/xstor/owriteablestream.cxx
+++ b/package/source/xstor/owriteablestream.cxx
@@ -79,9 +79,11 @@ struct WSInternalData_Impl
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.empty() && 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 )
@@ -1160,7 +1162,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 e3eeaf09d4fd..5501d6a4df47 100644
--- a/package/source/xstor/owriteablestream.hxx
+++ b/package/source/xstor/owriteablestream.hxx
@@ -55,7 +55,8 @@ namespace com { namespace sun { namespace star { namespace uno {
} } } }
namespace package {
- 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 0a43a07869f9..1725b1627762 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -857,7 +857,7 @@ void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
SAL_INFO("package.xstor", "No Encryption: " << rNoEncryptionException);
}
- if (bHasCommonEncryptionData && ::package::PackageEncryptionDatasEqual(pElement->m_xStream->GetCachedEncryptionData(), aCommonEncryptionData))
+ if (bHasCommonEncryptionData && ::package::PackageEncryptionDataLessOrEqual(pElement->m_xStream->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 47ba55e34947..bea5aba9fe4d 100644
--- a/sfx2/source/appl/appopen.cxx
+++ b/sfx2/source/appl/appopen.cxx
@@ -44,6 +44,7 @@
#include <comphelper/processfactory.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/string.hxx>
+#include <comphelper/sequence.hxx>
#include <comphelper/synchronousdispatch.hxx>
#include <vcl/wrkwin.hxx>
@@ -240,6 +241,21 @@ ErrCode CheckPasswd_Impl
if ( !aEncryptionData.hasElements() && aGpgProperties.hasElements() )
aEncryptionData = ::comphelper::DocPasswordHelper::decryptGpgSession(aGpgProperties);
+ // 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) == SfxItemState::SET)
+ {
+ uno::Sequence< beans::NamedValue > aContainer(1);
+ aContainer[0].Name = "ForSalvage";
+ aContainer[0].Value <<= true;
+
+ aEncryptionData = comphelper::concatSequences(
+ aEncryptionData, aContainer);
+ }
+
SfxDocPasswordVerifier aVerifier( xStorage );
aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
aVerifier, aEncryptionData, aPassword, xInteractionHandler, pFile->GetOrigURL(), comphelper::DocPasswordRequestType::Standard );