diff options
author | Jan-Marek Glogowski <jan-marek.glogowski@extern.cib.de> | 2019-07-19 15:28:45 +0200 |
---|---|---|
committer | Vasily Melenchuk <vasily.melenchuk@cib.de> | 2021-04-15 12:12:49 +0300 |
commit | d5195a73629eff2035152eea7e5c936f3f4baaa9 (patch) | |
tree | 8703db2f7b429519e8d641f77a26aa082e161e1e /xmlsecurity/qa/unit/signing/signing.cxx | |
parent | cc4987d3e566db2c4aa0675ae94f6c2f713d8a0a (diff) |
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@cib.de>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@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@CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'xmlsecurity/qa/unit/signing/signing.cxx')
-rw-r--r-- | xmlsecurity/qa/unit/signing/signing.cxx | 252 |
1 files changed, 251 insertions, 1 deletions
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx index b2781ccf714f..a7ad9c147c08 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,6 +38,7 @@ #include <sfx2/objsh.hxx> #include <osl/file.hxx> #include <osl/process.h> +#include <comphelper/sequence.hxx> #include <comphelper/ofopxmlhelper.hxx> #include <unotools/streamwrap.hxx> @@ -44,6 +47,10 @@ #include <documentsignaturemanager.hxx> #include <certificate.hxx> #include <xsecctl.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <officecfg/Office/Common.hxx> +#include <comphelper/configuration.hxx> using namespace com::sun::star; @@ -125,6 +132,10 @@ public: void testODFEncryptedGPG(); #endif #endif + void testPreserveMacroTemplateSignature12(); + void testDropMacroTemplateSignature(); + void testPreserveMacroTemplateSignature10(); + CPPUNIT_TEST_SUITE(SigningTest); CPPUNIT_TEST(testDescription); CPPUNIT_TEST(testECDSA); @@ -158,10 +169,13 @@ public: CPPUNIT_TEST(testODFUntrustedGoodGPG); CPPUNIT_TEST(testODFBrokenStreamGPG); CPPUNIT_TEST(testODFBrokenDsigGPG); + CPPUNIT_TEST(testPreserveMacroTemplateSignature12); #if HAVE_GPGCONF_SOCKETDIR CPPUNIT_TEST(testODFEncryptedGPG); #endif #endif + CPPUNIT_TEST(testDropMacroTemplateSignature); + CPPUNIT_TEST(testPreserveMacroTemplateSignature10); CPPUNIT_TEST_SUITE_END(); private: @@ -170,6 +184,9 @@ private: 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() {} @@ -1062,6 +1079,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 +void 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 +void 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 +void 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()); +} + void SigningTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) { xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"), |