[Libreoffice-commits] core.git: Branch 'distro/cib/libreoffice-6-1' - sfx2/source xmlsecurity/CppunitTest_xmlsecurity_signing.mk xmlsecurity/qa

Jan-Marek Glogowski (via logerrit) logerrit at kemper.freedesktop.org
Mon Sep 23 00:43:55 UTC 2019


 sfx2/source/doc/objstor.cxx                         |   30 +-
 xmlsecurity/CppunitTest_xmlsecurity_signing.mk      |    4 
 xmlsecurity/qa/unit/signing/data/tdf42316.ott       |binary
 xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott |binary
 xmlsecurity/qa/unit/signing/signing.cxx             |  246 +++++++++++++++++++-
 5 files changed, 271 insertions(+), 9 deletions(-)

New commits:
commit c21f9769b96e1dddfe0b1005bca4c4a55f508860
Author:     Jan-Marek Glogowski <jan-marek.glogowski at extern.cib.de>
AuthorDate: Fri Jul 19 15:28:45 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon Sep 23 02:43:19 2019 +0200

    tdf#42316 preserve macro signature of templates
    
    When comparing the filter of the current and the target document
    we have to strip the '_template' from the filter name.
    
    Still this won't preserve the signature of the document attached
    to tdf#42316, as this is a ODF 1.0 OTT, which doesn't have a
    valid signature in ODF 1.2, as the signature doesn't match the ODF
    1.2 namespace for signatures and the default LO ODF version is ODF
    1.2 extended.
    
    In theory the signature itself could even be converted most times,
    but that can be done in an additional patch, if needed.
    
    Since the code literally saves a template to an internal document,
    SfxObjectShell::DoSaveCompleted must keep the signature of the
    template. Eventually it'll be dropped on save of the template as
    a document later.
    
    The signing tests check "OTT 1.0 => ODT 1.0: preserve", "OTT 1.2
    => ODT 1.2: preserve" and "OTT 1.0 => ODT 1.2: drop".
    
    Reviewed-on: https://gerrit.libreoffice.org/75958
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    (cherry picked from commit c3a1c83ff5af05d34f433ac808adbe85f47e8c18)
    Reviewed-on: https://gerrit.libreoffice.org/77112
    
    Conflicts:
            xmlsecurity/qa/unit/signing/signing.cxx
    
    Change-Id: I2263093687f5a0568ea781ce3ac9b114c9599add
    Reviewed-on: https://gerrit.libreoffice.org/79371
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 716455cda9ae..fa08ceb42a4a 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -1160,10 +1160,18 @@ bool SfxObjectShell::SaveTo_Impl
             {}
 
             // preserve only if the same filter has been used
-            bTryToPreserveScriptSignature = pMedium->GetFilter() && pFilter && pMedium->GetFilter()->GetFilterName() == pFilter->GetFilterName();
-
+            // for templates, strip the _template from the filter name for comparison
+            OUString aMediumFilter = pMedium->GetFilter()->GetFilterName();
+            if (aMediumFilter.endsWith("_template"))
+                aMediumFilter = aMediumFilter.copy(0, aMediumFilter.getLength() - 9);
+            bTryToPreserveScriptSignature = pMedium->GetFilter() && pFilter && aMediumFilter == pFilter->GetFilterName();
+
+            // signatures were specified in ODF 1.2 but were used since much longer.
+            // LO will still correctly validate an old style signature on an ODF 1.2
+            // document, but technically this is not correct, so this prevents old
+            // signatures to be copied over to a version 1.2 document
             bNoPreserveForOasis = (
-                                   (aODFVersion == ODFVER_012_TEXT && nVersion == SvtSaveOptions::ODFVER_011) ||
+                                   (aODFVersion == ODFVER_012_TEXT && nVersion < SvtSaveOptions::ODFVER_012) ||
                                    (aODFVersion.isEmpty() && nVersion >= SvtSaveOptions::ODFVER_012)
                                   );
         }
@@ -2026,13 +2034,21 @@ bool SfxObjectShell::DoSaveCompleted( SfxMedium* pNewMed, bool bRegisterRecent )
                 {}
             }
 
+            const SfxBoolItem* pTemplateItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_TEMPLATE, false);
+            bool bTemplate = pTemplateItem && pTemplateItem->GetValue();
+
             // before the title regenerated the document must lose the signatures
             pImpl->nDocumentSignatureState = SignatureState::NOSIGNATURES;
-            pImpl->nScriptingSignatureState = pNewMed->GetCachedSignatureState_Impl();
-            OSL_ENSURE( pImpl->nScriptingSignatureState != SignatureState::BROKEN, "The signature must not be broken at this place" );
+            if (!bTemplate)
+            {
+                pImpl->nScriptingSignatureState = pNewMed->GetCachedSignatureState_Impl();
+                OSL_ENSURE( pImpl->nScriptingSignatureState != SignatureState::BROKEN, "The signature must not be broken at this place" );
 
-            // TODO/LATER: in future the medium must control own signature state, not the document
-            pNewMed->SetCachedSignatureState_Impl( SignatureState::NOSIGNATURES ); // set the default value back
+                // TODO/LATER: in future the medium must control own signature state, not the document
+                pNewMed->SetCachedSignatureState_Impl( SignatureState::NOSIGNATURES ); // set the default value back
+            }
+            else
+                pNewMed->SetCachedSignatureState_Impl( pImpl->nScriptingSignatureState );
 
             // Set new title
             if (!pNewMed->GetName().isEmpty() && SfxObjectCreateMode::EMBEDDED != eCreateMode)
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
index 2f3ed41e2dfb..60a21f3944e1 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -71,4 +71,8 @@ $(call gb_CppunitTest_get_target,xmlsecurity_signing): \
 endif
 endif
 
