diff options
Diffstat (limited to 'svl/source/passwordcontainer/passwordcontainer.cxx')
-rw-r--r-- | svl/source/passwordcontainer/passwordcontainer.cxx | 122 |
1 files changed, 85 insertions, 37 deletions
diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx index f3b1132de7a5..7f4ae8543764 100644 --- a/svl/source/passwordcontainer/passwordcontainer.cxx +++ b/svl/source/passwordcontainer/passwordcontainer.cxx @@ -185,15 +185,18 @@ PassMap StorageItem::getInfo() Sequence< OUString > aNodeNames = ConfigItem::GetNodeNames( "Store" ); sal_Int32 aNodeCount = aNodeNames.getLength(); - Sequence< OUString > aPropNames( aNodeCount ); + Sequence< OUString > aPropNames( aNodeCount * 2); std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.begin(), [](const OUString& rName) -> OUString { return "Store/Passwordstorage['" + rName + "']/Password"; }); + std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.getArray() + aNodeCount, + [](const OUString& rName) -> OUString { + return "Store/Passwordstorage['" + rName + "']/InitializationVector"; }); Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames ); - if( aPropertyValues.getLength() != aNodeCount ) + if( aPropertyValues.getLength() != aNodeCount * 2) { OSL_FAIL( "Problems during reading" ); return aResult; @@ -209,14 +212,16 @@ PassMap StorageItem::getInfo() OUString aName = aUrlUsr[1]; OUString aEPasswd; + OUString aIV; aPropertyValues[aNodeInd] >>= aEPasswd; + aPropertyValues[aNodeInd + aNodeCount] >>= aIV; PassMap::iterator aIter = aResult.find( aUrl ); if( aIter != aResult.end() ) - aIter->second.emplace_back( aName, aEPasswd ); + aIter->second.emplace_back( aName, aEPasswd, aIV ); else { - NamePassRecord aNewRecord( aName, aEPasswd ); + NamePassRecord aNewRecord( aName, aEPasswd, aIV ); std::vector< NamePassRecord > listToAdd( 1, aNewRecord ); aResult.insert( PairUrlRecord( aUrl, listToAdd ) ); @@ -273,17 +278,19 @@ sal_Int32 StorageItem::getStorageVersion() return nResult; } -bool StorageItem::getEncodedMP( OUString& aResult ) +bool StorageItem::getEncodedMP( OUString& aResult, OUString& aResultIV ) { if( hasEncoded ) { aResult = mEncoded; + aResultIV = mEncodedIV; return true; } - Sequence< OUString > aNodeNames( 2 ); + Sequence< OUString > aNodeNames( 3 ); aNodeNames[0] = "HasMaster"; aNodeNames[1] = "Master"; + aNodeNames[2] = "MasterInitializationVector"; Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); @@ -295,23 +302,27 @@ bool StorageItem::getEncodedMP( OUString& aResult ) aPropertyValues[0] >>= hasEncoded; aPropertyValues[1] >>= mEncoded; + aPropertyValues[2] >>= mEncodedIV; aResult = mEncoded; + aResultIV = mEncodedIV; return hasEncoded; } -void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty ) +void StorageItem::setEncodedMP( const OUString& aEncoded, const OUString& aEncodedIV, bool bAcceptEmpty ) { bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty ); ConfigItem::SetModified(); - ConfigItem::PutProperties( { "HasMaster", "Master", "StorageVersion" }, - { uno::Any(bHasMaster), uno::Any(aEncoded), uno::Any(nCurrentStorageVersion) } ); + ConfigItem::PutProperties( { "HasMaster", "Master", "MasterInitializationVector", "StorageVersion" }, + { uno::Any(bHasMaster), uno::Any(aEncoded), + uno::Any(aEncodedIV), uno::Any(nCurrentStorageVersion) } ); hasEncoded = bHasMaster; mEncoded = aEncoded; + mEncodedIV = aEncodedIV; } @@ -337,11 +348,13 @@ void StorageItem::update( const OUString& aURL, const NamePassRecord& aRecord ) return; } - Sequence< beans::PropertyValue > sendSeq(1); + Sequence< beans::PropertyValue > sendSeq(2); - sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() } ) + "']/Password"; + sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() } ) + "']/InitializationVector"; + sendSeq[0].Value <<= aRecord.GetPersistentIV(); - sendSeq[0].Value <<= aRecord.GetPersPasswords(); + sendSeq[1].Name = "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() } ) + "']/Password"; + sendSeq[1].Value <<= aRecord.GetPersPasswords(); ConfigItem::SetModified(); ConfigItem::SetSetProperties( "Store", sendSeq ); @@ -402,7 +415,7 @@ void SAL_CALL PasswordContainer::disposing( const EventObject& ) } } -std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aMasterPasswd, css::task::PasswordRequestMode mode ) +std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPasswd, css::task::PasswordRequestMode mode ) { if( !aMasterPasswd.isEmpty() ) { @@ -417,9 +430,16 @@ std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLin for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) code[ ind ] = static_cast<char>(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16)); + unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0}; + if (!aIV.isEmpty()) + { + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + iv[ ind ] = static_cast<char>(aIV.copy( ind*2, 2 ).toUInt32(16)); + } + rtlCipherError result = rtl_cipher_init ( aDecoder, rtl_Cipher_DirectionDecode, - code, RTL_DIGEST_LENGTH_MD5, nullptr, 0 ); + code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 ); if( result == rtl_Cipher_E_None ) { @@ -452,7 +472,7 @@ std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLin "Can't decode!", css::uno::Reference<css::uno::XInterface>(), mode); } -OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, const OUString& aMasterPasswd ) +OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPasswd) { if( !aMasterPasswd.isEmpty() ) { @@ -469,9 +489,16 @@ OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) code[ ind ] = static_cast<char>(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16)); + unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0}; + if (!aIV.isEmpty()) + { + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + iv[ ind ] = static_cast<char>(aIV.copy( ind*2, 2 ).toUInt32(16)); + } + rtlCipherError result = rtl_cipher_init ( aEncoder, rtl_Cipher_DirectionEncode, - code, RTL_DIGEST_LENGTH_MD5, nullptr, 0 ); + code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 ); if( result == rtl_Cipher_E_None ) { @@ -539,7 +566,7 @@ void PasswordContainer::UpdateVector( const OUString& aURL, std::vector< NamePas if( aRecord.HasPasswords( PERSISTENT_RECORD ) ) { - aNPIter.SetPersPasswords( aRecord.GetPersPasswords() ); + aNPIter.SetPersPasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV() ); if( writeFile ) { @@ -572,7 +599,8 @@ UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, b { try { - ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ); + ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV(), + GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ); aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() ); } catch( NoMasterException& ) @@ -617,6 +645,19 @@ void SAL_CALL PasswordContainer::addPersistent( const OUString& Url, const OUStr PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler ); } +OUString PasswordContainer::createIV() +{ + rtlRandomPool randomPool = mRandomPool.get(); + unsigned char iv[RTL_DIGEST_LENGTH_MD5]; + rtl_random_getBytes(randomPool, iv, RTL_DIGEST_LENGTH_MD5); + OUStringBuffer aBuffer; + for (sal_uInt8 i : iv) + { + aBuffer.append(OUString::number(i >> 4, 16)); + aBuffer.append(OUString::number(i & 15, 16)); + } + return aBuffer.makeStringAndClear(); +} void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) { @@ -624,7 +665,11 @@ void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserNam ::std::vector< OUString > aStorePass = comphelper::sequenceToContainer< std::vector<OUString> >( Passwords ); if( Mode == PERSISTENT_RECORD ) - aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) ); + { + OUString sIV = createIV(); + OUString sEncodedPasswords = EncodePasswords( aStorePass, sIV, GetMasterPassword( aHandler ) ); + aRecord.SetPersPasswords( sEncodedPasswords, sIV ); + } else if( Mode == MEMORY_RECORD ) aRecord.SetMemPasswords( aStorePass ); else @@ -814,10 +859,10 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac if( m_aMasterPasswd.isEmpty() && aHandler.is() ) { - OUString aEncodedMP; + OUString aEncodedMP, aEncodedMPIV; bool bDefaultPassword = false; - if( !m_pStorageFile->getEncodedMP( aEncodedMP ) ) + if( !m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) aRMode = PasswordRequestMode_PASSWORD_CREATE; else if ( aEncodedMP.isEmpty() ) { @@ -839,14 +884,15 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac m_aMasterPasswd = aPass; std::vector< OUString > aMaster( 1, m_aMasterPasswd ); - m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); + OUString sIV = createIV(); + m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, sIV, m_aMasterPasswd ), sIV ); } else { if (m_pStorageFile->getStorageVersion() == 0) aPass = ReencodeAsOldHash(aPass); - std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass, aRMode ) ); + std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aEncodedMPIV, aPass, aRMode ) ); if( aRM.empty() || aPass != aRM[0] ) { bAskAgain = true; @@ -1003,7 +1049,8 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere { sal_Int32 oldLen = aUsers.getLength(); aUsers.realloc( oldLen + 1 ); - aUsers[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersPasswords(), GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) ); + aUsers[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersPasswords(), aNP.GetPersistentIV(), + GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) ); } if( aUsers.hasElements() ) @@ -1020,12 +1067,12 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) { bool bResult = false; - OUString aEncodedMP; + OUString aEncodedMP, aEncodedMPIV; uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; ::osl::MutexGuard aGuard( mMutex ); // the method should fail if there is no master password - if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ) + if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) { if ( aEncodedMP.isEmpty() ) { @@ -1091,8 +1138,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< bool bCanChangePassword = true; // if there is already a stored master password it should be entered by the user before the change happen - OUString aEncodedMP; - if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP ) ) + OUString aEncodedMP, aEncodedMPIV; + if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); if ( bCanChangePassword ) @@ -1111,7 +1158,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< // store the new master password m_aMasterPasswd = aPass; std::vector< OUString > aMaster( 1, m_aMasterPasswd ); - m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); + OUString aIV = createIV(); + m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, aIV, m_aMasterPasswd ), aIV ); // store all the entries with the new password for ( const auto& rURL : aPersistent ) @@ -1136,7 +1184,7 @@ void SAL_CALL PasswordContainer::removeMasterPassword() if ( m_pStorageFile ) { m_aMasterPasswd.clear(); - m_pStorageFile->setEncodedMP( OUString() ); // let the master password be removed from configuration + m_pStorageFile->setEncodedMP( OUString(), OUString() ); // let the master password be removed from configuration } } @@ -1147,8 +1195,8 @@ sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( ) if ( !m_pStorageFile ) throw uno::RuntimeException(); - OUString aEncodedMP; - return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ); + OUString aEncodedMP, aEncodedMPIV; + return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ); } sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( sal_Bool bAllow ) @@ -1195,8 +1243,8 @@ sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Refere bool bCanChangePassword = true; // if there is already a stored nondefault master password it should be entered by the user before the change happen - OUString aEncodedMP; - if( m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.isEmpty() ) + OUString aEncodedMP, aEncodedMPIV; + if( m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) && !aEncodedMP.isEmpty() ) bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); if ( bCanChangePassword ) @@ -1213,7 +1261,7 @@ sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Refere // store the empty string to flag the default master password m_aMasterPasswd = aPass; - m_pStorageFile->setEncodedMP( OUString(), true ); + m_pStorageFile->setEncodedMP( OUString(), OUString(), true ); // store all the entries with the new password for ( const auto& rURL : aPersistent ) @@ -1237,8 +1285,8 @@ sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed() if ( !m_pStorageFile ) throw uno::RuntimeException(); - OUString aEncodedMP; - return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.isEmpty() ); + OUString aEncodedMP, aEncodedMPIV; + return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) && aEncodedMP.isEmpty() ); } |