[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1016037: bullseye-pu: package libreoffice/1:7.0.4-4+deb11u2 (was: bullseye-pu: package libreoffice/1:7.0.4-4+deb11u1)



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 <rene@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?= <caolanm@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 <vmiklos@collabora.com>
+(cherry picked from commit 65442205b5b274ad309308162f150f8d41648f72)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130866
+Reviewed-by: Michael Stahl <michael.stahl@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?= <caolanm@redhat.com>
+Date: Mon, 21 Mar 2022 20:58:34 +0000
+Subject: [PATCH 2/4] CVE-2022-26307 make hash encoding match decoding
+
+Seeing as old versions of the hash may be in the users config, add a
+StorageVersion field to the office config Passwords section which
+defaults to 0 to indicate the old hash is in use.
+
+Try the old varient when StorageVersion is 0. When a new encoded master
+password it set write StorageVersion of 1 to indicate a new hash is in
+use and use the new style when StorageVersion is 1.
+
+Change-Id: I3174c37a5891bfc849984e0ec5c2c392b9c6e7b1
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132080
+Tested-by: Jenkins
+Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
+(cherry picked from commit e890f54dbac57f3ab5acf4fbd31222095d3e8ab6)
+---
+ .../schema/org/openoffice/Office/Common.xcs   |  6 +++
+ .../passwordcontainer/passwordcontainer.cxx   | 45 +++++++++++++++++--
+ .../passwordcontainer/passwordcontainer.hxx   |  6 +++
+ uui/source/iahndl-authentication.cxx          |  5 ++-
+ 4 files changed, 57 insertions(+), 5 deletions(-)
+
+diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+index 9097c23c3c6a..922efc33cca7 100644
+--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+@@ -942,6 +942,12 @@
+         </info>
+         <value>false</value>
+       </prop>
++      <prop oor:name="StorageVersion" oor:type="xs:int" oor:nillable="false">
++        <info>
++          <desc>Specifies what version of encoding scheme the password container uses.</desc>
++        </info>
++        <value>0</value>
++      </prop>
+       <prop oor:name="HasMaster" oor:type="xs:boolean" oor:nillable="false">
+         <info>
+           <desc>Specifies if there is a valid master password.</desc>
+diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx
+index 51fb129cddb1..b674844f91d3 100644
+--- a/svl/source/passwordcontainer/passwordcontainer.cxx
++++ b/svl/source/passwordcontainer/passwordcontainer.cxx
+@@ -17,7 +17,6 @@
+  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+  */
+ 
+-
+ #include "passwordcontainer.hxx"
+ 
+ #include <cppuhelper/factory.hxx>
+@@ -259,6 +258,23 @@ bool StorageItem::useStorage()
+     return aResult;
+ }
+ 
++sal_Int32 StorageItem::getStorageVersion()
++{
++    Sequence<OUString> aNodeNames { "StorageVersion" };
++
++    Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
++
++    if( aPropertyValues.getLength() != aNodeNames.getLength() )
++    {
++        OSL_FAIL( "Problems during reading" );
++        return 0;
++    }
++
++    sal_Int32 nResult = 0;
++    aPropertyValues[0] >>= nResult;
++
++    return nResult;
++}
+ 
+ bool StorageItem::getEncodedMP( OUString& aResult )
+ {
+@@ -291,15 +307,17 @@ bool StorageItem::getEncodedMP( OUString& aResult )
+ 
+ void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty )
+ {
+-    Sequence< OUString > sendNames(2);
+-    Sequence< uno::Any > sendVals(2);
++    Sequence< OUString > sendNames(3);
++    Sequence< uno::Any > sendVals(3);
+ 
+     sendNames[0] = "HasMaster";
+     sendNames[1] = "Master";
++    sendNames[2] = "StorageVersion";
+ 
+     bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty );
+     sendVals[0] <<= bHasMaster;
+     sendVals[1] <<= aEncoded;
++    sendVals[2] <<= nCurrentStorageVersion;
+ 
+     ConfigItem::SetModified();
+     ConfigItem::PutProperties( sendNames, sendVals );
+@@ -800,6 +818,18 @@ OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode,
+     return aResult;
+ }
+ 
++// Mangle the key to match an old bug
++static OUString ReencodeAsOldHash(const OUString& rPass)
++{
++    OUStringBuffer aBuffer;
++    for (int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ++ind)
++    {
++        unsigned char i = static_cast<char>(rPass.copy(ind * 2, 2).toUInt32(16));
++        aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4)));
++        aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15)));
++    }
++    return aBuffer.makeStringAndClear();
++}
+ 
+ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler )
+ {
+@@ -838,6 +868,9 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac
+                     }
+                     else
+                     {
++                        if (m_pStorageFile->getStorageVersion() == 0)
++                            aPass = ReencodeAsOldHash(aPass);
++
+                         std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass, aRMode ) );
+                         if( aRM.empty() || aPass != aRM[0] )
+                         {
+@@ -1042,6 +1075,12 @@ sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::R
+ 
+                 do {
+                     aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
++
++                    if (!aPass.isEmpty() && m_pStorageFile->getStorageVersion() == 0)
++                    {
++                        aPass = ReencodeAsOldHash(aPass);
++                    }
++
+                     bResult = ( !aPass.isEmpty() && aPass == m_aMasterPasswd );
+                     aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification
+                 } while( !bResult && !aPass.isEmpty() );
+diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx b/svl/source/passwordcontainer/passwordcontainer.hxx
+index 46ffec888602..bf43b5903602 100644
+--- a/svl/source/passwordcontainer/passwordcontainer.hxx
++++ b/svl/source/passwordcontainer/passwordcontainer.hxx
+@@ -168,6 +168,10 @@ public:
+ typedef ::std::pair< const OUString, ::std::vector< NamePassRecord > > PairUrlRecord;
+ typedef ::std::map< OUString, ::std::vector< NamePassRecord > > PassMap;
+ 
++// org.openoffice.Office.Common/Passwords/StorageVersion bump if details of
++// how password details are saved changes. Enables migration from previous
++// schemes.
++constexpr sal_Int32 nCurrentStorageVersion = 1;
+ 
+ class PasswordContainer;
+ 
+@@ -195,6 +195,8 @@
+     void remove( const OUString& url, const OUString& rec );
+     void clear();
+ 
++    sal_Int32 getStorageVersion();
++
+     bool getEncodedMP( OUString& aResult );
+     void setEncodedMP( const OUString& aResult, bool bAcceptEnmpty = false );
+     void setUseStorage( bool bUse );
+diff --git a/uui/source/iahndl-authentication.cxx b/uui/source/iahndl-authentication.cxx
+index ad975d3f9ae7..951f0b8a1c6b 100644
+--- a/uui/source/iahndl-authentication.cxx
++++ b/uui/source/iahndl-authentication.cxx
+@@ -436,8 +436,9 @@ executeMasterPasswordDialog(
+     OUStringBuffer aBuffer;
+     for (sal_uInt8 i : aKey)
+     {
+-        aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4)));
+-        aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15)));
++        // match PasswordContainer::DecodePasswords aMasterPasswd.copy(index * 2, 2).toUInt32(16));
++        aBuffer.append(OUString::number(i >> 4, 16));
++        aBuffer.append(OUString::number(i & 15, 16));
+     }
+     rInfo.SetPassword(aBuffer.makeStringAndClear());
+ }
+-- 
+2.37.1
+
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?= <caolanm@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.stahl@allotropia.de>
+(cherry picked from commit 192fa1e3bfc6269f2ebb91716471485a56074aea)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132306
+Reviewed-by: Thorsten Behrens <thorsten.behrens@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?= <caolanm@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.stahl@allotropia.de>
+(cherry picked from commit bbd196ff82bda9f66b4ba32a412f10cefe6da60e)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132307
+Reviewed-by: Sophie Gautier <sophi@libreoffice.org>
+Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
+(cherry picked from commit c5d01b11db3c83cb4a89d3b388d78e20dd3990b5)
+
+Change-Id: Id99cbf2b50a4ebf289dae6fc67e22e20afcda35b
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133906
+Tested-by: Michael Stahl <michael.stahl@allotropia.de>
+Reviewed-by: Michael Stahl <michael.stahl@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?= <caolanm@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 <vmiklos@collabora.com>
+(cherry picked from commit be446d81e07b5499152efeca6ca23034e51ea5ff)
+Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127178
+Reviewed-by: Adolfo Jayme Barrientos <fitojb@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 <serval2412@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 <caolanm@redhat.com>
+Reviewed-by: Caolán McNamara <caolanm@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 <erack@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 <erack@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 <erack@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 <erack@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(&quot;CURRENCIES_16&quot;)
+ 		sCurrLATVIAN = GetResText(&quot;CURRENCIES_17&quot;)
+ 		sCurrLITHUANIAN = GetResText(&quot;CURRENCIES_18&quot;)
++		sCurrCROATIAN = GetResText(&quot;CURRENCIES_19&quot;)
+ 		.cmdCancel.Label =  sCANCEL
+ 		.cmdHelp.Label =  sHELP
+ 		.cmdBack.Label =  GetResText(&quot;STEP_ZERO_2&quot;)
+@@ -393,6 +395,11 @@ Sub InitializeLanguages()
+     LangIDValue(18,0,1) = &quot;LT&quot;
+     LangIDValue(18,0,2) = &quot;-427&quot;
+ 
++&apos; CURRENCIES_CROATIAN
++    LangIDValue(19,0,0) = &quot;hr&quot;
++    LangIDValue(19,0,1) = &quot;HR&quot;
++    LangIDValue(19,0,2) = &quot;-41A&quot;
++
+ End Sub
+ 
+ 
+@@ -572,6 +579,15 @@ Dim i as Integer
+ 	CurrValue(18,4) = &quot;Lt&quot;
+ 	CurrValue(18,5) = &quot;LTL&quot;
+ 
++	CurrValue(19,0) = sCurrCROATIAN
++	&apos; real conversion rate
++	CurrValue(19,1) = 7.53450
++	&apos; rounded conversion rate
++	CurrValue(19,2) = 7.5
++	CurrValue(19,3) = &quot;kn&quot;
++	CurrValue(19,4) = &quot;kn&quot;
++	CurrValue(19,5) = &quot;HRK&quot;
++
+ 	i = -1
+ 	CurrSymbolList(0) = &quot;&quot;
+ 	CurrSymbolList(1) = &quot;&quot;
+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

Reply to: