Hi,
[ redoing all the information for better clarity in the bugreport ]
[ Reason ]
1) It seems the evolution adress book is broken since 2015 due to a
evolution change. Apparently noone noticed until 2021, where I
backported the patch but then actually forgot to request a stable update
2) Croatia will join the Eurozone on 2023-01-01. I think we should
prepare.
TODO: After (or shortly before) 2023-01-01 we then can do a point
release update to switch the default...
3) CVE-2021-25636 was no-DSA for bullseye but given we do an update
anyway we can just include it
4) I just talked with Moritz and CVE-2022-2630{5,6,7} are also no-DSA.
While we are at it we can fix it too here
[ Impact ]
for 1) it stays broken.
for 2) EUR isn't supported in .hr locale
for 3) and 4) stays vulnerable (though it's minor)
[ Tests ]
None, ttbomk.
[ Risks ]
for 2) trivial, and doesn't yet affect the default
for 1) it is a bigger patch but upstream since 2021. No regression known
and if it should regress, it can't get more broken than "broken".
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[ ] the issue is verified as fixed in unstable
(2) is not yet fixed in unstable, that will happen with the upload of
7.4.0 rc2 (or someting later) to it
[ Changes ]
See above. I just added the verbatim upstream commits. (Made to apply
and build for the CVE-2022-2630{5,6,7} fixes)
Debdiff attached.
[ Other info ]
As said, for 2) we need a new update to switch the default later.
Regards,
Rene
diff --git a/changelog b/changelog
index bdd1d149..ea05cdd3 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,19 @@
+libreoffice (1:7.0.4-4+deb11u2) stable; urgency=medium
+
+ * debian/patches/fix-e_book_client_connect_direct_sync-sig.diff:
+ as name says; from libreoffice-7-2 branch
+ * debian/patches/hrk-euro.diff: add EUR to .hr i18n;
+ add HRK<->EUR conversion rate to Calc and the Euro Wizard
+ * debian/patches/b0404f80577de9ff69e58390c6f6ef949fdb0139.patch: fix
+ CVE-2021-25636
+ * debian/patches/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch,
+ debian/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch
+ debian/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch
+ debian/patches/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch:
+ fix CVE-2022-2630{5,6,7}
+
+ -- Rene Engelhard <r...@debian.org> Tue, 26 Jul 2022 13:19:49 +0200
+
libreoffice (1:7.0.4-4+deb11u1) bullseye-security; urgency=high
* backport fixes from libreoffice-7-0 branch:
diff --git a/patches/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch b/patches/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch
new file mode 100644
index 00000000..e02b110f
--- /dev/null
+++ b/patches/0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch
@@ -0,0 +1,63 @@
+From 77f30ada1156ca1e1357776fea8e9dc113f6898d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caol...@redhat.com>
+Date: Thu, 3 Mar 2022 14:22:37 +0000
+Subject: [PATCH 1/4] CVE-2022-26305 compare authors using Thumbprint
+
+Change-Id: I338f58eb07cbf0a3d13a7dafdaddac09252a8546
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130929
+Tested-by: Jenkins
+Reviewed-by: Miklos Vajna <vmik...@collabora.com>
+(cherry picked from commit 65442205b5b274ad309308162f150f8d41648f72)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130866
+Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
+(cherry picked from commit a7aaa78acea4c1d51283c2fce54ff9f5339026f8)
+---
+ .../component/documentdigitalsignatures.cxx | 23 +++++++++++++++----
+ 1 file changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx
+index b9066ea92cac..5a21c8421bec 100644
+--- a/xmlsecurity/source/component/documentdigitalsignatures.cxx
++++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
+@@ -19,9 +19,10 @@
+
+ #include <resourcemanager.hxx>
+
+-#include <digitalsignaturesdialog.hxx>
++#include <certificate.hxx>
+ #include <certificatechooser.hxx>
+ #include <certificateviewer.hxx>
++#include <digitalsignaturesdialog.hxx>
+ #include <macrosecurity.hxx>
+ #include <biginteger.hxx>
+ #include <strings.hrc>
+@@ -666,9 +667,23 @@ sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
+ Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors();
+
+ return std::any_of(aTrustedAuthors.begin(), aTrustedAuthors.end(),
+- [&xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) {
+- return xmlsecurity::EqualDistinguishedNames(rAuthor[0], xAuthor->getIssuerName())
+- && ( rAuthor[1] == sSerialNum );
++ [this, &xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) {
++ if (!xmlsecurity::EqualDistinguishedNames(rAuthor[0], xAuthor->getIssuerName()))
++ return false;
++ if (rAuthor[1] != sSerialNum)
++ return false;
++
++ DocumentSignatureManager aSignatureManager(mxCtx, {});
++ if (!aSignatureManager.init())
++ return false;
++ uno::Reference<css::security::XCertificate> xCert = aSignatureManager.getSecurityEnvironment()->createCertificateFromAscii(rAuthor[2]);
++
++ auto pAuthor = dynamic_cast<xmlsecurity::Certificate*>(xAuthor.get());
++ auto pCert = dynamic_cast<xmlsecurity::Certificate*>(xCert.get());
++ if (pAuthor && pCert)
++ return pCert->getSHA256Thumbprint() == pAuthor->getSHA256Thumbprint();
++
++ return xCert->getSHA1Thumbprint() == xAuthor->getSHA1Thumbprint();
+ });
+ }
+
+--
+2.37.1
+
diff --git a/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch b/patches/0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch
new file mode 100644
index 00000000..d56b5ea0
--- /dev/null
+++ b/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?= <caol...@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 <sberg...@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
+
diff --git a/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch b/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch
new file mode 100644
index 00000000..b65b3530
--- /dev/null
+++ b/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch
@@ -0,0 +1,583 @@
+From e809625c2ca9f0c026aab9b5c2d13ced628c13e9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caol...@redhat.com>
+Date: Tue, 22 Mar 2022 17:22:22 +0000
+Subject: [PATCH 3/4] CVE-2022-26306 add Initialization Vectors to password
+ storage
+
+old ones default to the current all zero case and continue to work
+as before
+
+Change-Id: I6fe3b02fafcce1b5e7133e77e76a5118177d77af
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131974
+Tested-by: Jenkins
+Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
+(cherry picked from commit 192fa1e3bfc6269f2ebb91716471485a56074aea)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132306
+Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
+(cherry picked from commit ab77587ec300f5c30084471000663c46ddf25dad)
+---
+ .../schema/org/openoffice/Office/Common.xcs | 10 ++
+ .../passwordcontainer/passwordcontainer.cxx | 127 ++++++++++++------
+ .../passwordcontainer/passwordcontainer.hxx | 63 +++++++--
+ 3 files changed, 151 insertions(+), 49 deletions(-)
+
+diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+index 922efc33cca7..8d87d00d5369 100644
+--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+@@ -27,6 +27,11 @@
+ <info>
+ <desc>Contains a container for passwords.</desc>
+ </info>
++ <prop oor:name="InitializationVector" oor:type="xs:string">
++ <info>
++ <desc>Contains an initialization vector for the password encryption.</desc>
++ </info>
++ </prop>
+ <prop oor:name="Password" oor:type="xs:string" oor:localized="false">
+ <info>
+ <desc>Contains a password encoded with the master password.</desc>
+@@ -954,6 +959,11 @@
+ </info>
+ <value>false</value>
+ </prop>
++ <prop oor:name="MasterInitializationVector" oor:type="xs:string">
++ <info>
++ <desc>Contains an initialization vector for the master password encryption.</desc>
++ </info>
++ </prop>
+ <prop oor:name="Master" oor:type="xs:string" oor:nillable="false">
+ <info>
+ <desc>Contains the master password encrypted by itself.</desc>
+diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx
+index b674844f91d3..ef79470a2cb6 100644
+--- a/svl/source/passwordcontainer/passwordcontainer.cxx
++++ b/svl/source/passwordcontainer/passwordcontainer.cxx
+@@ -181,15 +181,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;
+@@ -205,14 +208,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 ) );
+@@ -276,17 +281,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 );
+
+@@ -298,32 +305,37 @@ 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 )
+ {
+- Sequence< OUString > sendNames(3);
+- Sequence< uno::Any > sendVals(3);
++ Sequence< OUString > sendNames(4);
++ Sequence< uno::Any > sendVals(4);
+
+ sendNames[0] = "HasMaster";
+ sendNames[1] = "Master";
+- sendNames[2] = "StorageVersion";
++ sendNames[2] = "MasterInitializationVector";
++ sendNames[3] = "StorageVersion";
+
+ bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty );
+ sendVals[0] <<= bHasMaster;
+ sendVals[1] <<= aEncoded;
+- sendVals[2] <<= nCurrentStorageVersion;
++ sendVals[2] <<= aEncodedIV;
++ sendVals[3] <<= nCurrentStorageVersion;
+
+ ConfigItem::SetModified();
+ ConfigItem::PutProperties( sendNames, sendVals );
+
+ hasEncoded = bHasMaster;
+ mEncoded = aEncoded;
++ mEncodedIV = aEncodedIV;
+ }
+
+
+@@ -359,11 +371,13 @@ void StorageItem::update( const OUString& aURL, const NamePassRecord& aRecord )
+ forIndex.push_back( aURL );
+ forIndex.push_back( aRecord.GetUserName() );
+
+- Sequence< beans::PropertyValue > sendSeq(1);
++ Sequence< beans::PropertyValue > sendSeq(2);
+
+- sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/Password";
++ sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/InitializationVector";
++ sendSeq[0].Value <<= aRecord.GetPersistentIV();
+
+- sendSeq[0].Value <<= aRecord.GetPersPasswords();
++ sendSeq[1].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/Password";
++ sendSeq[1].Value <<= aRecord.GetPersPasswords();
+
+ ConfigItem::SetModified();
+ ConfigItem::SetSetProperties( "Store", sendSeq );
+@@ -424,7 +438,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() )
+ {
+@@ -439,9 +453,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 )
+ {
+@@ -474,7 +495,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() )
+ {
+@@ -491,9 +512,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 )
+ {
+@@ -561,7 +589,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 )
+ {
+@@ -594,7 +622,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& )
+@@ -639,6 +668,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 )
+ {
+@@ -646,7 +688,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
+@@ -839,10 +885,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() )
+ {
+@@ -864,14 +910,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;
+@@ -1028,7 +1075,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() )
+@@ -1045,12 +1093,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() )
+ {
+@@ -1118,8 +1166,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 )
+@@ -1138,7 +1186,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 )
+@@ -1163,7 +1212,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
+ }
+ }
+
+@@ -1174,8 +1223,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 )
+@@ -1222,8 +1271,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 )
+@@ -1240,7 +1289,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 )
+@@ -1264,8 +1313,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() );
+ }
+
+
+diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx b/svl/source/passwordcontainer/passwordcontainer.hxx
+index bf43b5903602..0454437b9dc2 100644
+--- a/svl/source/passwordcontainer/passwordcontainer.hxx
++++ b/svl/source/passwordcontainer/passwordcontainer.hxx
+@@ -34,6 +34,7 @@
+ #include <unotools/configitem.hxx>
+ #include <ucbhelper/interactionrequest.hxx>
+
++#include <rtl/random.h>
+ #include <rtl/ref.hxx>
+ #include <osl/mutex.hxx>
+
+@@ -52,11 +53,12 @@ class NamePassRecord
+ ::std::vector< OUString > m_aMemPass;
+
+ // persistent passwords are encrypted in one string
+- bool m_bHasPersPass;
++ bool m_bHasPersPass;
+ OUString m_aPersPass;
++ OUString m_aPersistentIV;
+
+ void InitArrays( bool bHasMemoryList, const ::std::vector< OUString >& aMemoryList,
+- bool bHasPersistentList, const OUString& aPersistentList )
++ bool bHasPersistentList, const OUString& aPersistentList, const OUString& aPersistentIV )
+ {
+ m_bHasMemPass = bHasMemoryList;
+ if ( bHasMemoryList )
+@@ -64,7 +66,10 @@ class NamePassRecord
+
+ m_bHasPersPass = bHasPersistentList;
+ if ( bHasPersistentList )
++ {
+ m_aPersPass = aPersistentList;
++ m_aPersistentIV = aPersistentIV;
++ }
+ }
+
+ public:
+@@ -76,11 +81,12 @@ public:
+ {
+ }
+
+- NamePassRecord( const OUString& aName, const OUString& aPersistentList )
++ NamePassRecord( const OUString& aName, const OUString& aPersistentList, const OUString& aPersistentIV )
+ : m_aName( aName )
+ , m_bHasMemPass( false )
+ , m_bHasPersPass( true )
+ , m_aPersPass( aPersistentList )
++ , m_aPersistentIV( aPersistentIV )
+ {
+ }
+
+@@ -89,7 +95,8 @@ public:
+ , m_bHasMemPass( false )
+ , m_bHasPersPass( false )
+ {
+- InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass );
++ InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass,
++ aRecord.m_bHasPersPass, aRecord.m_aPersPass, aRecord.m_aPersistentIV );
+ }
+
+ NamePassRecord& operator=( const NamePassRecord& aRecord )
+@@ -100,7 +107,9 @@ public:
+
+ m_aMemPass.clear();
+ m_aPersPass.clear();
+- InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass );
++ m_aPersistentIV.clear();
++ InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass,
++ aRecord.m_bHasPersPass, aRecord.m_aPersPass, aRecord.m_aPersistentIV );
+ }
+ return *this;
+ }
+@@ -136,15 +145,24 @@ public:
+ return OUString();
+ }
+
++ OUString GetPersistentIV() const
++ {
++ if ( m_bHasPersPass )
++ return m_aPersistentIV;
++
++ return OUString();
++ }
++
+ void SetMemPasswords( const ::std::vector< OUString >& aMemList )
+ {
+ m_aMemPass = aMemList;
+ m_bHasMemPass = true;
+ }
+
+- void SetPersPasswords( const OUString& aPersList )
++ void SetPersPasswords( const OUString& aPersList, const OUString& aPersIV )
+ {
+ m_aPersPass = aPersList;
++ m_aPersistentIV = aPersIV;
+ m_bHasPersPass = true;
+ }
+
+@@ -159,6 +177,7 @@ public:
+ {
+ m_bHasPersPass = false;
+ m_aPersPass.clear();
++ m_aPersistentIV.clear();
+ }
+ }
+
+@@ -182,6 +201,7 @@ private:
+ PasswordContainer* mainCont;
+ bool hasEncoded;
+ OUString mEncoded;
++ OUString mEncodedIV;
+
+ virtual void ImplCommit() override;
+
+@@ -201,8 +201,8 @@
+
+ sal_Int32 getStorageVersion();
+
+- bool getEncodedMP( OUString& aResult );
+- void setEncodedMP( const OUString& aResult, bool bAcceptEnmpty = false );
++ bool getEncodedMP( OUString& aResult, OUString& aResultIV );
++ void setEncodedMP( const OUString& aResult, const OUString& aResultIV, bool bAcceptEmpty = false );
+ void setUseStorage( bool bUse );
+ bool useStorage();
+
+@@ -224,6 +244,29 @@ private:
+ css::uno::Reference< css::lang::XComponent > mComponent;
+ SysCredentialsConfig mUrlContainer;
+
++ class RandomPool
++ {
++ private:
++ rtlRandomPool m_aRandomPool;
++ public:
++ RandomPool() : m_aRandomPool(rtl_random_createPool())
++ {
++ }
++ rtlRandomPool get()
++ {
++ return m_aRandomPool;
++ }
++ ~RandomPool()
++ {
++ // Clean up random pool memory
++ rtl_random_destroyPool(m_aRandomPool);
++ }
++ };
++
++ RandomPool mRandomPool;
++
++ OUString createIV();
++
+ /// @throws css::uno::RuntimeException
+ css::uno::Sequence< css::task::UserRecord > CopyToUserRecordSequence(
+ const ::std::vector< NamePassRecord >& original,
+@@ -274,10 +317,10 @@ css::task::UrlRecord find(
+ const css::uno::Reference< css::task::XInteractionHandler >& Handler );
+
+ /// @throws css::uno::RuntimeException
+- static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aMasterPassword, css::task::PasswordRequestMode mode );
++ static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPassword, css::task::PasswordRequestMode mode );
+
+ /// @throws css::uno::RuntimeException
+- static OUString EncodePasswords(const std::vector< OUString >& lines, const OUString& aMasterPassword );
++ static OUString EncodePasswords(const std::vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPassword );
+
+ public:
+ PasswordContainer( const css::uno::Reference< css::lang::XMultiServiceFactory >& );
+--
+2.37.1
+
diff --git a/patches/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch b/patches/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch
new file mode 100644
index 00000000..fd02eb7b
--- /dev/null
+++ b/patches/0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch
@@ -0,0 +1,117 @@
+From 4cfd591942e4cfd3efc416bfac8e46e3580d37ba Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caol...@redhat.com>
+Date: Wed, 23 Mar 2022 13:03:30 +0000
+Subject: add infobar to prompt to refresh to replace old format
+
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131976
+Tested-by: Jenkins
+Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
+(cherry picked from commit bbd196ff82bda9f66b4ba32a412f10cefe6da60e)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132307
+Reviewed-by: Sophie Gautier <so...@libreoffice.org>
+Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
+(cherry picked from commit c5d01b11db3c83cb4a89d3b388d78e20dd3990b5)
+
+Change-Id: Id99cbf2b50a4ebf289dae6fc67e22e20afcda35b
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133906
+Tested-by: Michael Stahl <michael.st...@allotropia.de>
+Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
+---
+ include/sfx2/strings.hrc | 2 ++
+ include/sfx2/viewfrm.hxx | 1 +
+ sfx2/source/view/viewfrm.cxx | 40 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 43 insertions(+)
+
+diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc
+index 1f21f0a0f186..1db36e733c0c 100644
+--- a/include/sfx2/strings.hrc
++++ b/include/sfx2/strings.hrc
+@@ -297,6 +297,8 @@
+ #define STR_SIGNATURE_NOTVALIDATED_PARTIAL_OK NC_("STR_SIGNATURE_NOTVALIDATED_PARTIAL_OK", "The certificate could not be validated and the document is only partially signed.")
+ #define STR_SIGNATURE_OK NC_("STR_SIGNATURE_OK", "This document is digitally signed and the signature is valid.")
+ #define STR_SIGNATURE_SHOW NC_("STR_SIGNATURE_SHOW", "Show Signatures")
++#define STR_REFRESH_MASTER_PASSWORD NC_("STR_REFRESH_MASTER_PASSWORD", "The master password is stored in an outdated format, you should refresh it")
++#define STR_REFRESH_PASSWORD NC_("STR_REFRESH_PASSWORD", "Refresh Password")
+
+ #define STR_CLOSE_PANE NC_("STR_CLOSE_PANE", "Close Pane")
+ #define STR_SFX_DOCK NC_("STR_SFX_DOCK", "Dock")
+diff --git a/include/sfx2/viewfrm.hxx b/include/sfx2/viewfrm.hxx
+index fe336ba5f091..cc6a7dae7047 100644
+--- a/include/sfx2/viewfrm.hxx
++++ b/include/sfx2/viewfrm.hxx
+@@ -61,6 +61,7 @@ protected:
+ DECL_LINK(WhatsNewHandler, Button*, void);
+ DECL_LINK(SwitchReadOnlyHandler, Button*, void);
+ DECL_LINK(SignDocumentHandler, Button*, void);
++ DECL_DLLPRIVATE_LINK(RefreshMasterPasswordHdl, Button*, void);
+ SAL_DLLPRIVATE void KillDispatcher_Impl();
+
+ virtual ~SfxViewFrame() override;
+diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
+index 5a64599e5894..86e7d51bbfea 100644
+--- a/sfx2/source/view/viewfrm.cxx
++++ b/sfx2/source/view/viewfrm.cxx
+@@ -32,6 +32,7 @@
+ #include <com/sun/star/frame/XLoadable.hpp>
+ #include <com/sun/star/frame/XLayoutManager.hpp>
+ #include <com/sun/star/frame/XComponentLoader.hpp>
++#include <com/sun/star/task/PasswordContainer.hpp>
+ #include <officecfg/Office/Common.hxx>
+ #include <officecfg/Setup.hxx>
+ #include <toolkit/helper/vclunohelper.hxx>
+@@ -1390,6 +1391,24 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+ batch->commit();
+ }
+
++ if (officecfg::Office::Common::Passwords::HasMaster::get() &&
++ officecfg::Office::Common::Passwords::StorageVersion::get() == 0)
++ {
++ // master password stored in deprecated format
++ VclPtr<SfxInfoBarWindow> pOldMasterPasswordInfoBar =
++ AppendInfoBar("oldmasterpassword", "",
++ SfxResId(STR_REFRESH_MASTER_PASSWORD), InfobarType::DANGER, false);
++ if (pOldMasterPasswordInfoBar)
++ {
++ VclPtrInstance<PushButton> const xBtn(&GetWindow());
++ xBtn->SetText(SfxResId(STR_REFRESH_PASSWORD));
++ xBtn->SetSizePixel(xBtn->GetOptimalSize());
++ xBtn->SetClickHdl(LINK(this,
++ SfxViewFrame, RefreshMasterPasswordHdl));
++ pOldMasterPasswordInfoBar->addButton(xBtn);
++ }
++ }
++
+ // read-only infobar if necessary
+ const SfxViewShell *pVSh;
+ const SfxShell *pFSh;
+@@ -1565,6 +1584,27 @@ IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, Button*, void)
+ GetDispatcher()->Execute(SID_SIGNATURE);
+ }
+
++IMPL_LINK_NOARG(SfxViewFrame, RefreshMasterPasswordHdl, Button*, void)
++{
++ bool bChanged = false;
++ try
++ {
++ Reference< task::XPasswordContainer2 > xMasterPasswd(
++ task::PasswordContainer::create(comphelper::getProcessComponentContext()));
++
++ css::uno::Reference<css::frame::XFrame> xFrame = GetFrame().GetFrameInterface();
++ css::uno::Reference<css::awt::XWindow> xContainerWindow = xFrame->getContainerWindow();
++
++ uno::Reference<task::XInteractionHandler> xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(),
++ xContainerWindow));
++ bChanged = xMasterPasswd->changeMasterPassword(xTmpHandler);
++ }
++ catch (const Exception&)
++ {}
++ if (bChanged)
++ RemoveInfoBar(u"oldmasterpassword");
++}
++
+ void SfxViewFrame::Construct_Impl( SfxObjectShell *pObjSh )
+ {
+ m_pImpl->bResizeInToOut = true;
+--
+cgit v1.2.1
+
diff --git a/patches/b0404f80577de9ff69e58390c6f6ef949fdb0139.patch b/patches/b0404f80577de9ff69e58390c6f6ef949fdb0139.patch
new file mode 100644
index 00000000..15af1368
--- /dev/null
+++ b/patches/b0404f80577de9ff69e58390c6f6ef949fdb0139.patch
@@ -0,0 +1,63 @@
+From b0404f80577de9ff69e58390c6f6ef949fdb0139 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caol...@redhat.com>
+Date: Mon, 20 Dec 2021 17:05:44 +0000
+Subject: [PATCH] only use X509Data
+
+Change-Id: I52e6588f5fac04bb26d77c1f3af470db73e41f72
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127193
+Tested-by: Jenkins
+Reviewed-by: Miklos Vajna <vmik...@collabora.com>
+(cherry picked from commit be446d81e07b5499152efeca6ca23034e51ea5ff)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127178
+Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>
+---
+ xmlsecurity/inc/xmlsec-wrapper.h | 4 ++++
+ .../source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx | 4 ++++
+ xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx | 4 ++++
+ 3 files changed, 12 insertions(+)
+
+diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h
+index e4048de94bf2a..cc149379c36be 100644
+--- a/xmlsecurity/inc/xmlsec-wrapper.h
++++ b/xmlsecurity/inc/xmlsec-wrapper.h
+@@ -43,6 +43,10 @@
+ #include <xmlsec/nss/app.h>
+ #include <xmlsec/nss/crypto.h>
+ #include <xmlsec/nss/pkikeys.h>
++#include <xmlsec/nss/x509.h>
++#endif
++#ifdef XMLSEC_CRYPTO_MSCRYPTO
++#include <xmlsec/mscng/x509.h>
+ #endif
+
+ #endif
+diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
+index d9b8b1eace680..824139464fbb8 100644
+--- a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
++++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
+@@ -233,6 +233,10 @@ SAL_CALL XMLSignature_MSCryptImpl::validate(
+ // We do certificate verification ourselves.
+ pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+
++ // limit possible key data to valid X509 certificates only, no KeyValues
++ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0)
++ throw RuntimeException("failed to limit allowed key data");
++
+ //Verify signature
+ //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0)
+ //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if
+diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
+index b41d754f74072..fde4b747e9322 100644
+--- a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
++++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
+@@ -247,6 +247,10 @@ SAL_CALL XMLSignature_NssImpl::validate(
+ // We do certificate verification ourselves.
+ pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+
++ // limit possible key data to valid X509 certificates only, no KeyValues
++ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecNssKeyDataX509GetKlass()) < 0)
++ throw RuntimeException("failed to limit allowed key data");
++
+ //Verify signature
+ int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode );
+
diff --git a/patches/fix-e_book_client_connect_direct_sync-sig.diff b/patches/fix-e_book_client_connect_direct_sync-sig.diff
new file mode 100644
index 00000000..7aef915e
--- /dev/null
+++ b/patches/fix-e_book_client_connect_direct_sync-sig.diff
@@ -0,0 +1,417 @@
+From 3b9210195b8d2ac9861a1e607455ff9d16eb68fd Mon Sep 17 00:00:00 2001
+From: Julien Nabet <serval2...@yahoo.fr>
+Date: Wed, 15 Dec 2021 22:45:47 +0100
+Subject: [PATCH] tdf#137101: fix e_book_client_connect_direct_sync signature
+ in Evolution
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+since it changed in 2015, see all details from tdf#137101
+Thank you to krumelmonster for having spotted this!
+
++ some cleanup to remove all eds_check_version calls
+and dependencies
+
+Change-Id: Iaf2437f8f5c04ab9674a380dac1dfb16ec8c7201
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126898
+Tested-by: Jenkins
+Tested-by: Caolán McNamara <caol...@redhat.com>
+Reviewed-by: Caolán McNamara <caol...@redhat.com>
+(cherry picked from commit 0661c796c767802c114441ad9a17fd0979d72ef4)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126920
+---
+ connectivity/source/drivers/evoab2/EApi.cxx | 54 +-------
+ connectivity/source/drivers/evoab2/EApi.h | 2 +-
+ .../drivers/evoab2/NDatabaseMetaData.cxx | 121 +++++------------
+ .../source/drivers/evoab2/NResultSet.cxx | 125 +-----------------
+ 4 files changed, 39 insertions(+), 263 deletions(-)
+
+diff --git a/connectivity/source/drivers/evoab2/EApi.cxx b/connectivity/source/drivers/evoab2/EApi.cxx
+index 12096bdade87..ebe710dedb57 100644
+--- a/connectivity/source/drivers/evoab2/EApi.cxx
++++ b/connectivity/source/drivers/evoab2/EApi.cxx
+@@ -23,16 +23,7 @@
+ static const char *eBookLibNames[] = {
+ "libebook-1.2.so.20", // evolution-data-server 3.33.2+
+ "libebook-1.2.so.19", // evolution-data-server 3.24+
+- "libebook-1.2.so.16",
+- "libebook-1.2.so.15",
+- "libebook-1.2.so.14", // bumped again (evolution-3.6)
+- "libebook-1.2.so.13", // bumped again (evolution-3.4)
+- "libebook-1.2.so.12", // bumped again
+- "libebook-1.2.so.10", // bumped again
+- "libebook-1.2.so.9", // evolution-2.8
+- "libebook-1.2.so.5", // evolution-2.4 and 2.6+
+- "libebook-1.2.so.3", // evolution-2.2
+- "libebook.so.8" // evolution-2.0
++ "libebook-1.2.so.16"
+ };
+
+ typedef void (*SymbolFunc) ();
+@@ -71,19 +62,6 @@ static const ApiMap aCommonApiMap[] =
+ SYM_MAP( e_book_query_field_exists )
+ };
+
+-//< 3.6 api
+-static const ApiMap aOldApiMap[] =
+-{
+- SYM_MAP( e_book_get_addressbooks ),
+- SYM_MAP( e_book_get_uri ),
+- SYM_MAP( e_book_authenticate_user ),
+- SYM_MAP( e_source_group_peek_base_uri),
+- SYM_MAP( e_source_peek_name ),
+- SYM_MAP( e_source_get_property ),
+- SYM_MAP( e_source_list_peek_groups ),
+- SYM_MAP( e_source_group_peek_sources )
+-};
+-
+ //>= 3.6 api
+ static const ApiMap aNewApiMap[] =
+ {
+@@ -101,12 +79,6 @@ static const ApiMap aNewApiMap[] =
+ SYM_MAP( e_client_util_free_object_slist )
+ };
+
+-//== indirect read access (3.6 only)
+-static const ApiMap aClientApiMap36[] =
+-{
+- SYM_MAP( e_book_client_new )
+-};
+-
+ //>= direct read access API (>= 3.8)
+ static const ApiMap aClientApiMap38[] =
+ {
+@@ -144,33 +116,14 @@ bool EApiInit()
+
+ if (tryLink( aModule, eBookLibNames[ j ], aCommonApiMap))
+ {
+- if (eds_check_version( 3, 6, 0 ) != nullptr)
++ if (tryLink( aModule, eBookLibNames[ j ], aNewApiMap))
+ {
+- if (tryLink( aModule, eBookLibNames[ j ], aOldApiMap))
++ if (tryLink( aModule, eBookLibNames[ j ], aClientApiMap38))
+ {
+ aModule.release();
+ return true;
+ }
+ }
+- else if (tryLink( aModule, eBookLibNames[ j ], aNewApiMap))
+- {
+- if (eds_check_version( 3, 7, 6 ) != nullptr)
+- {
+- if (tryLink( aModule, eBookLibNames[ j ], aClientApiMap36))
+- {
+- aModule.release();
+- return true;
+- }
+- }
+- else
+- {
+- if (tryLink( aModule, eBookLibNames[ j ], aClientApiMap38))
+- {
+- aModule.release();
+- return true;
+- }
+- }
+- }
+ }
+ }
+ fprintf( stderr, "Can find no compliant libebook client libraries\n" );
+diff --git a/connectivity/source/drivers/evoab2/EApi.h b/connectivity/source/drivers/evoab2/EApi.h
+index 8c05f95fa2ce..928786d79f00 100644
+--- a/connectivity/source/drivers/evoab2/EApi.h
++++ b/connectivity/source/drivers/evoab2/EApi.h
+@@ -147,7 +147,7 @@ EAPI_EXTERN const gchar* (*eds_check_version) (guint required_major, guint requi
+ EAPI_EXTERN const gchar* (*e_source_get_uid) (ESource *source);
+ EAPI_EXTERN ESource* (*e_source_registry_ref_source) (ESourceRegistry *registry, const gchar *uid);
+ EAPI_EXTERN EBookClient* (*e_book_client_new) (ESource *source, GError **error);
+-EAPI_EXTERN EBookClient* (*e_book_client_connect_direct_sync) (ESourceRegistry *registry, ESource *source, GCancellable *cancellable, GError **error);
++EAPI_EXTERN EBookClient* (*e_book_client_connect_direct_sync) (ESourceRegistry *registry, ESource *source, guint32 wait_for_connected_seconds, GCancellable *cancellable, GError **error);
+ EAPI_EXTERN gboolean (*e_client_open_sync) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error);
+ EAPI_EXTERN ESource* (*e_client_get_source) (EClient *client);
+ EAPI_EXTERN gboolean (*e_book_client_get_contacts_sync) (EBookClient *client, const gchar *sexp, GSList **contacts, GCancellable *cancellable, GError **error);
+diff --git a/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx b/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx
+index 9eb6f1d34862..783d9728784f 100644
+--- a/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx
++++ b/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx
+@@ -1106,103 +1106,50 @@ Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::getTables(
+
+ ODatabaseMetaDataResultSet::ORows aRows;
+
+- if (eds_check_version(3, 6, 0) == nullptr)
+- {
+- GList *pSources = e_source_registry_list_sources(get_e_source_registry(), E_SOURCE_EXTENSION_ADDRESS_BOOK);
++ GList *pSources = e_source_registry_list_sources(get_e_source_registry(), E_SOURCE_EXTENSION_ADDRESS_BOOK);
+
+- for (GList* liter = pSources; liter; liter = liter->next)
+- {
+- ESource *pSource = E_SOURCE (liter->data);
+- bool can = false;
+- switch (m_pConnection->getSDBCAddressType())
+- {
+- case SDBCAddress::EVO_GWISE:
+- can = isSourceBackend( pSource, "groupwise"); // not supported in evo/eds 3.6.x+, somehow
+- break;
+- case SDBCAddress::EVO_LOCAL:
+- can = isSourceBackend( pSource, "local");
+- break;
+- case SDBCAddress::EVO_LDAP:
+- can = isSourceBackend( pSource, "ldap");
+- break;
+- case SDBCAddress::Unknown:
+- can = true;
+- break;
+- }
+- if (!can)
+- continue;
+-
+- OUString aHumanName = OStringToOUString( e_source_get_display_name( pSource ),
+- RTL_TEXTENCODING_UTF8 );
+- OUString aUID = OStringToOUString( e_source_get_uid( pSource ),
+- RTL_TEXTENCODING_UTF8 );
+- ODatabaseMetaDataResultSet::ORow aRow{
+- ORowSetValueDecoratorRef(),
+- ORowSetValueDecoratorRef(),
+- ORowSetValueDecoratorRef(),
+- new ORowSetValueDecorator(aHumanName), //tablename
+- new ORowSetValueDecorator(aTable),
+- new ORowSetValueDecorator(aUID)}; //comment
+- //I'd prefer to swap the comment and the human name and
+- //just use e_source_registry_ref_source(get_e_source_registry(), aUID);
+- //in open book rather than search for the name again
+- aRows.push_back(aRow);
+- }
+-
+- g_list_foreach (pSources, reinterpret_cast<GFunc>(g_object_unref), nullptr);
+- g_list_free (pSources);
+- }
+- else
++ for (GList* liter = pSources; liter; liter = liter->next)
+ {
+- ESourceList *pSourceList;
+- if( !e_book_get_addressbooks (&pSourceList, nullptr) )
+- pSourceList = nullptr;
+-
+- GSList *g;
+- for( g = e_source_list_peek_groups( pSourceList ); g; g = g->next)
++ ESource *pSource = E_SOURCE (liter->data);
++ bool can = false;
++ switch (m_pConnection->getSDBCAddressType())
+ {
+- GSList *s;
+- const char *p = e_source_group_peek_base_uri(E_SOURCE_GROUP(g->data));
+-
+- switch (m_pConnection->getSDBCAddressType()) {
+ case SDBCAddress::EVO_GWISE:
+- if ( !strncmp( "groupwise://", p, 11 ))
+- break;
+- else
+- continue;
++ can = isSourceBackend( pSource, "groupwise"); // not supported in evo/eds 3.6.x+, somehow
++ break;
+ case SDBCAddress::EVO_LOCAL:
+- if ( !strncmp( "file://", p, 6 ) ||
+- !strncmp( "local://", p, 6 ) )
+- break;
+- else
+- continue;
++ can = isSourceBackend( pSource, "local");
++ break;
+ case SDBCAddress::EVO_LDAP:
+- if ( !strncmp( "ldap://", p, 6 ))
+- break;
+- else
+- continue;
++ can = isSourceBackend( pSource, "ldap");
++ break;
+ case SDBCAddress::Unknown:
++ can = true;
+ break;
+- }
+- for (s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data)); s; s = s->next)
+- {
+- ESource *pSource = E_SOURCE (s->data);
+-
+- OUString aName = OStringToOUString( e_source_peek_name( pSource ),
+- RTL_TEXTENCODING_UTF8 );
+-
+- ODatabaseMetaDataResultSet::ORow aRow{
+- ORowSetValueDecoratorRef(),
+- ORowSetValueDecoratorRef(),
+- ORowSetValueDecoratorRef(),
+- new ORowSetValueDecorator(aName),
+- new ORowSetValueDecorator(aTable),
+- ODatabaseMetaDataResultSet::getEmptyValue()};
+- aRows.push_back(aRow);
+- }
+ }
++ if (!can)
++ continue;
++
++ OUString aHumanName = OStringToOUString( e_source_get_display_name( pSource ),
++ RTL_TEXTENCODING_UTF8 );
++ OUString aUID = OStringToOUString( e_source_get_uid( pSource ),
++ RTL_TEXTENCODING_UTF8 );
++ ODatabaseMetaDataResultSet::ORow aRow{
++ ORowSetValueDecoratorRef(),
++ ORowSetValueDecoratorRef(),
++ ORowSetValueDecoratorRef(),
++ new ORowSetValueDecorator(aHumanName), //tablename
++ new ORowSetValueDecorator(ORowSetValue(aTable)),
++ new ORowSetValueDecorator(aUID)}; //comment
++ //I'd prefer to swap the comment and the human name and
++ //just use e_source_registry_ref_source(get_e_source_registry(), aUID);
++ //in open book rather than search for the name again
++ aRows.push_back(aRow);
+ }
+
++ g_list_foreach (pSources, reinterpret_cast<GFunc>(g_object_unref), nullptr);
++ g_list_free (pSources);
++
+ pResult->setRows(aRows);
+
+ return xRef;
+diff --git a/connectivity/source/drivers/evoab2/NResultSet.cxx b/connectivity/source/drivers/evoab2/NResultSet.cxx
+index 77d53939c1aa..2e15f245b8c8 100644
+--- a/connectivity/source/drivers/evoab2/NResultSet.cxx
++++ b/connectivity/source/drivers/evoab2/NResultSet.cxx
+@@ -477,123 +477,7 @@ class OEvoabVersion38Helper : public OEvoabVersion36Helper
+ protected:
+ virtual EBookClient * createClient( ESource *pSource ) override
+ {
+- return e_book_client_connect_direct_sync (get_e_source_registry (), pSource, nullptr, nullptr);
+- }
+-};
+-
+-ESource * findSource( const char *id )
+-{
+- ESourceList *pSourceList = nullptr;
+-
+- g_return_val_if_fail (id != nullptr, nullptr);
+-
+- if (!e_book_get_addressbooks (&pSourceList, nullptr))
+- pSourceList = nullptr;
+-
+- for ( GSList *g = e_source_list_peek_groups (pSourceList); g; g = g->next)
+- {
+- for (GSList *s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data)); s; s = s->next)
+- {
+- ESource *pSource = E_SOURCE (s->data);
+- if (!strcmp (e_source_peek_name (pSource), id))
+- return pSource;
+- }
+- }
+- return nullptr;
+-}
+-
+-bool isAuthRequired( EBook *pBook )
+-{
+- return e_source_get_property( e_book_get_source( pBook ),
+- "auth" ) != nullptr;
+-}
+-
+-class OEvoabVersion35Helper : public OEvoabVersionHelper
+-{
+-private:
+- GList *m_pContacts;
+-
+-public:
+- OEvoabVersion35Helper()
+- : m_pContacts(nullptr)
+- {
+- }
+-
+- virtual ~OEvoabVersion35Helper() override
+- {
+- freeContacts();
+- }
+-
+- virtual EBook* openBook(const char *abname) override
+- {
+- ESource *pSource = findSource (abname);
+- EBook *pBook = pSource ? e_book_new (pSource, nullptr) : nullptr;
+- if (pBook && !e_book_open (pBook, true, nullptr))
+- {
+- g_object_unref (G_OBJECT (pBook));
+- pBook = nullptr;
+- }
+- return pBook;
+- }
+-
+- virtual bool isLDAP( EBook *pBook ) override
+- {
+- return pBook && !strncmp( "ldap://", e_book_get_uri( pBook ), 6 );
+- }
+-
+- virtual bool isLocal( EBook *pBook ) override
+- {
+- return pBook && ( !strncmp( "file://", e_book_get_uri( pBook ), 6 ) ||
+- !strncmp( "local:", e_book_get_uri( pBook ), 6 ) );
+- }
+-
+- virtual void freeContacts() override final
+- {
+- g_list_free(m_pContacts);
+- m_pContacts = nullptr;
+- }
+-
+- virtual void executeQuery (EBook* pBook, EBookQuery* pQuery, OString &rPassword) override
+- {
+- freeContacts();
+-
+- ESource *pSource = e_book_get_source( pBook );
+- bool bAuthSuccess = true;
+-
+- if( isAuthRequired( pBook ) )
+- {
+- OString aUser( getUserName( pBook ) );
+- const char *pAuth = e_source_get_property( pSource, "auth" );
+- bAuthSuccess = e_book_authenticate_user( pBook, aUser.getStr(), rPassword.getStr(), pAuth, nullptr );
+- }
+-
+- if (bAuthSuccess)
+- e_book_get_contacts( pBook, pQuery, &m_pContacts, nullptr );
+- }
+-
+- virtual EContact *getContact(sal_Int32 nIndex) override
+- {
+- gpointer pData = g_list_nth_data (m_pContacts, nIndex);
+- return pData ? E_CONTACT (pData) : nullptr;
+- }
+-
+- virtual sal_Int32 getNumContacts() override
+- {
+- return g_list_length( m_pContacts );
+- }
+-
+- virtual bool hasContacts() override
+- {
+- return m_pContacts != nullptr;
+- }
+-
+- virtual void sortContacts( const ComparisonData& _rCompData ) override
+- {
+- OSL_ENSURE( !_rCompData.rSortOrder.empty(), "sortContacts: no need to call this without any sort order!" );
+- ENSURE_OR_THROW( _rCompData.aIntlWrapper.getCaseCollator(), "no collator for comparing strings" );
+-
+- m_pContacts = g_list_sort_with_data( m_pContacts, &CompareContacts,
+- const_cast< gpointer >( static_cast< gconstpointer >( &_rCompData ) ) );
++ return e_book_client_connect_direct_sync (get_e_source_registry (), pSource, 10, nullptr, nullptr);
+ }
+ };
+
+@@ -612,12 +496,7 @@ OEvoabResultSet::OEvoabResultSet( OCommonStatement* pStmt, OEvoabConnection *pCo
+ ,m_nIndex(-1)
+ ,m_nLength(0)
+ {
+- if (eds_check_version( 3, 7, 6 ) == nullptr)
+- m_pVersionHelper = std::make_unique<OEvoabVersion38Helper>();
+- else if (eds_check_version( 3, 6, 0 ) == nullptr)
+- m_pVersionHelper = std::make_unique<OEvoabVersion36Helper>();
+- else
+- m_pVersionHelper = std::make_unique<OEvoabVersion35Helper>();
++ m_pVersionHelper = std::make_unique<OEvoabVersion38Helper>();
+
+ #define REGISTER_PROP( id, member ) \
+ registerProperty( \
diff --git a/patches/hrk-euro.diff b/patches/hrk-euro.diff
new file mode 100644
index 00000000..b4fbe69a
--- /dev/null
+++ b/patches/hrk-euro.diff
@@ -0,0 +1,156 @@
+From 7c4b2db21ef77b37daf234ac1ab9989234606a22 Mon Sep 17 00:00:00 2001
+From: Eike Rathke <er...@redhat.com>
+Date: Fri, 22 Jul 2022 22:12:02 +0200
+Subject: Resolves: tdf#150011 Add HRK Croatian Kuna conversion to EUR Euro
+
+TODO: switch defaults before 2023-01-01 in
+i18npool/source/localedata/data/hr_HR.xml
+
+Change-Id: Ifc62aefbc8c9fe8bbf044f61ae4fd6eeff692185
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137371
+Reviewed-by: Eike Rathke <er...@redhat.com>
+Tested-by: Jenkins
+---
+ i18npool/source/localedata/data/hr_HR.xml | 8 ++++++++
+ officecfg/registry/data/org/openoffice/Office/Calc.xcu | 11 +++++++++++
+ sc/source/core/tool/interpr2.cxx | 3 ++-
+ 3 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/i18npool/source/localedata/data/hr_HR.xml b/i18npool/source/localedata/data/hr_HR.xml
+index 0c493131e16b..4de83e5535cd 100644
+--- a/i18npool/source/localedata/data/hr_HR.xml
++++ b/i18npool/source/localedata/data/hr_HR.xml
+@@ -421,6 +421,14 @@
+ <CurrencyName>Hrvatska Kuna</CurrencyName>
+ <DecimalPlaces>2</DecimalPlaces>
+ </Currency>
++ <!-- TODO: switch defaults before 2023-01-01 -->
++ <Currency default="false" usedInCompatibleFormatCodes="false">
++ <CurrencyID>EUR</CurrencyID>
++ <CurrencySymbol>€</CurrencySymbol>
++ <BankSymbol>EUR</BankSymbol>
++ <CurrencyName>Euro</CurrencyName>
++ <DecimalPlaces>2</DecimalPlaces>
++ </Currency>
+ </LC_CURRENCY>
+ <LC_TRANSLITERATION>
+ <Transliteration unoid="SENTENCE_CASE"/>
+diff --git a/officecfg/registry/data/org/openoffice/Office/Calc.xcu b/officecfg/registry/data/org/openoffice/Office/Calc.xcu
+index a62d06512704..eda60fe6c434 100644
+--- a/officecfg/registry/data/org/openoffice/Office/Calc.xcu
++++ b/officecfg/registry/data/org/openoffice/Office/Calc.xcu
+@@ -228,6 +228,17 @@
+ <value>3.45280</value>
+ </prop>
+ </node>
++ <node oor:name="CR20" oor:op="replace">
++ <prop oor:name="FromUnit">
++ <value>EUR</value>
++ </prop>
++ <prop oor:name="ToUnit">
++ <value>HRK</value>
++ </prop>
++ <prop oor:name="Factor">
++ <value>7.53450</value>
++ </prop>
++ </node>
+ </node>
+ <node oor:name="Calculate">
+ <node oor:name="Other">
+diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
+index 31c42a4b728a..67fcd9f787f8 100644
+--- a/sc/source/core/tool/interpr2.cxx
++++ b/sc/source/core/tool/interpr2.cxx
+@@ -3235,7 +3235,8 @@ static bool lclConvertMoney( const OUString& aSearchUnit, double& rfRate, int& r
+ { "SKK", 30.1260, 2 },
+ { "EEK", 15.6466, 2 },
+ { "LVL", 0.702804, 2 },
+- { "LTL", 3.45280, 2 }
++ { "LTL", 3.45280, 2 },
++ { "HRK", 7.53450, 2 }
+ };
+
+ for (const auto & i : aConvertTable)
+--
+cgit v1.2.1
+
+From b1a2f727ca99ecd3402d4b051b99cbfd24266e59 Mon Sep 17 00:00:00 2001
+From: Eike Rathke <er...@redhat.com>
+Date: Fri, 22 Jul 2022 22:17:11 +0200
+Subject: Related: tdf#150011 Add HRK Croatian Kuna to Euro conversion wizard
+
+Maybe just for completeness, it's removed from menu but might be
+callable as macro.
+
+Change-Id: Iade0be845186d3deb2f00f4aaa230c0b344cea72
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137372
+Reviewed-by: Eike Rathke <er...@redhat.com>
+Tested-by: Jenkins
+---
+ wizards/source/euro/Init.xba | 16 ++++++++++++++++
+ wizards/source/resources/resources_en_US.properties | 1 +
+ 2 files changed, 17 insertions(+)
+
+diff --git a/wizards/source/euro/Init.xba b/wizards/source/euro/Init.xba
+index 623a0a53be46..9f56c503a347 100644
+--- a/wizards/source/euro/Init.xba
++++ b/wizards/source/euro/Init.xba
+@@ -89,6 +89,7 @@ Public sCurrSLOVAK as String
+ Public sCurrESTONIAN as String
+ Public sCurrLATVIAN as String
+ Public sCurrLITHUANIAN as String
++Public sCurrCROATIAN as String
+
+ Public sPrgsRETRIEVAL as String
+ Public sPrgsCONVERTING as String
+@@ -214,6 +215,7 @@ Dim LocWorkPath as String
+ sCurrESTONIAN = GetResText("CURRENCIES_16")
+ sCurrLATVIAN = GetResText("CURRENCIES_17")
+ sCurrLITHUANIAN = GetResText("CURRENCIES_18")
++ sCurrCROATIAN = GetResText("CURRENCIES_19")
+ .cmdCancel.Label = sCANCEL
+ .cmdHelp.Label = sHELP
+ .cmdBack.Label = GetResText("STEP_ZERO_2")
+@@ -393,6 +395,11 @@ Sub InitializeLanguages()
+ LangIDValue(18,0,1) = "LT"
+ LangIDValue(18,0,2) = "-427"
+
++' CURRENCIES_CROATIAN
++ LangIDValue(19,0,0) = "hr"
++ LangIDValue(19,0,1) = "HR"
++ LangIDValue(19,0,2) = "-41A"
++
+ End Sub
+
+
+@@ -572,6 +579,15 @@ Dim i as Integer
+ CurrValue(18,4) = "Lt"
+ CurrValue(18,5) = "LTL"
+
++ CurrValue(19,0) = sCurrCROATIAN
++ ' real conversion rate
++ CurrValue(19,1) = 7.53450
++ ' rounded conversion rate
++ CurrValue(19,2) = 7.5
++ CurrValue(19,3) = "kn"
++ CurrValue(19,4) = "kn"
++ CurrValue(19,5) = "HRK"
++
+ i = -1
+ CurrSymbolList(0) = ""
+ CurrSymbolList(1) = ""
+diff --git a/wizards/source/resources/resources_en_US.properties b/wizards/source/resources/resources_en_US.properties
+index 32f9104e97e0..8649b2500e6a 100644
+--- a/wizards/source/resources/resources_en_US.properties
++++ b/wizards/source/resources/resources_en_US.properties
+@@ -448,6 +448,7 @@ CURRENCIES_15=Slovak Koruna
+ CURRENCIES_16=Estonian Kroon
+ CURRENCIES_17=Latvian Lats
+ CURRENCIES_18=Lithuanian Litas
++CURRENCIES_19=Croatian Kuna
+ STEP_LASTPAGE_0=Progress
+ STEP_LASTPAGE_1=Retrieving the relevant documents...
+ STEP_LASTPAGE_2=Converting the documents...
+--
+cgit v1.2.1
+
diff --git a/patches/series b/patches/series
index d7c5a79c..0d440f91 100644
--- a/patches/series
+++ b/patches/series
@@ -56,3 +56,10 @@ xmlsecurity-XSecParser-confused-about-multiple-timestamps.diff
xmlsecurity-ignore-elements-in-ds:Object-that-arent-signed.diff
default-to-CertificateValidity::INVALID.diff
xmlsecurity-improve-handling-of-multiple-X509Data-elements.diff
+fix-e_book_client_connect_direct_sync-sig.diff
+hrk-euro.diff
+b0404f80577de9ff69e58390c6f6ef949fdb0139.patch
+0001-CVE-2022-26305-compare-authors-using-Thumbprint.patch
+0002-CVE-2022-26307-make-hash-encoding-match-decoding.patch
+0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch
+0004-CVE-2022-2630-6-7-add-infobar-to-prompt-to-refresh-t.patch