include/sfx2/digitalsignatures.hxx | 5 + officecfg/registry/schema/org/openoffice/Office/Common.xcs | 7 + sfx2/source/doc/docfile.cxx | 32 ++++++ xmlsecurity/inc/UriBindingHelper.hxx | 10 +- xmlsecurity/inc/digitalsignaturesdialog.hxx | 2 xmlsecurity/inc/documentsignaturemanager.hxx | 7 + xmlsecurity/inc/xmlsignaturehelper.hxx | 3 xmlsecurity/qa/unit/signing/data/macro.odt |binary xmlsecurity/qa/unit/signing/signing.cxx | 62 +++++++++++++ xmlsecurity/source/component/documentdigitalsignatures.cxx | 12 ++ xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx | 39 +++++++- xmlsecurity/source/helper/UriBindingHelper.cxx | 29 +++++- xmlsecurity/source/helper/documentsignaturemanager.cxx | 9 + xmlsecurity/source/helper/xmlsignaturehelper.cxx | 5 - 14 files changed, 210 insertions(+), 12 deletions(-)
New commits: commit e5a0209d4b1e1f09191a442e04d626b21c49b9df Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Sep 12 15:29:33 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Sep 12 16:53:06 2024 +0200 cool#9992 lok doc sign: allow sign of macros & the document itself in one step Sign a document with macros (via file -> digital signatures -> digital signatures), realize that you still get a warning on file open, sign the macros in the document (via tools -> macros -> digital signature), realize that you did this in the wrong order, so now you have to re-sign the doc content. The reason for this is that the macro signature only signs the macro parts of the document (so you can still edit the document and the signature is valid, as long as you don't touch macros), while the doc content signature signs everything, including the macro signature, so the order of the two matters. Solve this trouble by adding a new setting that allows doing the two signatures in one step. Do this by extending the doc content signing code with an optional pre-step that first signs the document macros. This is a bit tricky to do, since xmlsecurity/ gets an RW signature stream and a RO document storage from sfx2/, but transferring one more signature stream can solve this trouble. Other tricky parts of the change: 1) The crypto signing is always done by libxmlsec, so DigitalSignaturesDialog::SetScriptingSignatureStream() has to update the storage of the sign manager's sign helper, otherwise, the hashes in the macro signature will be empty. 2) Signing reads the RO storage, so normally the macro signature would not be part of the doc signature when creating both signatures inside a single dialog. (The storage is only committed after the dialog ends.) Fix this problem by extending DocumentSignatureManager::add() and UriBindingHelper::OpenInputStream() to provide kind of an overlay when xmlsecurity/ gets a script signature stream: this way the macro signature will be part of the doc signature while the dialog is in progress. No overlay is needed later, once both streams are committed to the storage on dialog end. Change-Id: Ic2728689997165595991d5ec59c7a2683286e22d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173263 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/include/sfx2/digitalsignatures.hxx b/include/sfx2/digitalsignatures.hxx index b364c9518931..856e1c5bf61a 100644 --- a/include/sfx2/digitalsignatures.hxx +++ b/include/sfx2/digitalsignatures.hxx @@ -45,6 +45,11 @@ public: const std::function<void(bool)>& rCallback) = 0; + /// Create a scripting signature before creating a document signature. + virtual void + SetSignScriptingContent(const css::uno::Reference<css::io::XStream>& xScriptingSignStream) + = 0; + protected: ~DigitalSignatures() noexcept = default; }; diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs index 068df683a2c5..3c60f6f38252 100644 --- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs +++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs @@ -2358,6 +2358,13 @@ </info> <value>true</value> </prop> + <prop oor:name="ImplicitScriptSign" oor:type="xs:boolean" oor:nillable="false"> + <info> + <desc>Specifies whether to implicitly sign macros when adding the first signature + to an ODF document with macros.</desc> + </info> + <value>false</value> + </prop> <prop oor:name="CertDir" oor:type="xs:string"> <info> <desc>Contains the path to the users NSS certificate directory.</desc> diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx index acef518d97f9..441ae3b432f6 100644 --- a/sfx2/source/doc/docfile.cxx +++ b/sfx2/source/doc/docfile.cxx @@ -4439,12 +4439,39 @@ void SfxMedium::SignContents_Impl(weld::Window* pDialogParent, } else { + // Signing the entire document. if (xMetaInf.is()) { // ODF. uno::Reference< io::XStream > xStream; + uno::Reference< io::XStream > xScriptingStream; if (GetFilter() && GetFilter()->IsOwnFormat()) + { + bool bImplicitScriptSign = officecfg::Office::Common::Security::Scripting::ImplicitScriptSign::get(); + if (comphelper::LibreOfficeKit::isActive()) + { + bImplicitScriptSign = true; + } + + OUString aDocSigName = xSigner->getDocumentContentSignatureDefaultStreamName(); + bool bHasSignatures = xMetaInf->hasByName(aDocSigName); + + // C.f. DocumentSignatureHelper::CreateElementList() for the + // DocumentSignatureMode::Macros case. + bool bHasMacros = xWriteableZipStor->hasByName(u"Basic"_ustr) + || xWriteableZipStor->hasByName(u"Dialogs"_ustr) + || xWriteableZipStor->hasByName(u"Scripts"_ustr); + xStream.set(xMetaInf->openStreamElement(xSigner->getDocumentContentSignatureDefaultStreamName(), embed::ElementModes::READWRITE), uno::UNO_SET_THROW); + if (bImplicitScriptSign && bHasMacros && !bHasSignatures) + { + xScriptingStream.set( + xMetaInf->openStreamElement( + xSigner->getScriptingContentSignatureDefaultStreamName(), + embed::ElementModes::READWRITE), + uno::UNO_SET_THROW); + } + } bool bSuccess = false; auto onODFSignDocumentContentFinished = [this, xMetaInf, xWriteableZipStor]() { @@ -4462,6 +4489,11 @@ void SfxMedium::SignContents_Impl(weld::Window* pDialogParent, xValidGraphic, xInvalidGraphic, aComment); else { + if (xScriptingStream.is()) + { + xModelSigner->SetSignScriptingContent(xScriptingStream); + } + // Async, all code before return has to go into the callback. xModelSigner->SignDocumentContentAsync(GetZipStorageToSign_Impl(), xStream, [onODFSignDocumentContentFinished, onSignDocumentContentFinished](bool bRet) { diff --git a/xmlsecurity/inc/UriBindingHelper.hxx b/xmlsecurity/inc/UriBindingHelper.hxx index 67c9ae69f8ba..f8a07d4d4264 100644 --- a/xmlsecurity/inc/UriBindingHelper.hxx +++ b/xmlsecurity/inc/UriBindingHelper.hxx @@ -26,7 +26,10 @@ #include <com/sun/star/xml/crypto/XUriBinding.hpp> namespace com::sun::star { - namespace io { class XInputStream; } + namespace io { + class XStream; + class XInputStream; + } namespace embed { class XStorage; } } @@ -36,16 +39,17 @@ class UriBindingHelper final : public cppu::WeakImplHelper< css::xml::crypto::XU { private: css::uno::Reference < css::embed::XStorage > mxStorage; + css::uno::Reference<css::io::XStream> mxScriptingSignatureStream; public: UriBindingHelper(); - explicit UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage ); + explicit UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage, const css::uno::Reference<css::io::XStream>& xScriptingSignatureStream ); void SAL_CALL setUriBinding( const OUString& uri, const css::uno::Reference< css::io::XInputStream >& aInputStream ) override; css::uno::Reference< css::io::XInputStream > SAL_CALL getUriBinding( const OUString& uri ) override; - static css::uno::Reference < css::io::XInputStream > OpenInputStream( const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& rURI ); + static css::uno::Reference < css::io::XInputStream > OpenInputStream( const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& rURI, const css::uno::Reference<css::io::XStream>& xScriptingSignatureStream ); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx index 3f515a36706d..a56175fff5b4 100644 --- a/xmlsecurity/inc/digitalsignaturesdialog.hxx +++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx @@ -39,6 +39,7 @@ class DigitalSignaturesDialog final : public weld::GenericDialogController { private: DocumentSignatureManager maSignatureManager; + std::optional<DocumentSignatureManager> moScriptSignatureManager; bool mbVerifySignatures; bool mbSignaturesChanged; @@ -108,6 +109,7 @@ public: // Set the storage which should be signed or verified void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ); void SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ); + void SetScriptingSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ); // Execute the dialog... void beforeRun(); diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx index 9f0c5d61f9e2..a66d97e3c7dd 100644 --- a/xmlsecurity/inc/documentsignaturemanager.hxx +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -68,6 +68,7 @@ private: DocumentSignatureMode const meSignatureMode; css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> m_manifest; css::uno::Reference<css::io::XStream> mxSignatureStream; + css::uno::Reference<css::io::XStream> mxScriptingSignatureStream; css::uno::Reference<css::frame::XModel> mxModel; rtl::Reference<utl::TempFileFastService> mxTempSignatureStream; /// Storage containing all OOXML signatures, unused for ODF. @@ -126,6 +127,12 @@ public: { mxSignatureStream = xSignatureStream; } + css::uno::Reference<css::io::XStream> getSignatureStream() const { return mxSignatureStream; } + void setScriptingSignatureStream( + const css::uno::Reference<css::io::XStream>& xScriptingSignatureStream) + { + mxScriptingSignatureStream = xScriptingSignatureStream; + } void setModel(const css::uno::Reference<css::frame::XModel>& xModel); const css::uno::Reference<css::embed::XStorage>& getStore() const { return mxStore; } DocumentSignatureMode getSignatureMode() const { return meSignatureMode; } diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx index d3c5479e4b61..cf31636cac74 100644 --- a/xmlsecurity/inc/xmlsignaturehelper.hxx +++ b/xmlsecurity/inc/xmlsignaturehelper.hxx @@ -36,6 +36,7 @@ namespace com::sun::star { namespace io { class XOutputStream; class XInputStream; + class XStream; } namespace embed { class XStorage; } } @@ -82,7 +83,7 @@ public: // Set the storage which should be used by the default UriBinding // Must be set before StartMission(). //sODFVersion indicates the ODF version - XMLSECURITY_DLLPUBLIC void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStorage, std::u16string_view sODFVersion ); + XMLSECURITY_DLLPUBLIC void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStorage, std::u16string_view sODFVersion, const css::uno::Reference<css::io::XStream>& xScriptStream = css::uno::Reference<css::io::XStream>() ); // Argument for the Link is a uno::Reference< xml::sax::XAttributeList >* // Return 1 to verify, 0 to skip. diff --git a/xmlsecurity/qa/unit/signing/data/macro.odt b/xmlsecurity/qa/unit/signing/data/macro.odt new file mode 100644 index 000000000000..b6e470076bef Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/macro.odt differ diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx index 038bf78ce193..5646a2afa6b6 100644 --- a/xmlsecurity/qa/unit/signing/signing.cxx +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -1149,6 +1149,68 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineODF) CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); } +CPPUNIT_TEST_FIXTURE(SigningTest, testImplicitScriptSign) +{ + // Given an ODT file with macros, and two signature managers to create macro + doc signatures: + OUString aFileURL = createFileURL(u"macro.odt"); + uno::Reference<embed::XStorage> xWriteableZipStor + = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aFileURL, + embed::ElementModes::READWRITE); + uno::Reference<embed::XStorage> xMetaInf + = xWriteableZipStor->openStorageElement(u"META-INF"_ustr, embed::ElementModes::READWRITE); + uno::Reference<io::XStream> xStream = xMetaInf->openStreamElement( + u"documentsignatures.xml"_ustr, embed::ElementModes::READWRITE); + uno::Reference<io::XStream> xScriptingStream + = xMetaInf->openStreamElement(u"macrosignatures.xml"_ustr, embed::ElementModes::READWRITE); + uno::Reference<embed::XStorage> xZipStor + = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aFileURL, + embed::ElementModes::READ); + DocumentSignatureManager aManager(m_xContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + aManager.setStore(xZipStor); + aManager.setSignatureStream(xStream); + aManager.getSignatureHelper().SetStorage(xZipStor, u"1.2", xScriptingStream); + DocumentSignatureManager aScriptManager(m_xContext, DocumentSignatureMode::Macros); + CPPUNIT_ASSERT(aScriptManager.init()); + aScriptManager.setStore(xZipStor); + aScriptManager.getSignatureHelper().SetStorage(xZipStor, u"1.2"); + aScriptManager.setSignatureStream(xScriptingStream); + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + + // When adding those signatures and writing them to the streams from the read-write storage: + OUString aDescription; + sal_Int32 nSecurityId; + bool bAdESCompliant = true; + aScriptManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, bAdESCompliant); + aScriptManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + aScriptManager.write(bAdESCompliant); + aManager.setScriptingSignatureStream(xScriptingStream); + aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, bAdESCompliant); + aManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + aManager.write(bAdESCompliant); + + // Then make sure both signatures are created correctly: + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xScriptingStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + OUString aScriptDigest = getXPathContent( + pXmlDoc, "/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/" + "dsig:Reference[@URI='Basic/script-lc.xml']/dsig:DigestValue"_ostr); + // Without the accompanying fix in place, this test would have failed, the digest value was just a + // " " placeholder. + CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(1), aScriptDigest.getLength()); + pStream = utl::UcbStreamHelper::CreateStream(xStream, true); + pXmlDoc = parseXmlStream(pStream.get()); + // Without the accompanying fix in place, this test would have failed, the macro signature was + // not part of the signed data of the document signature. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/" + "dsig:Reference[@URI='META-INF/macrosignatures.xml']"_ostr, + 1); +} + #if HAVE_FEATURE_GPGVERIFY /// Test a typical ODF where all streams are GPG-signed. CPPUNIT_TEST_FIXTURE(SigningTest, testODFGoodGPG) diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index 5cd2e6e5bb44..9c89b293bb39 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -70,6 +70,7 @@ class DocumentDigitalSignatures private: css::uno::Reference<css::uno::XComponentContext> mxCtx; css::uno::Reference<css::awt::XWindow> mxParentWindow; + uno::Reference<io::XStream> mxScriptingSignStream; /// will be set by XInitialization. If not we assume true. false means an earlier version (whatever that means, /// this is a string, not a boolean). @@ -221,6 +222,10 @@ public: void SignScriptingContentAsync(const css::uno::Reference<css::embed::XStorage>& xStorage, const css::uno::Reference<css::io::XStream>& xSignStream, const std::function<void(bool)>& rCallback) override; + + /// See sfx2::DigitalSignatures::SetSignScriptingContent(). + void SetSignScriptingContent( + const css::uno::Reference<css::io::XStream>& xScriptingSignStream) override; }; } @@ -444,6 +449,7 @@ void DocumentDigitalSignatures::ImplViewSignatures( xSignaturesDialog->SetStorage(rxStorage); xSignaturesDialog->SetSignatureStream( xSignStream ); + xSignaturesDialog->SetScriptingSignatureStream( mxScriptingSignStream ); xSignaturesDialog->beforeRun(); weld::DialogController::runAsync(xSignaturesDialog, [xSignaturesDialog, rxStorage, xSignStream, rCallback] (sal_Int32 nRet) { @@ -849,6 +855,12 @@ void DocumentDigitalSignatures::SignScriptingContentAsync( ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Macros, false, rCallback ); } +void DocumentDigitalSignatures::SetSignScriptingContent( + const css::uno::Reference<css::io::XStream>& xScriptingSignStream) +{ + mxScriptingSignStream = xScriptingSignStream; +} + sal_Bool DocumentDigitalSignatures::signPackageWithCertificate( css::uno::Reference<css::security::XCertificate> const& xCertificate, css::uno::Reference<css::embed::XStorage> const& xStorage, diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx index 9c3081cdca34..0b1173f70e7a 100644 --- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -311,7 +311,7 @@ void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed || !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); maSignatureManager.setStore(rxStore); - maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion); + maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion, {}); } void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ) @@ -319,6 +319,26 @@ void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < cs maSignatureManager.setSignatureStream(rxStream); } +void DigitalSignaturesDialog::SetScriptingSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ) +{ + if (!rxStream.is()) + { + return; + } + + uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext(); + moScriptSignatureManager.emplace(xContext, DocumentSignatureMode::Macros); + if (!moScriptSignatureManager->init()) + { + return; + } + moScriptSignatureManager->setStore(maSignatureManager.getStore()); + // This is the storage used by UriBindingHelper::getUriBinding(). + moScriptSignatureManager->getSignatureHelper().SetStorage(maSignatureManager.getStore(), m_sODFVersion); + maSignatureManager.getSignatureHelper().SetStorage(maSignatureManager.getStore(), m_sODFVersion, rxStream); + moScriptSignatureManager->setSignatureStream(rxStream); +} + bool DigitalSignaturesDialog::canAddRemove() { //FIXME: this func needs some cleanup, such as real split between @@ -469,6 +489,23 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) while (aChooser->run() == RET_OK) { sal_Int32 nSecurityId; + + if (moScriptSignatureManager) + { + if (!moScriptSignatureManager->add(aChooser->GetSelectedCertificates()[0], + aChooser->GetSelectedSecurityContext(), + aChooser->GetDescription(), nSecurityId, + m_bAdESCompliant)) + { + return; + } + + moScriptSignatureManager->read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + moScriptSignatureManager->write(m_bAdESCompliant); + + maSignatureManager.setScriptingSignatureStream(moScriptSignatureManager->getSignatureStream()); + } + if (!maSignatureManager.add(aChooser->GetSelectedCertificates()[0], aChooser->GetSelectedSecurityContext(), aChooser->GetDescription(), nSecurityId, m_bAdESCompliant)) return; diff --git a/xmlsecurity/source/helper/UriBindingHelper.cxx b/xmlsecurity/source/helper/UriBindingHelper.cxx index 52cf6d07a4fa..86948b682aee 100644 --- a/xmlsecurity/source/helper/UriBindingHelper.cxx +++ b/xmlsecurity/source/helper/UriBindingHelper.cxx @@ -28,6 +28,8 @@ #include <rtl/uri.hxx> #include <sal/log.hxx> +#include <documentsignaturehelper.hxx> + using namespace com::sun::star; // XUriBinding @@ -36,9 +38,10 @@ UriBindingHelper::UriBindingHelper() { } -UriBindingHelper::UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage ) +UriBindingHelper::UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage, const uno::Reference<io::XStream>& xScriptingSignatureStream ) { mxStorage = rxStorage; + mxScriptingSignatureStream = xScriptingSignatureStream; } void SAL_CALL UriBindingHelper::setUriBinding( const OUString& /*uri*/, const uno::Reference< io::XInputStream >&) @@ -50,7 +53,7 @@ uno::Reference< io::XInputStream > SAL_CALL UriBindingHelper::getUriBinding( con uno::Reference< io::XInputStream > xInputStream; if ( mxStorage.is() ) { - xInputStream = OpenInputStream( mxStorage, uri ); + xInputStream = OpenInputStream( mxStorage, uri, mxScriptingSignatureStream ); } else { @@ -60,7 +63,7 @@ uno::Reference< io::XInputStream > SAL_CALL UriBindingHelper::getUriBinding( con return xInputStream; } -uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno::Reference < embed::XStorage >& rxStore, const OUString& rURI ) +uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno::Reference < embed::XStorage >& rxStore, const OUString& rURI, const css::uno::Reference<css::io::XStream>& xScriptingSignatureStream ) { OSL_ASSERT(!rURI.isEmpty()); uno::Reference < io::XInputStream > xInStream; @@ -87,7 +90,23 @@ uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno uno::Reference< io::XStream > xStream; if (!rxStore->hasByName(sName)) - SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << sName); + { + if (xScriptingSignatureStream.is() && sName == DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName()) + { + xStream = xScriptingSignatureStream; + uno::Reference<io::XSeekable> xSeekable(xScriptingSignatureStream, uno::UNO_QUERY); + if (xSeekable.is()) + { + // Cloned streams are always positioned at the start, do the same in the overlay + // case. + xSeekable->seek(0); + } + } + else + { + SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << sName); + } + } else xStream = rxStore->cloneStreamElement( sName ); if ( !xStream.is() ) @@ -103,7 +122,7 @@ uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno OUString aElement = aURI.copy( nSepPos+1 ); uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ ); - xInStream = OpenInputStream( xSubStore, aElement ); + xInStream = OpenInputStream( xSubStore, aElement, xScriptingSignatureStream ); } return xInStream; } diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx index f3931a9cdd31..d74c9a12f900 100644 --- a/xmlsecurity/source/helper/documentsignaturemanager.cxx +++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx @@ -436,6 +436,15 @@ bool DocumentSignatureManager::add( std::vector<OUString> aElements = DocumentSignatureHelper::CreateElementList( mxStore, meSignatureMode, DocumentSignatureAlgorithm::OOo3_2); + + if (mxScriptingSignatureStream.is()) + { + aElements.emplace_back( + u"META-INF/"_ustr + + DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName()); + std::sort(aElements.begin(), aElements.end()); + } + DocumentSignatureHelper::AppendContentTypes(mxStore, aElements); for (OUString const& rUri : aElements) diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx index 71c6ebdbce56..1510af12a83a 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -70,10 +70,11 @@ XMLSignatureHelper::~XMLSignatureHelper() void XMLSignatureHelper::SetStorage( const Reference < css::embed::XStorage >& rxStorage, - std::u16string_view sODFVersion) + std::u16string_view sODFVersion, + const css::uno::Reference<css::io::XStream>& xScriptStream) { SAL_WARN_IF( mxUriBinding.is(), "xmlsecurity.helper", "SetStorage - UriBinding already set!" ); - mxUriBinding = new UriBindingHelper( rxStorage ); + mxUriBinding = new UriBindingHelper( rxStorage, xScriptStream ); SAL_WARN_IF(!rxStorage.is(), "xmlsecurity.helper", "SetStorage - empty storage!"); mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion); }