+$(eval $(call gb_CppunitTest_use_custom_headers,xmlsecurity_signing,\
+    officecfg/registry \
+))
+
 # vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316.ott b/xmlsecurity/qa/unit/signing/data/tdf42316.ott
new file mode 100644
index 000000000000..95162a627176
Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf42316.ott differ
diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott
new file mode 100644
index 000000000000..ecff48709109
Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
index 6b124654a292..a5b1ed276ff0 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -18,13 +18,15 @@
 #include <unotest/macros_test.hxx>
 #include <test/xmltesttools.hxx>
 
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/MacroExecMode.hpp>
 #include <com/sun/star/embed/XStorage.hpp>
 #include <com/sun/star/embed/XTransactedObject.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
-#include <com/sun/star/xml/crypto/SEInitializer.hpp>
 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
 
 #include <comphelper/processfactory.hxx>
 #include <comphelper/propertysequence.hxx>
@@ -36,12 +38,17 @@
 #include <sfx2/objsh.hxx>
 #include <osl/file.hxx>
 #include <osl/process.h>
+#include <comphelper/sequence.hxx>
 #include <comphelper/ofopxmlhelper.hxx>
 
 #include <documentsignaturehelper.hxx>
 #include <xmlsignaturehelper.hxx>
 #include <documentsignaturemanager.hxx>
 #include <certificate.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <comphelper/configuration.hxx>
 
 using namespace com::sun::star;
 
@@ -150,7 +157,9 @@ public:
 private:
     void createDoc(const OUString& rURL);
     void createCalc(const OUString& rURL);
-    uno::Reference<security::XCertificate> getCertificate(DocumentSignatureManager& rSignatureManager, svl::crypto::SignatureMethodAlgorithm eAlgo);
+    SfxObjectShell* assertDocument(const ::CppUnit::SourceLine aSrcLine,
+                                   const OUString& rFilterName, const SignatureState nDocSign,
+                                   const SignatureState nMacroSign, const OUString& sVersion);
 };
 
 SigningTest::SigningTest()
@@ -810,6 +819,239 @@ void SigningTest::testODFEncryptedGPG()
 
 #endif
 
