diff options
author | Caolán McNamara <caolanm@redhat.com> | 2022-03-21 20:58:34 +0000 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2022-04-01 23:26:31 +0200 |
commit | 0ee75556a6c10384bba6b980476ec533c669d575 (patch) | |
tree | 378399441976e08d21dffe60e152fa9eadef7839 | |
parent | Bump version to 21.06.24.1 (diff) | |
download | core-0ee75556a6c10384bba6b980476ec533c669d575.tar.gz core-0ee75556a6c10384bba6b980476ec533c669d575.zip |
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>
4 files changed, 54 insertions, 11 deletions
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index e1df1a0d8ffd..d7ccca5ae705 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..0970d1f9b6dc 100644 --- a/svl/source/passwordcontainer/passwordcontainer.cxx +++ b/svl/source/passwordcontainer/passwordcontainer.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/log.hxx> #include "passwordcontainer.hxx" @@ -259,6 +260,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,18 +309,11 @@ bool StorageItem::getEncodedMP( OUString& aResult ) void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty ) { - Sequence< OUString > sendNames(2); - Sequence< uno::Any > sendVals(2); - - sendNames[0] = "HasMaster"; - sendNames[1] = "Master"; - bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty ); - sendVals[0] <<= bHasMaster; - sendVals[1] <<= aEncoded; ConfigItem::SetModified(); - ConfigItem::PutProperties( sendNames, sendVals ); + ConfigItem::PutProperties( { "HasMaster", "Master", "StorageVersion" }, + { uno::Any(bHasMaster), uno::Any(aEncoded), uno::Any(nCurrentStorageVersion) } ); hasEncoded = bHasMaster; mEncoded = aEncoded; @@ -800,6 +811,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 +861,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 +1068,10 @@ sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::R do { aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); + + if (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; @@ -196,6 +200,8 @@ public: void remove( const OUString& url, const OUString& rec ); void clear(); + sal_Int32 getStorageVersion(); + bool getEncodedMP( OUString& aResult ); void setEncodedMP( const OUString& aResult, bool bAcceptEmpty = 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()); } |