diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 9913d021fdf7..3f20dc65ec04 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -6836,6 +6837,12 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo pDoc->getCommandValues(aJsonWriter, aCommand); return convertOString(aJsonWriter.finishAndGetAsOString()); } + else if (SfxLokHelper::supportsCommand(INetURLObject(OUString::fromUtf8(aCommand)).GetURLPath())) + { + tools::JsonWriter aJsonWriter; + SfxLokHelper::getCommandValues(aJsonWriter, aCommand); + return convertOString(aJsonWriter.finishAndGetAsOString()); + } else { SetLastExceptionMsg(OUString::fromUtf8(aCommand) + u" : Unknown command, no values returned"_ustr); @@ -7272,7 +7279,9 @@ static bool doc_insertCertificate(LibreOfficeKitDocument* pThis, SolarMutexGuard aGuard; - return pObjectShell->SignDocumentContentUsingCertificate(xCertificate); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + return pObjectShell->SignDocumentContentUsingCertificate(aSigningContext); } static bool doc_addCertificate(LibreOfficeKitDocument* pThis, diff --git a/include/sfx2/digitalsignatures.hxx b/include/sfx2/digitalsignatures.hxx index 84b77fd759dd..fe5f2bc97874 100644 --- a/include/sfx2/digitalsignatures.hxx +++ b/include/sfx2/digitalsignatures.hxx @@ -19,6 +19,10 @@ #include class SfxViewShell; +namespace svl::crypto +{ +class SigningContext; +} namespace sfx2 { @@ -27,11 +31,10 @@ class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") Digita { public: /// Same as signDocumentWithCertificate(), but passes the xModel as well. - virtual bool - SignModelWithCertificate(const css::uno::Reference& xModel, - const css::uno::Reference& xCertificate, - const css::uno::Reference& xStorage, - const css::uno::Reference& xStream) + virtual bool SignModelWithCertificate(const css::uno::Reference& xModel, + svl::crypto::SigningContext& rSigningContext, + const css::uno::Reference& xStorage, + const css::uno::Reference& xStream) = 0; /// Async replacement for signDocumentContent(). diff --git a/include/sfx2/docfile.hxx b/include/sfx2/docfile.hxx index 9725a71340e5..ccf143c7e2a2 100644 --- a/include/sfx2/docfile.hxx +++ b/include/sfx2/docfile.hxx @@ -47,6 +47,7 @@ namespace com::sun::star::frame class XModel; } namespace ucbhelper { class Content; } +namespace svl::crypto { class SigningContext; } class SvKeyValueIterator; class SfxFilter; @@ -289,7 +290,7 @@ public: SAL_DLLPRIVATE bool SignDocumentContentUsingCertificate( const css::uno::Reference& xModel, bool bHasValidDocumentSignature, - const css::uno::Reference& xCertificate); + svl::crypto::SigningContext& rSigningContext); // the following two methods must be used and make sense only during saving currently // TODO/LATER: in future the signature state should be controlled by the medium not by the document diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index bdf7d0816786..a35670332097 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -249,6 +249,10 @@ public: static void addCertificates(const std::vector& rCerts); /// Parses a private key + certificate pair. static css::uno::Reference getSigningCertificate(const std::string& rCert, const std::string& rKey); + /// Decides if it's OK to call getCommandValues(rCommand). + static bool supportsCommand(std::u16string_view rCommand); + /// Returns information about a given command in JSON format. + static void getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand); private: static int createView(SfxViewFrame& rViewFrame, ViewShellDocId docId); diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index 14855e8b62f0..7e6682c57bee 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -147,6 +147,7 @@ namespace o3tl } namespace weld { class Window; } +namespace svl::crypto { class SigningContext; } enum class HiddenWarningFact { @@ -368,7 +369,7 @@ public: const css::uno::Reference& xSigner = css::uno::Reference()); - bool SignDocumentContentUsingCertificate(const css::uno::Reference& xCertificate); + bool SignDocumentContentUsingCertificate(svl::crypto::SigningContext& rSigningContext); bool ResignDocument(css::uno::Sequence< css::security::DocumentSignatureInformation >& rSignaturesInfo); void SignSignatureLine(weld::Window* pDialogParent, const OUString& aSignatureLineId, diff --git a/include/svl/cryptosign.hxx b/include/svl/cryptosign.hxx index 3bb682916edc..a558690bbf48 100644 --- a/include/svl/cryptosign.hxx +++ b/include/svl/cryptosign.hxx @@ -92,6 +92,17 @@ private: OUString m_aSignPassword; }; +/// Wrapper around a certificate: allows either an actual signing or extracting enough info, so a +/// 3rd-party can sign our document. +class SVL_DLLPUBLIC SigningContext +{ +public: + /// If set, the certificate used for signing. + css::uno::Reference m_xCertificate; + /// If m_xCertificate is not set, the time that would be used. + sal_Int64 m_nSignatureTime = 0; +}; + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx index bf68f92e70fb..4823e0bb0ec2 100644 --- a/sfx2/source/doc/docfile.cxx +++ b/sfx2/source/doc/docfile.cxx @@ -132,6 +132,7 @@ #include #include #include +#include #include #include @@ -4184,7 +4185,7 @@ void SfxMedium::CreateTempFileNoCopy() bool SfxMedium::SignDocumentContentUsingCertificate( const css::uno::Reference& xModel, bool bHasValidDocumentSignature, - const Reference& xCertificate) + svl::crypto::SigningContext& rSigningContext) { bool bChanges = false; @@ -4252,7 +4253,7 @@ bool SfxMedium::SignDocumentContentUsingCertificate( xStream.set(xMetaInf->openStreamElement(xSigner->getDocumentContentSignatureDefaultStreamName(), embed::ElementModes::READWRITE), uno::UNO_SET_THROW); bool bSuccess = xModelSigner->SignModelWithCertificate( - xModel, xCertificate, GetZipStorageToSign_Impl(), xStream); + xModel, rSigningContext, GetZipStorageToSign_Impl(), xStream); if (bSuccess) { @@ -4273,7 +4274,7 @@ bool SfxMedium::SignDocumentContentUsingCertificate( // We need read-write to be able to add the signature relation. bool bSuccess = xModelSigner->SignModelWithCertificate( - xModel, xCertificate, GetZipStorageToSign_Impl(/*bReadOnly=*/false), xStream); + xModel, rSigningContext, GetZipStorageToSign_Impl(/*bReadOnly=*/false), xStream); if (bSuccess) { @@ -4291,7 +4292,7 @@ bool SfxMedium::SignDocumentContentUsingCertificate( std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(GetName(), StreamMode::READ | StreamMode::WRITE)); uno::Reference xStream(new utl::OStreamWrapper(*pStream)); if (xModelSigner->SignModelWithCertificate( - xModel, xCertificate, uno::Reference(), xStream)) + xModel, rSigningContext, uno::Reference(), xStream)) bChanges = true; } } diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx index db1984c59052..a9b51afca983 100644 --- a/sfx2/source/doc/guisaveas.cxx +++ b/sfx2/source/doc/guisaveas.cxx @@ -101,6 +101,7 @@ #include #include +#include #ifdef _WIN32 #include @@ -1922,7 +1923,9 @@ bool SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons { bFoundCert = true; SfxObjectShell* pDocShell = SfxViewShell::Current()->GetObjectShell(); - bool bSigned = pDocShell->SignDocumentContentUsingCertificate(xCert); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCert; + bool bSigned = pDocShell->SignDocumentContentUsingCertificate(aSigningContext); if (bSigned && pDocShell->HasValidSignatures()) { std::unique_ptr xBox( diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx index 4791daf42692..369ae57be6d8 100644 --- a/sfx2/source/doc/objserv.cxx +++ b/sfx2/source/doc/objserv.cxx @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -579,7 +580,9 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq) if (xCertificate.is()) { - bHaveWeSigned |= SignDocumentContentUsingCertificate(xCertificate); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + bHaveWeSigned |= SignDocumentContentUsingCertificate(aSigningContext); // Reload to show how the PDF actually looks like after signing. This also // changes "finish signing" on the infobar back to "sign document" as a side @@ -2194,14 +2197,16 @@ bool SfxObjectShell::ResignDocument(uno::Sequence< security::DocumentSignatureIn auto xCert = rInfo.Signer; if (xCert.is()) { - bSignSuccess &= SignDocumentContentUsingCertificate(xCert); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCert; + bSignSuccess &= SignDocumentContentUsingCertificate(aSigningContext); } } return bSignSuccess; } -bool SfxObjectShell::SignDocumentContentUsingCertificate(const Reference& xCertificate) +bool SfxObjectShell::SignDocumentContentUsingCertificate(svl::crypto::SigningContext& rSigningContext) { // 1. PrepareForSigning @@ -2271,7 +2276,7 @@ bool SfxObjectShell::SignDocumentContentUsingCertificate(const ReferenceSignDocumentContentUsingCertificate( - GetBaseModel(), HasValidSignatures(), xCertificate); + GetBaseModel(), HasValidSignatures(), rSigningContext); // 4. AfterSigning AfterSigning(bSignSuccess, false); diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index b1d7d13249a5..f7259567236f 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -992,6 +993,32 @@ void SfxLokHelper::addCertificates(const std::vector& rCerts) pObjectShell->RecheckSignature(false); } +bool SfxLokHelper::supportsCommand(std::u16string_view rCommand) +{ + static const std::initializer_list vSupport = { u"Signature" }; + + return std::find(vSupport.begin(), vSupport.end(), rCommand) != vSupport.end(); +} + +void SfxLokHelper::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) +{ + static constexpr OStringLiteral aSignature(".uno:Signature"); + if (!o3tl::starts_with(rCommand, aSignature)) + { + return; + } + + SfxObjectShell* pObjectShell = SfxObjectShell::Current(); + if (!pObjectShell) + { + return; + } + + svl::crypto::SigningContext aSigningContext; + pObjectShell->SignDocumentContentUsingCertificate(aSigningContext); + rJsonWriter.put("signatureTime", aSigningContext.m_nSignatureTime); +} + void SfxLokHelper::notifyUpdate(SfxViewShell const* pThisView, int nType) { if (DisableCallbacks::disabled()) diff --git a/vcl/CppunitTest_vcl_filter_ipdf.mk b/vcl/CppunitTest_vcl_filter_ipdf.mk index d5daba87e3d6..902deedec275 100644 --- a/vcl/CppunitTest_vcl_filter_ipdf.mk +++ b/vcl/CppunitTest_vcl_filter_ipdf.mk @@ -27,6 +27,7 @@ $(eval $(call gb_CppunitTest_use_libraries,vcl_filter_ipdf, \ sal \ sfx \ subsequenttest \ + svl \ svx \ test \ tl \ diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx index 606d9ae64a79..b910f55820f0 100644 --- a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx +++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx @@ -23,6 +23,7 @@ #include #include #include +#include using namespace ::com::sun::star; @@ -109,7 +110,9 @@ CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testPDFAddVisibleSignatureLastPage) pObjectShell->SetModified(false); // When: do the actual signing. - pObjectShell->SignDocumentContentUsingCertificate(xCert); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCert; + pObjectShell->SignDocumentContentUsingCertificate(aSigningContext); // Then: count the # of shapes on the signature widget/annotation. std::unique_ptr pPdfDocument = parsePDFExport(); diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk index 37d1c2a7dea7..91613c06046e 100644 --- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk +++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk @@ -22,6 +22,7 @@ $(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing, \ sal \ sax \ sfx \ + svl \ svx \ subsequenttest \ test \ diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx index 8408ca421666..dbee1cba4587 100644 --- a/xmlsecurity/qa/unit/signing/signing.cxx +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -57,6 +57,7 @@ #include #include #include +#include using namespace com::sun::star; @@ -765,7 +766,9 @@ CPPUNIT_TEST_FIXTURE(SigningTest, testPDFAddVisibleSignature) pObjectShell->SetModified(false); // When: do the actual signing. - pObjectShell->SignDocumentContentUsingCertificate(xCert); + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCert; + pObjectShell->SignDocumentContentUsingCertificate(aSigningContext); // Then: count the # of shapes on the signature widget/annotation. std::unique_ptr pPdfDocument = parsePDFExport(); diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx index f5fe24e518e2..60549f37852b 100644 --- a/xmlsecurity/source/component/documentdigitalsignatures.cxx +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -52,6 +52,7 @@ #include #include #include +#include #include @@ -103,7 +104,7 @@ private: bool signWithCertificateImpl(const uno::Reference& /*xModel*/, - css::uno::Reference const& xCertificate, + svl::crypto::SigningContext& rSigningContext, css::uno::Reference const& xStorage, css::uno::Reference const& xStream, DocumentSignatureMode eMode); @@ -190,7 +191,7 @@ public: /// See sfx2::DigitalSignatures::SignModelWithCertificate(). bool SignModelWithCertificate(const css::uno::Reference& xModel, - const css::uno::Reference& xCertificate, + svl::crypto::SigningContext& rSigningContext, const css::uno::Reference& xStorage, const css::uno::Reference& xStream) override; /// See sfx2::DigitalSignatures::SignDocumentContentAsync(). @@ -759,17 +760,19 @@ sal_Bool DocumentDigitalSignatures::signDocumentWithCertificate( css::uno::Reference const & xStream) { uno::Reference xModel; - return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + return signWithCertificateImpl(xModel, aSigningContext, xStorage, xStream, DocumentSignatureMode::Content); } bool DocumentDigitalSignatures::SignModelWithCertificate( const uno::Reference& xModel, - const css::uno::Reference& xCertificate, + svl::crypto::SigningContext& rSigningContext, const css::uno::Reference& xStorage, const css::uno::Reference& xStream) { - return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + return signWithCertificateImpl(xModel, rSigningContext, xStorage, xStream, DocumentSignatureMode::Content); } @@ -814,13 +817,15 @@ sal_Bool DocumentDigitalSignatures::signScriptingContentWithCertificate( css::uno::Reference const& xStream) { uno::Reference xModel; - return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + svl::crypto::SigningContext aSigningContext; + aSigningContext.m_xCertificate = xCertificate; + return signWithCertificateImpl(xModel, aSigningContext, xStorage, xStream, DocumentSignatureMode::Macros); } bool DocumentDigitalSignatures::signWithCertificateImpl( const uno::Reference& xModel, - css::uno::Reference const& xCertificate, + svl::crypto::SigningContext& rSigningContext, css::uno::Reference const& xStorage, css::uno::Reference const& xStream, DocumentSignatureMode eMode) { @@ -838,8 +843,8 @@ bool DocumentDigitalSignatures::signWithCertificateImpl( aSignatureManager.setModel(xModel); Reference xSecurityContext; - Reference xServiceInfo(xCertificate, UNO_QUERY); - if (xServiceInfo->getImplementationName() + Reference xServiceInfo(rSigningContext.m_xCertificate, UNO_QUERY); + if (xServiceInfo.is() && xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl") xSecurityContext = aSignatureManager.getGpgSecurityContext(); else @@ -847,7 +852,7 @@ bool DocumentDigitalSignatures::signWithCertificateImpl( sal_Int32 nSecurityId; - bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, u""_ustr, nSecurityId, true); + bool bSuccess = aSignatureManager.add(rSigningContext.m_xCertificate, xSecurityContext, u""_ustr, nSecurityId, true); if (!bSuccess) return false;