+SfxObjectShell* SigningTest::assertDocument(const ::CppUnit::SourceLine aSrcLine,
+                                            const OUString& rFilterName,
+                                            const SignatureState nDocSign,
+                                            const SignatureState nMacroSign,
+                                            const OUString& sVersion)
+{
+    std::string sPos = aSrcLine.fileName() + ":" + OString::number(aSrcLine.lineNumber()).getStr();
+
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT_MESSAGE(sPos, pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT_MESSAGE(sPos, pObjectShell);
+
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, rFilterName,
+                                 pObjectShell->GetMedium()->GetFilter()->GetFilterName());
+    SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, nDocSign, nActual);
+    nActual = pObjectShell->GetScriptingSignatureState();
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, nMacroSign, nActual);
+
+    OUString aODFVersion;
+    uno::Reference<beans::XPropertySet> xPropSet(pObjectShell->GetStorage(), uno::UNO_QUERY_THROW);
+    xPropSet->getPropertyValue("Version") >>= aODFVersion;
+    CPPUNIT_ASSERT_EQUAL(sVersion, aODFVersion);
+
+    return pObjectShell;
+}
+
+/// Test if a macro signature from a OTT 1.2 template is preserved for ODT 1.2
+CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature12)
+{
+    const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316_odt12.ott");
+    const OUString sLoadMessage = "loading failed: " + aURL;
+
+    // load the template as-is to validate signatures
+    mxComponent = loadFromDesktop(
+        aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+    CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+                           mxComponent.is());
+
+    // we are a template, and have a valid document and macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::OK, SignatureState::OK,
+                   ODFVER_012_TEXT);
+    mxComponent->dispose();
+
+    // create new document from template
+    // we can't use createDoc / MacrosTest::loadFromDesktop, because ALWAYS_EXECUTE_NO_WARN
+    // won't verify the signature for templates, so the resulting document won't be able to
+    // preserve the templates signature.
+    mxComponent = mxDesktop->loadComponentFromURL(
+        aURL, "_default", 0,
+        comphelper::InitPropertySequence(
+            { { "MacroExecutionMode",
+                uno::Any(document::MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN) } }));
+    CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+                           mxComponent.is());
+
+    // we are somehow a template (?), and have just a valid macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+                   SignatureState::OK, ODFVER_012_TEXT);
+
+    // save as new ODT document
+    utl::TempFile aTempFileSaveAs;
+    aTempFileSaveAs.EnableKillingFile();
+    try
+    {
+        uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+        uno::Sequence<beans::PropertyValue> descSaveAs(
+            comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+        xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs);
+    }
+    catch (...)
+    {
+        CPPUNIT_FAIL("Failed to save ODT document");
+    }
+
+    // load saved document
+    createDoc(aTempFileSaveAs.GetURL());
+
+    // the loaded document is a ODT with a macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES,
+                   SignatureState::OK, ODFVER_012_TEXT);
+}
+
+/// Test if a macro signature from an OTT 1.0 is dropped for ODT 1.2
+CPPUNIT_TEST_FIXTURE(SigningTest, testDropMacroTemplateSignature)
+{
+    const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316.ott");
+    const OUString sLoadMessage = "loading failed: " + aURL;
+
+    // load the template as-is to validate signatures
+    mxComponent = loadFromDesktop(
+        aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+    CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+                           mxComponent.is());
+
+    // we are a template, and have a valid document and macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+                   SignatureState::NOTVALIDATED, OUString());
+    mxComponent->dispose();
+
+    // create new document from template
+    // we can't use createDoc / MacrosTest::loadFromDesktop, because ALWAYS_EXECUTE_NO_WARN
+    // won't verify the signature for templates, so the resulting document won't be able to
+    // preserve the templates signature.
+    mxComponent = mxDesktop->loadComponentFromURL(
+        aURL, "_default", 0,
+        comphelper::InitPropertySequence(
+            { { "MacroExecutionMode",
+                uno::Any(document::MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN) } }));
+    CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+                           mxComponent.is());
+
+    // we are somehow a template (?), and have just a valid macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+                   SignatureState::NOTVALIDATED, OUString());
+
+    // save as new ODT document
+    utl::TempFile aTempFileSaveAs;
+    aTempFileSaveAs.EnableKillingFile();
+    try
+    {
+        uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+        uno::Sequence<beans::PropertyValue> descSaveAs(
+            comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+        xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs);
+    }
+    catch (...)
+    {
+        CPPUNIT_FAIL("Failed to save ODT document");
+    }
+
+    // load saved document
+    createDoc(aTempFileSaveAs.GetURL());
+
+    // the loaded document is a 1.2 ODT without any signatures
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES,
+                   SignatureState::NOSIGNATURES, ODFVER_012_TEXT);
+}
+
+class Resetter
+{
+private:
+    std::function<void()> m_Func;
+
+public:
+    Resetter(std::function<void()> const& rFunc)
+        : m_Func(rFunc)
+    {
+    }
+    ~Resetter()
+    {
+        try
+        {
+            m_Func();
+        }
+        catch (...) // has to be reliable
+        {
+            fprintf(stderr, "resetter failed with exception\n");
+            abort();
+        }
+    }
+};
+
+/// Test if a macro signature from a OTT 1.0 template is preserved for ODT 1.0
+CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature10)
+{
+    // set ODF version 1.0 / 1.1 as default
+    Resetter _([]() {
+        std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+            comphelper::ConfigurationChanges::create());
+        officecfg::Office::Common::Save::ODF::DefaultVersion::set(3, pBatch);
+        return pBatch->commit();
+    });
+    std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+        comphelper::ConfigurationChanges::create());
+    officecfg::Office::Common::Save::ODF::DefaultVersion::set(2, pBatch);
+    pBatch->commit();
+
+    const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316.ott");
+    const OUString sLoadMessage = "loading failed: " + aURL;
+
+    // load the template as-is to validate signatures
+    mxComponent = loadFromDesktop(
+        aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+    CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+                           mxComponent.is());
+
+    // we are a template, and have a valid document and macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+                   SignatureState::NOTVALIDATED, OUString());
+
+    mxComponent->dispose();
+
+    // create new document from template
+    // we can't use createDoc / MacrosTest::loadFromDesktop, because ALWAYS_EXECUTE_NO_WARN
+    // won't verify the signature for templates, so the resulting document won't be able to
+    // preserve the templates signature.
+    mxComponent = mxDesktop->loadComponentFromURL(
+        aURL, "_default", 0,
+        comphelper::InitPropertySequence(
+            { { "MacroExecutionMode",
+                uno::Any(document::MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN) } }));
+    CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+                           mxComponent.is());
+
+    // we are somehow a template (?), and have just a valid macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+                   SignatureState::NOTVALIDATED, OUString());
+
+    // save as new ODT document
+    utl::TempFile aTempFileSaveAs;
+    aTempFileSaveAs.EnableKillingFile();
+    try
+    {
+        uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+        uno::Sequence<beans::PropertyValue> descSaveAs(
+            comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+        xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs);
+    }
+    catch (...)
+    {
+        CPPUNIT_FAIL("Failed to save ODT document");
+    }
+
+    // load saved document
+    createDoc(aTempFileSaveAs.GetURL());
+
+    // the loaded document is a ODT with a macro signature
+    assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES,
+                   SignatureState::NOTVALIDATED, OUString());
+}
+
 #endif
 
 void SigningTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)


More information about the Libreoffice-commits mailing list