diff options
Diffstat (limited to 'debian/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch')
-rw-r--r-- | debian/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/debian/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch b/debian/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch new file mode 100644 index 000000000..d56b5ea04 --- /dev/null +++ b/debian/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch @@ -0,0 +1,183 @@ +From 780c42cdd8006dc60e281be2fe6566f101e909bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com> +Date: Mon, 21 Mar 2022 20:58:34 +0000 +Subject: [PATCH 2/4] CVE-2022-26307 make hash encoding match decoding + +Seeing as old versions of the hash may be in the users config, add a +StorageVersion field to the office config Passwords section which +defaults to 0 to indicate the old hash is in use. + +Try the old varient when StorageVersion is 0. When a new encoded master +password it set write StorageVersion of 1 to indicate a new hash is in +use and use the new style when StorageVersion is 1. + +Change-Id: I3174c37a5891bfc849984e0ec5c2c392b9c6e7b1 +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132080 +Tested-by: Jenkins +Reviewed-by: Stephan Bergmann <sbergman@redhat.com> +(cherry picked from commit e890f54dbac57f3ab5acf4fbd31222095d3e8ab6) +--- + .../schema/org/openoffice/Office/Common.xcs | 6 +++ + .../passwordcontainer/passwordcontainer.cxx | 45 +++++++++++++++++-- + .../passwordcontainer/passwordcontainer.hxx | 6 +++ + uui/source/iahndl-authentication.cxx | 5 ++- + 4 files changed, 57 insertions(+), 5 deletions(-) + +diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +index 9097c23c3c6a..922efc33cca7 100644 +--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs ++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +@@ -942,6 +942,12 @@ + </info> + <value>false</value> + </prop> ++ <prop oor:name="StorageVersion" oor:type="xs:int" oor:nillable="false"> ++ <info> ++ <desc>Specifies what version of encoding scheme the password container uses.</desc> ++ </info> ++ <value>0</value> ++ </prop> + <prop oor:name="HasMaster" oor:type="xs:boolean" oor:nillable="false"> + <info> + <desc>Specifies if there is a valid master password.</desc> +diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx +index 51fb129cddb1..b674844f91d3 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.cxx ++++ b/svl/source/passwordcontainer/passwordcontainer.cxx +@@ -17,7 +17,6 @@ + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +- + #include "passwordcontainer.hxx" + + #include <cppuhelper/factory.hxx> +@@ -259,6 +258,23 @@ bool StorageItem::useStorage() + return aResult; + } + ++sal_Int32 StorageItem::getStorageVersion() ++{ ++ Sequence<OUString> aNodeNames { "StorageVersion" }; ++ ++ Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); ++ ++ if( aPropertyValues.getLength() != aNodeNames.getLength() ) ++ { ++ OSL_FAIL( "Problems during reading" ); ++ return 0; ++ } ++ ++ sal_Int32 nResult = 0; ++ aPropertyValues[0] >>= nResult; ++ ++ return nResult; ++} + + bool StorageItem::getEncodedMP( OUString& aResult ) + { +@@ -291,15 +307,17 @@ bool StorageItem::getEncodedMP( OUString& aResult ) + + void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty ) + { +- Sequence< OUString > sendNames(2); +- Sequence< uno::Any > sendVals(2); ++ Sequence< OUString > sendNames(3); ++ Sequence< uno::Any > sendVals(3); + + sendNames[0] = "HasMaster"; + sendNames[1] = "Master"; ++ sendNames[2] = "StorageVersion"; + + bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty ); + sendVals[0] <<= bHasMaster; + sendVals[1] <<= aEncoded; ++ sendVals[2] <<= nCurrentStorageVersion; + + ConfigItem::SetModified(); + ConfigItem::PutProperties( sendNames, sendVals ); +@@ -800,6 +818,18 @@ OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, + return aResult; + } + ++// Mangle the key to match an old bug ++static OUString ReencodeAsOldHash(const OUString& rPass) ++{ ++ OUStringBuffer aBuffer; ++ for (int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ++ind) ++ { ++ unsigned char i = static_cast<char>(rPass.copy(ind * 2, 2).toUInt32(16)); ++ aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4))); ++ aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15))); ++ } ++ return aBuffer.makeStringAndClear(); ++} + + OUString const & PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) + { +@@ -838,6 +868,9 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac + } + else + { ++ if (m_pStorageFile->getStorageVersion() == 0) ++ aPass = ReencodeAsOldHash(aPass); ++ + std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass, aRMode ) ); + if( aRM.empty() || aPass != aRM[0] ) + { +@@ -1042,6 +1075,12 @@ sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::R + + do { + aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); ++ ++ if (!aPass.isEmpty() && m_pStorageFile->getStorageVersion() == 0) ++ { ++ aPass = ReencodeAsOldHash(aPass); ++ } ++ + bResult = ( !aPass.isEmpty() && aPass == m_aMasterPasswd ); + aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification + } while( !bResult && !aPass.isEmpty() ); +diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx b/svl/source/passwordcontainer/passwordcontainer.hxx +index 46ffec888602..bf43b5903602 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.hxx ++++ b/svl/source/passwordcontainer/passwordcontainer.hxx +@@ -168,6 +168,10 @@ public: + typedef ::std::pair< const OUString, ::std::vector< NamePassRecord > > PairUrlRecord; + typedef ::std::map< OUString, ::std::vector< NamePassRecord > > PassMap; + ++// org.openoffice.Office.Common/Passwords/StorageVersion bump if details of ++// how password details are saved changes. Enables migration from previous ++// schemes. ++constexpr sal_Int32 nCurrentStorageVersion = 1; + + class PasswordContainer; + +@@ -195,6 +195,8 @@ + void remove( const OUString& url, const OUString& rec ); + void clear(); + ++ sal_Int32 getStorageVersion(); ++ + bool getEncodedMP( OUString& aResult ); + void setEncodedMP( const OUString& aResult, bool bAcceptEnmpty = false ); + void setUseStorage( bool bUse ); +diff --git a/uui/source/iahndl-authentication.cxx b/uui/source/iahndl-authentication.cxx +index ad975d3f9ae7..951f0b8a1c6b 100644 +--- a/uui/source/iahndl-authentication.cxx ++++ b/uui/source/iahndl-authentication.cxx +@@ -436,8 +436,9 @@ executeMasterPasswordDialog( + OUStringBuffer aBuffer; + for (sal_uInt8 i : aKey) + { +- aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4))); +- aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15))); ++ // match PasswordContainer::DecodePasswords aMasterPasswd.copy(index * 2, 2).toUInt32(16)); ++ aBuffer.append(OUString::number(i >> 4, 16)); ++ aBuffer.append(OUString::number(i & 15, 16)); + } + rInfo.SetPassword(aBuffer.makeStringAndClear()); + } +-- +2.37.1 + |