summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2022-03-21 20:58:34 +0000
committerThorsten Behrens <thorsten.behrens@allotropia.de>2022-10-30 00:49:32 +0200
commit893dde23ecd2a15daad825e603b479407ff5df18 (patch)
treebdde9a9fd4ee86309a4cc7b3401f44d717988380
parent5139365bbeee3689079585acc0dedae9bc7022c0 (diff)
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. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132080 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com> (cherry picked from commit e890f54dbac57f3ab5acf4fbd31222095d3e8ab6) svl: fix crash if user cancels/closes master password dialog (regression from d7ba5614d90381d68f880ca7e7c5ef8bbb1b1c43) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133932 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit bbb8617ece6d946957c2eb96287081029bce530f) Change-Id: I3174c37a5891bfc849984e0ec5c2c392b9c6e7b1 (cherry picked from commit 7e35d53f51bb89ed3cea5f946214afb7d81e1b1e)
-rw-r--r--officecfg/registry/schema/org/openoffice/Office/Common.xcs6
-rw-r--r--svl/source/passwordcontainer/passwordcontainer.cxx47
-rw-r--r--svl/source/passwordcontainer/passwordcontainer.hxx6
-rw-r--r--uui/source/iahndl-authentication.cxx5
4 files changed, 60 insertions, 4 deletions
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index b0c738194f25..c1890efc4599 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -911,6 +911,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 5c59f976d8ec..12dcd19dae77 100644
--- a/svl/source/passwordcontainer/passwordcontainer.cxx
+++ b/svl/source/passwordcontainer/passwordcontainer.cxx
@@ -17,6 +17,8 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <sal/config.h>
+#include <sal/log.hxx>
#include "passwordcontainer.hxx"
@@ -262,6 +264,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 )
{
@@ -294,15 +313,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 );
@@ -803,6 +824,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 )
{
@@ -841,6 +874,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] )
{
@@ -1045,6 +1081,13 @@ 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 878eeb8fadaf..87798ca045ee 100644
--- a/svl/source/passwordcontainer/passwordcontainer.hxx
+++ b/svl/source/passwordcontainer/passwordcontainer.hxx
@@ -170,6 +170,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;
@@ -198,6 +202,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 bAcceptEnmpty = false );
void setUseStorage( bool bUse );
diff --git a/uui/source/iahndl-authentication.cxx b/uui/source/iahndl-authentication.cxx
index 114cf8b87563..d557fb75cbd5 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());
}