diff options
Diffstat (limited to 'comphelper/source/misc/docpasswordhelper.cxx')
-rw-r--r-- | comphelper/source/misc/docpasswordhelper.cxx | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/comphelper/source/misc/docpasswordhelper.cxx b/comphelper/source/misc/docpasswordhelper.cxx index 3f470520fbf5..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> @@ -426,8 +427,28 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( bool* pbIsDefaultPassword ) { css::uno::Sequence< css::beans::NamedValue > aEncData; + 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; @@ -439,8 +460,12 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( if( !aIt->isEmpty() ) { eResult = rVerifier.verifyPassword( *aIt, aEncData ); - if( pbIsDefaultPassword ) - *pbIsDefaultPassword = eResult == DocPasswordVerifierResult::OK; + if (eResult == DocPasswordVerifierResult::OK) + { + aPassword = *aIt; + if (pbIsDefaultPassword) + *pbIsDefaultPassword = true; + } } } } @@ -448,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 ) @@ -460,7 +485,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) @@ -476,6 +505,8 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( { if( !pRequest->getPassword().isEmpty() ) eResult = rVerifier.verifyPassword( pRequest->getPassword(), aEncData ); + if (eResult == DocPasswordVerifierResult::OK) + aPassword = pRequest->getPassword(); } else { @@ -488,6 +519,41 @@ 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)); + } + + 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 >(); } |