summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sfx2/source/doc/objstor.cxx30
-rw-r--r--xmlsecurity/CppunitTest_xmlsecurity_signing.mk4
-rw-r--r--xmlsecurity/qa/unit/signing/data/tdf42316.ottbin0 -> 10242 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ottbin0 -> 14625 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/signing.cxx245
5 files changed, 271 insertions, 8 deletions
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 9375989e35e3..f3ef1c2992a3 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -1167,10 +1167,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)
);
}
@@ -2017,13 +2025,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 418aa21a27c9..84e7a76c043b 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -60,4 +60,8 @@ $(call gb_CppunitTest_get_target,xmlsecurity_signing): \
LIBO_LD_PATH=$$LD_LIBRARY_PATH
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
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/tdf42316.ott
Binary files 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
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
index e316a4dc7ef9..87411c7afa72 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>
@@ -37,6 +39,7 @@
#include <osl/file.hxx>
#include <osl/process.h>
#include <osl/thread.hxx>
+#include <comphelper/sequence.hxx>
#include <comphelper/ofopxmlhelper.hxx>
#include <unotools/streamwrap.hxx>
@@ -45,6 +48,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;
@@ -78,6 +85,9 @@ protected:
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() {}
@@ -955,6 +965,239 @@ CPPUNIT_TEST_FIXTURE(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)