desktop/source/lib/init.cxx | 125 ----------------------------------------- include/sfx2/lokhelper.hxx | 4 + sfx2/source/view/lokhelper.cxx | 97 +++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 122 deletions(-)
New commits: commit ab2fd7c9af1f01b5582f3c990b64cd6c9ceb37e1 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Sep 20 08:13:04 2024 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Mon Sep 23 12:25:54 2024 +0200 cool#9992 lok doc sign: extract duplicated code to SfxLokHelper I want to improve extractCertificate() so it can work on a certificate chain, but that's easier when this code is not directly in desktop/, but at some lower level. This allows covering the code with tests from CppunitTest_sfx2_view in a follow-up change. If this code will be needed by some non-LOK area as well, then it can be moved down further, but let's wait for a second area first. (cherry picked from commit 7bad76c3a5b319f8ede74be8f78e5645f9ffd050) Change-Id: I6291da0c3e56aed7dca1a8dc1446209044cace92 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173811 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index d1f7603d8d05..13efa144ba57 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -818,48 +818,6 @@ static uno::Reference<css::lang::XMultiComponentFactory> xFactory; namespace { -std::string extractCertificate(const std::string & certificate) -{ - static constexpr std::string_view header("-----BEGIN CERTIFICATE-----"); - static constexpr std::string_view footer("-----END CERTIFICATE-----"); - - std::string result; - - size_t pos1 = certificate.find(header); - if (pos1 == std::string::npos) - return result; - - size_t pos2 = certificate.find(footer, pos1 + 1); - if (pos2 == std::string::npos) - return result; - - pos1 = pos1 + header.length(); - pos2 = pos2 - pos1; - - return certificate.substr(pos1, pos2); -} - -std::string extractPrivateKey(const std::string & privateKey) -{ - static constexpr std::string_view header("-----BEGIN PRIVATE KEY-----"); - static constexpr std::string_view footer("-----END PRIVATE KEY-----"); - - std::string result; - - size_t pos1 = privateKey.find(header); - if (pos1 == std::string::npos) - return result; - - size_t pos2 = privateKey.find(footer, pos1 + 1); - if (pos2 == std::string::npos) - return result; - - pos1 = pos1 + header.length(); - pos2 = pos2 - pos1; - - return privateKey.substr(pos1, pos2); -} - OUString lcl_getCurrentDocumentMimeType(const LibLODocument_Impl* pDocument) { SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(pDocument->mxComponent.get()); @@ -3187,47 +3145,9 @@ static bool lo_signDocument(LibreOfficeKit* /*pThis*/, if (!xContext.is()) return false; - uno::Sequence<sal_Int8> aCertificateSequence; - std::string aCertificateString(reinterpret_cast<const char*>(pCertificateBinary), nCertificateBinarySize); - std::string aCertificateBase64String = extractCertificate(aCertificateString); - if (!aCertificateBase64String.empty()) - { - OUString aBase64OUString = OUString::createFromAscii(aCertificateBase64String); - comphelper::Base64::decode(aCertificateSequence, aBase64OUString); - } - else - { - aCertificateSequence.realloc(nCertificateBinarySize); - std::copy(pCertificateBinary, pCertificateBinary + nCertificateBinarySize, aCertificateSequence.getArray()); - } - - uno::Sequence<sal_Int8> aPrivateKeySequence; std::string aPrivateKeyString(reinterpret_cast<const char*>(pPrivateKeyBinary), nPrivateKeyBinarySize); - std::string aPrivateKeyBase64String = extractPrivateKey(aPrivateKeyString); - if (!aPrivateKeyBase64String.empty()) - { - OUString aBase64OUString = OUString::createFromAscii(aPrivateKeyBase64String); - comphelper::Base64::decode(aPrivateKeySequence, aBase64OUString); - } - else - { - aPrivateKeySequence.realloc(nPrivateKeyBinarySize); - std::copy(pPrivateKeyBinary, pPrivateKeyBinary + nPrivateKeyBinarySize, aPrivateKeySequence.getArray()); - } - - uno::Reference<xml::crypto::XSEInitializer> xSEInitializer = xml::crypto::SEInitializer::create(xContext); - uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext = xSEInitializer->createSecurityContext(OUString()); - if (!xSecurityContext.is()) - return false; - - uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment = xSecurityContext->getSecurityEnvironment(); - uno::Reference<xml::crypto::XCertificateCreator> xCertificateCreator(xSecurityEnvironment, uno::UNO_QUERY); - - if (!xCertificateCreator.is()) - return false; - - uno::Reference<security::XCertificate> xCertificate = xCertificateCreator->createDERCertificateWithPrivateKey(aCertificateSequence, aPrivateKeySequence); + uno::Reference<security::XCertificate> xCertificate = SfxLokHelper::getSigningCertificate(aCertificateString, aPrivateKeyString); if (!xCertificate.is()) return false; @@ -7332,48 +7252,9 @@ static bool doc_insertCertificate(LibreOfficeKitDocument* pThis, if (!pObjectShell) return false; - uno::Reference<xml::crypto::XSEInitializer> xSEInitializer = xml::crypto::SEInitializer::create(xContext); - uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext = xSEInitializer->createSecurityContext(OUString()); - if (!xSecurityContext.is()) - return false; - - uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment = xSecurityContext->getSecurityEnvironment(); - uno::Reference<xml::crypto::XCertificateCreator> xCertificateCreator(xSecurityEnvironment, uno::UNO_QUERY); - - if (!xCertificateCreator.is()) - return false; - - uno::Sequence<sal_Int8> aCertificateSequence; - std::string aCertificateString(reinterpret_cast<const char*>(pCertificateBinary), nCertificateBinarySize); - std::string aCertificateBase64String = extractCertificate(aCertificateString); - if (!aCertificateBase64String.empty()) - { - OUString aBase64OUString = OUString::createFromAscii(aCertificateBase64String); - comphelper::Base64::decode(aCertificateSequence, aBase64OUString); - } - else - { - aCertificateSequence.realloc(nCertificateBinarySize); - std::copy(pCertificateBinary, pCertificateBinary + nCertificateBinarySize, aCertificateSequence.getArray()); - } - - uno::Sequence<sal_Int8> aPrivateKeySequence; std::string aPrivateKeyString(reinterpret_cast<const char*>(pPrivateKeyBinary), nPrivateKeySize); - std::string aPrivateKeyBase64String = extractPrivateKey(aPrivateKeyString); - if (!aPrivateKeyBase64String.empty()) - { - OUString aBase64OUString = OUString::createFromAscii(aPrivateKeyBase64String); - comphelper::Base64::decode(aPrivateKeySequence, aBase64OUString); - } - else - { - aPrivateKeySequence.realloc(nPrivateKeySize); - std::copy(pPrivateKeyBinary, pPrivateKeyBinary + nPrivateKeySize, aPrivateKeySequence.getArray()); - } - - uno::Reference<security::XCertificate> xCertificate = xCertificateCreator->createDERCertificateWithPrivateKey(aCertificateSequence, aPrivateKeySequence); - + uno::Reference<security::XCertificate> xCertificate = SfxLokHelper::getSigningCertificate(aCertificateString, aPrivateKeyString); if (!xCertificate.is()) return false; @@ -7418,7 +7299,7 @@ static bool doc_addCertificate(LibreOfficeKitDocument* pThis, uno::Sequence<sal_Int8> aCertificateSequence; std::string aCertificateString(reinterpret_cast<const char*>(pCertificateBinary), nCertificateBinarySize); - std::string aCertificateBase64String = extractCertificate(aCertificateString); + std::string aCertificateBase64String = SfxLokHelper::extractCertificate(aCertificateString); if (!aCertificateBase64String.empty()) { OUString aBase64OUString = OUString::createFromAscii(aCertificateBase64String); diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 96974417430e..d6c514cd4f33 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -11,6 +11,7 @@ #define INCLUDED_SFX2_LOKHELPER_HXX #include <com/sun/star/ui/XAcceleratorConfiguration.hpp> +#include <com/sun/star/security/XCertificate.hpp> #include <vcl/IDialogRenderable.hxx> #include <vcl/ITiledRenderable.hxx> @@ -237,6 +238,9 @@ public: static void notifyLog(const std::ostringstream& stream); + static std::string extractCertificate(const std::string& rCert); + static css::uno::Reference<css::security::XCertificate> getSigningCertificate(const std::string& rCert, const std::string& rKey); + private: static int createView(SfxViewFrame& rViewFrame, ViewShellDocId docId); }; diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 66f8be5f2800..eb1a42bfbad9 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -18,6 +18,8 @@ #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/ui/ContextChangeEventObject.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> +#include <com/sun/star/xml/crypto/XCertificateCreator.hpp> #include <comphelper/processfactory.hxx> #include <o3tl/string_view.hxx> @@ -37,6 +39,7 @@ #include <comphelper/lok.hxx> #include <sfx2/msgpool.hxx> #include <comphelper/scopeguard.hxx> +#include <comphelper/base64.hxx> #include <tools/json_writer.hxx> #include <boost/property_tree/json_parser.hpp> @@ -823,6 +826,100 @@ void SfxLokHelper::notifyLog(const std::ostringstream& stream) } } +std::string SfxLokHelper::extractCertificate(const std::string & certificate) +{ + static constexpr std::string_view header("-----BEGIN CERTIFICATE-----"); + static constexpr std::string_view footer("-----END CERTIFICATE-----"); + + std::string result; + + size_t pos1 = certificate.find(header); + if (pos1 == std::string::npos) + return result; + + size_t pos2 = certificate.find(footer, pos1 + 1); + if (pos2 == std::string::npos) + return result; + + pos1 = pos1 + header.length(); + pos2 = pos2 - pos1; + + return certificate.substr(pos1, pos2); +} + +namespace +{ +std::string extractKey(const std::string & privateKey) +{ + static constexpr std::string_view header("-----BEGIN PRIVATE KEY-----"); + static constexpr std::string_view footer("-----END PRIVATE KEY-----"); + + std::string result; + + size_t pos1 = privateKey.find(header); + if (pos1 == std::string::npos) + return result; + + size_t pos2 = privateKey.find(footer, pos1 + 1); + if (pos2 == std::string::npos) + return result; + + pos1 = pos1 + header.length(); + pos2 = pos2 - pos1; + + return privateKey.substr(pos1, pos2); +} +} + +css::uno::Reference<css::security::XCertificate> SfxLokHelper::getSigningCertificate(const std::string& rCert, const std::string& rKey) +{ + uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext(); + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer = xml::crypto::SEInitializer::create(xContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext = xSEInitializer->createSecurityContext(OUString()); + if (!xSecurityContext.is()) + { + return {}; + } + + uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment = xSecurityContext->getSecurityEnvironment(); + uno::Reference<xml::crypto::XCertificateCreator> xCertificateCreator(xSecurityEnvironment, uno::UNO_QUERY); + + if (!xCertificateCreator.is()) + { + return {}; + } + + uno::Sequence<sal_Int8> aCertificateSequence; + + std::string aCertificateBase64String = extractCertificate(rCert); + if (!aCertificateBase64String.empty()) + { + OUString aBase64OUString = OUString::createFromAscii(aCertificateBase64String); + comphelper::Base64::decode(aCertificateSequence, aBase64OUString); + } + else + { + aCertificateSequence.realloc(rCert.size()); + std::copy(rCert.c_str(), rCert.c_str() + rCert.size(), aCertificateSequence.getArray()); + } + + uno::Sequence<sal_Int8> aPrivateKeySequence; + std::string aPrivateKeyBase64String = extractKey(rKey); + if (!aPrivateKeyBase64String.empty()) + { + OUString aBase64OUString = OUString::createFromAscii(aPrivateKeyBase64String); + comphelper::Base64::decode(aPrivateKeySequence, aBase64OUString); + } + else + { + aPrivateKeySequence.realloc(rKey.size()); + std::copy(rKey.c_str(), rKey.c_str() + rKey.size(), aPrivateKeySequence.getArray()); + } + + uno::Reference<security::XCertificate> xCertificate = xCertificateCreator->createDERCertificateWithPrivateKey(aCertificateSequence, aPrivateKeySequence); + return xCertificate; +} + void SfxLokHelper::notifyUpdate(SfxViewShell const* pThisView, int nType) { if (DisableCallbacks::disabled())