[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - 6 commits - desktop/qa desktop/source include/LibreOfficeKit include/sfx2 sfx2/Library_sfx.mk sfx2/source xmlsecurity/inc xmlsecurity/Library_xsec_xmlsec.mk xmlsecurity/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Jan 3 06:36:08 UTC 2019


 desktop/qa/data/blank_text.docx                               |binary
 desktop/qa/desktop_lib/test_desktop_lib.cxx                   |  242 ++++++----
 desktop/source/lib/init.cxx                                   |   78 +++
 include/LibreOfficeKit/LibreOfficeKit.h                       |   10 
 include/LibreOfficeKit/LibreOfficeKit.hxx                     |   12 
 include/sfx2/DocumentSigner.hxx                               |   41 +
 sfx2/Library_sfx.mk                                           |    1 
 sfx2/source/appl/appopen.cxx                                  |   16 
 sfx2/source/doc/DocumentSigner.cxx                            |  125 +++++
 xmlsecurity/Library_xsec_xmlsec.mk                            |    1 
 xmlsecurity/inc/documentsignaturemanager.hxx                  |    2 
 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx        |   21 
 xmlsecurity/source/helper/documentsignaturehelper.cxx         |    6 
 xmlsecurity/source/helper/documentsignaturemanager.cxx        |   77 ++-
 xmlsecurity/source/xmlsec/nss/nssinitializer.cxx              |  131 ++++-
 xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx |   56 +-
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx     |   23 
 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx     |    2 
 18 files changed, 664 insertions(+), 180 deletions(-)

New commits:
commit 277f4e186ce4a3f109c470b54a0accdb6c74e8cb
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Dec 31 12:27:39 2018 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Jan 3 07:34:39 2019 +0100

    lok: add signDocument to "Office" iface - to sign not opened docs.
    
    LOKit function "signDocument" can sign document without the need
    to open them. This is useful to sign PDF documents after they are
    created from a currently opened (ODF, DOCX) document.
    
    This adds DocumentDigner to sfx2, which could also be used in
    desktop LibreOffice without opening them and in further tests.
    
    Reviewed-on: https://gerrit.libreoffice.org/65767
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit a8cb7cf68ff661b502e7c006fe4330098b5b0944)
    
    Change-Id: Id6f242e817f594aa672f94f9c6f9b34e4035d46a

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 78f064a49c0a..27070b4440a3 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -125,6 +125,7 @@ public:
     void testInsertCertificate_DER_ODT();
     void testInsertCertificate_PEM_ODT();
     void testInsertCertificate_PEM_DOCX();
+    void testSignDocument_PEM_PDF();
     void testABI();
 
     CPPUNIT_TEST_SUITE(DesktopLOKTest);
@@ -173,6 +174,7 @@ public:
     CPPUNIT_TEST(testInsertCertificate_DER_ODT);
     CPPUNIT_TEST(testInsertCertificate_PEM_ODT);
     CPPUNIT_TEST(testInsertCertificate_PEM_DOCX);
+    CPPUNIT_TEST(testSignDocument_PEM_PDF);
     CPPUNIT_TEST(testABI);
     CPPUNIT_TEST_SUITE_END();
 
@@ -2484,6 +2486,66 @@ void DesktopLOKTest::testInsertCertificate_PEM_DOCX()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void DesktopLOKTest::testSignDocument_PEM_PDF()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    // Load the document, save it into a temp file and load that file again
+    LibLODocument_Impl* pDocument = loadDoc("blank_text.odt");
+    utl::TempFile aTempFile;
+    aTempFile.EnableKillingFile();
+
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(mxComponent.is());
+    pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
+    Scheduler::ProcessEventsToIdle();
+
+    std::vector<unsigned char> aCertificate;
+    std::vector<unsigned char> aPrivateKey;
+
+    {
+        readFileIntoByteVector("test-cert-chain-1.pem", aCertificate);
+
+        bool bResult = pDocument->m_pDocumentClass->addCertificate(
+                            pDocument, aCertificate.data(), int(aCertificate.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    {
+        readFileIntoByteVector("test-cert-chain-2.pem", aCertificate);
+
+        bool bResult = pDocument->m_pDocumentClass->addCertificate(
+                            pDocument, aCertificate.data(), int(aCertificate.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    {
+        readFileIntoByteVector("test-cert-chain-3.pem", aCertificate);
+
+        bool bResult = pDocument->m_pDocumentClass->addCertificate(
+                            pDocument, aCertificate.data(), int(aCertificate.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "pdf", nullptr));
+
+    closeDoc();
+
+    Scheduler::ProcessEventsToIdle();
+
+    readFileIntoByteVector("test-cert-signing.pem", aCertificate);
+    readFileIntoByteVector("test-PK-signing.pem", aPrivateKey);
+
+    LibLibreOffice_Impl aOffice;
+    bool bResult = aOffice.m_pOfficeClass->signDocument(&aOffice, aTempFile.GetURL().toUtf8().getStr(),
+                                         aCertificate.data(), int(aCertificate.size()),
+                                         aPrivateKey.data(), int(aPrivateKey.size()));
+
+    CPPUNIT_ASSERT(bResult);
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 namespace {
 
 size_t documentClassOffset(int i)
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index f534d9a9b23a..333da4cba3db 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -93,6 +93,7 @@
 #include <sfx2/msgpool.hxx>
 #include <sfx2/dispatch.hxx>
 #include <sfx2/lokhelper.hxx>
+#include <sfx2/DocumentSigner.hxx>
 #include <svx/dialmgr.hxx>
 #include <svx/dialogs.hrc>
 #include <svx/strings.hrc>
@@ -1425,6 +1426,13 @@ static void                    lo_setDocumentPassword(LibreOfficeKit* pThis,
 static char*                   lo_getVersionInfo(LibreOfficeKit* pThis);
 static int                     lo_runMacro      (LibreOfficeKit* pThis, const char* pURL);
 
+static bool lo_signDocument(LibreOfficeKit* pThis,
+                                   const char* pUrl,
+                                   const unsigned char* pCertificateBinary,
+                                   const int nCertificateBinarySize,
+                                   const unsigned char* pPrivateKeyBinary,
+                                   const int nPrivateKeyBinarySize);
+
 LibLibreOffice_Impl::LibLibreOffice_Impl()
     : m_pOfficeClass( gOfficeClass.lock() )
     , maThread(nullptr)
@@ -1447,6 +1455,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl()
         m_pOfficeClass->setDocumentPassword = lo_setDocumentPassword;
         m_pOfficeClass->getVersionInfo = lo_getVersionInfo;
         m_pOfficeClass->runMacro = lo_runMacro;
+        m_pOfficeClass->signDocument = lo_signDocument;
 
         gOfficeClass = m_pOfficeClass;
     }
@@ -1674,6 +1683,75 @@ static int lo_runMacro(LibreOfficeKit* pThis, const char *pURL)
     return false;
 }
 
+static bool lo_signDocument(LibreOfficeKit* /*pThis*/,
+                                       const char* pURL,
+                                       const unsigned char* pCertificateBinary,
+                                       const int nCertificateBinarySize,
+                                       const unsigned char* pPrivateKeyBinary,
+                                       const int nPrivateKeyBinarySize)
+{
+    OUString aURL(getAbsoluteURL(pURL));
+    if (aURL.isEmpty())
+       return false;
+
+    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.c_str());
+        comphelper::Base64::decode(aCertificateSequence, aBase64OUString);
+    }
+    else
+    {
+        aCertificateSequence.realloc(nCertificateBinarySize);
+        std::copy(pCertificateBinary, pCertificateBinary + nCertificateBinarySize, aCertificateSequence.begin());
+    }
+
+    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.c_str());
+        comphelper::Base64::decode(aPrivateKeySequence, aBase64OUString);
+    }
+    else
+    {
+        aPrivateKeySequence.realloc(nPrivateKeyBinarySize);
+        std::copy(pPrivateKeyBinary, pPrivateKeyBinary + nPrivateKeyBinarySize, aPrivateKeySequence.begin());
+    }
+
+    uno::Reference<xml::crypto::XSEInitializer> xSEInitializer = xml::crypto::SEInitializer::create(xContext);
+    uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext;
+    xSecurityContext = xSEInitializer->createSecurityContext(OUString());
+    if (!xSecurityContext.is())
+        return false;
+
+    uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment;
+    xSecurityEnvironment = xSecurityContext->getSecurityEnvironment();
+    uno::Reference<xml::crypto::XCertificateCreator> xCertificateCreator(xSecurityEnvironment, uno::UNO_QUERY);
+
+    if (!xCertificateCreator.is())
+        return false;
+
+    uno::Reference<security::XCertificate> xCertificate;
+    xCertificate = xCertificateCreator->createDERCertificateWithPrivateKey(aCertificateSequence, aPrivateKeySequence);
+
+    if (!xCertificate.is())
+        return false;
+
+    sfx2::DocumentSigner aDocumentSigner(aURL);
+    if (!aDocumentSigner.signDocument(xCertificate))
+        return false;
+
+    return true;
+}
+
 static void lo_registerCallback (LibreOfficeKit* pThis,
                                  LibreOfficeKitCallback pCallback,
                                  void* pData)
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 0581513d7701..479344cfc971 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -94,6 +94,16 @@ struct _LibreOfficeKitClass
         @since LibreOffice 6.0
      */
     int (*runMacro) (LibreOfficeKit *pThis, const char* pURL);
+
+    /** @see lok::Office::signDocument().
+        @since LibreOffice 6.2
+     */
+     bool (*signDocument) (LibreOfficeKit* pThis,
+                           const char* pUrl,
+                           const unsigned char* pCertificateBinary,
+                           const int nCertificateBinarySize,
+                           const unsigned char* pPrivateKeyBinary,
+                           const int nPrivateKeyBinarySize);
 };
 
 #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize)
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index ffcb87f4e5d0..8709f5418722 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -763,6 +763,18 @@ public:
     {
         return mpThis->pClass->runMacro( mpThis, pURL );
     }
+
+    /**
+     * Exports the document and signes its content.
+     */
+    bool signDocument(const char* pURL,
+                       const unsigned char* pCertificateBinary, const int nCertificateBinarySize,
+                       const unsigned char* pPrivateKeyBinary, const int nPrivateKeyBinarySize)
+    {
+        return mpThis->pClass->signDocument(mpThis, pURL,
+                                            pCertificateBinary, nCertificateBinarySize,
+                                            pPrivateKeyBinary, nPrivateKeyBinarySize);
+    }
 };
 
 /// Factory method to create a lok::Office instance.
diff --git a/include/sfx2/DocumentSigner.hxx b/include/sfx2/DocumentSigner.hxx
new file mode 100644
index 000000000000..1f4326ef3976
--- /dev/null
+++ b/include/sfx2/DocumentSigner.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_SFX2_DOCUMENTSIGNER_HXX
+#define INCLUDED_SFX2_DOCUMENTSIGNER_HXX
+
+#include <sal/config.h>
+#include <sfx2/dllapi.h>
+
+#include <memory>
+
+#include <com/sun/star/security/XCertificate.hpp>
+
+namespace sfx2
+{
+class SFX2_DLLPUBLIC DocumentSigner
+{
+private:
+    OUString m_aUrl;
+
+public:
+    DocumentSigner(OUString const& rUrl)
+        : m_aUrl(rUrl)
+    {
+    }
+
+    bool signDocument(css::uno::Reference<css::security::XCertificate> const& rxCertificate);
+};
+
+} // namespace sfx2
+
+#endif // INCLUDED_SFX2_DOCUMENTSIGNER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk
index 19beea4765e5..3d7e8ac3559e 100644
--- a/sfx2/Library_sfx.mk
+++ b/sfx2/Library_sfx.mk
@@ -202,6 +202,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\
     sfx2/source/dialog/tplpitem \
     sfx2/source/dialog/versdlg \
     sfx2/source/doc/DocumentMetadataAccess \
+    sfx2/source/doc/DocumentSigner \
     sfx2/source/doc/Metadatable \
     sfx2/source/doc/QuerySaveDocument \
     sfx2/source/doc/SfxDocumentMetaData \
diff --git a/sfx2/source/doc/DocumentSigner.cxx b/sfx2/source/doc/DocumentSigner.cxx
new file mode 100644
index 000000000000..4a07aa81cca9
--- /dev/null
+++ b/sfx2/source/doc/DocumentSigner.cxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sfx2/DocumentSigner.hxx>
+
+#include <tools/stream.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/streamwrap.hxx>
+
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/security/DocumentSignatureInformation.hpp>
+#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/io/XStream.hpp>
+
+using namespace css;
+
+namespace sfx2
+{
+bool DocumentSigner::signDocument(uno::Reference<security::XCertificate> const& rxCertificate)
+{
+    std::unique_ptr<SvStream> pStream(
+        utl::UcbStreamHelper::CreateStream(m_aUrl, StreamMode::READ | StreamMode::WRITE));
+    uno::Reference<io::XStream> xInputStream(new utl::OStreamWrapper(*pStream));
+
+    bool bHasValidDocumentSignature = true;
+
+    bool bResult = false;
+    uno::Reference<embed::XStorage> xWriteableZipStore;
+    try
+    {
+        xWriteableZipStore = comphelper::OStorageHelper::GetStorageOfFormatFromStream(
+            ZIP_STORAGE_FORMAT_STRING, xInputStream);
+    }
+    catch (const io::IOException&)
+    {
+    }
+
+    OUString aODFVersion(comphelper::OStorageHelper::GetODFVersionFromStorage(xWriteableZipStore));
+
+    uno::Reference<security::XDocumentDigitalSignatures> xSigner(
+        security::DocumentDigitalSignatures::createWithVersionAndValidSignature(
+            comphelper::getProcessComponentContext(), aODFVersion, bHasValidDocumentSignature));
+
+    try
+    {
+        uno::Reference<embed::XStorage> xMetaInf;
+        uno::Reference<container::XNameAccess> xNameAccess(xWriteableZipStore, uno::UNO_QUERY);
+        if (xNameAccess.is() && xNameAccess->hasByName("META-INF"))
+        {
+            xMetaInf = xWriteableZipStore->openStorageElement("META-INF",
+                                                              embed::ElementModes::READWRITE);
+            if (!xMetaInf.is())
+                throw uno::RuntimeException();
+        }
+        if (xMetaInf.is())
+        {
+            uno::Reference<embed::XStorage> xStorage;
+            xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(
+                ZIP_STORAGE_FORMAT_STRING, xInputStream);
+
+            // ODF.
+            uno::Reference<io::XStream> xStream;
+            xStream.set(
+                xMetaInf->openStreamElement(xSigner->getDocumentContentSignatureDefaultStreamName(),
+                                            embed::ElementModes::READWRITE),
+                uno::UNO_SET_THROW);
+            bool bSuccess = xSigner->signDocumentWithCertificate(rxCertificate, xStorage, xStream);
+            if (bSuccess)
+            {
+                uno::Reference<embed::XTransactedObject> xTransact(xMetaInf, uno::UNO_QUERY_THROW);
+                xTransact->commit();
+                xTransact.set(xWriteableZipStore, uno::UNO_QUERY_THROW);
+                xTransact->commit();
+                bResult = true;
+            }
+        }
+        else if (xWriteableZipStore.is())
+        {
+            uno::Reference<embed::XStorage> xStorage;
+            xStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(
+                ZIP_STORAGE_FORMAT_STRING, xInputStream);
+
+            // OOXML.
+            uno::Reference<io::XStream> xStream;
+
+            // We need read-write to be able to add the signature relation.
+            bool bSuccess = xSigner->signDocumentWithCertificate(rxCertificate, xStorage, xStream);
+
+            if (bSuccess)
+            {
+                uno::Reference<embed::XTransactedObject> xTransact(xWriteableZipStore,
+                                                                   uno::UNO_QUERY_THROW);
+                xTransact->commit();
+                bResult = true;
+            }
+        }
+        else
+        {
+            // Something not ZIP based: e.g. PDF.
+            bResult = xSigner->signDocumentWithCertificate(
+                rxCertificate, uno::Reference<embed::XStorage>(), xInputStream);
+        }
+    }
+    catch (const uno::Exception&)
+    {
+    }
+    return bResult;
+}
+
+} // namespace sfx2
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 48595091cae4248711c4fc48e68887e9f138c8ad
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Dec 31 12:14:19 2018 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Jan 3 07:34:31 2019 +0100

    NSS: create a temporary database instead of in-memory
    
    When initializing for the in-memory database (NSS_NoDB_Init) the
    internal slot is read-only so a lot of actions (PK11_ImportCert)
    fails. Instead of that we create a new cert/key database inside
    the tmp directory and delete it on exit. This way there are no
    limitations and all the actions perform as expected.
    
    Change-Id: Iadec5dd8f3459be56ba57d077057eacf3e0797fc
    Reviewed-on: https://gerrit.libreoffice.org/65765
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 87eec1b90b6ecd83455f09168430c23f73c25c86)

diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk
index 1ef27dbc6602..e75fb773fbf8 100644
--- a/xmlsecurity/Library_xsec_xmlsec.mk
+++ b/xmlsecurity/Library_xsec_xmlsec.mk
@@ -45,6 +45,7 @@ $(eval $(call gb_Library_use_libraries,xsec_xmlsec,\
 	svl \
 	tl \
 	xo \
+	utl \
 ))
 
 ifeq ($(SYSTEM_XMLSEC),)
diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
index 575be2a2702c..99db97559588 100644
--- a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
+++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
@@ -38,6 +38,8 @@
 #include <osl/file.hxx>
 #include <osl/thread.h>
 #include <sal/log.hxx>
+#include <unotools/tempfile.hxx>
+#include <salhelper/singletonref.hxx>
 
 #include "seinitializer_nssimpl.hxx"
 
@@ -46,6 +48,7 @@
 #include "ciphercontext.hxx"
 
 #include <memory>
+#include <vector>
 
 #include <nspr.h>
 #include <cert.h>
@@ -69,6 +72,97 @@ extern "C" void nsscrypto_finalize();
 namespace
 {
 
+class InitNSSPrivate
+{
+private:
+    std::unique_ptr<utl::TempFile> m_pTempFileDatabaseDirectory;
+
+    static void scanDirsAndFiles(OUString const & rDirURL, std::vector<OUString> & rDirs, std::vector<OUString> & rFiles)
+    {
+        if (rDirURL.isEmpty())
+            return;
+        osl::Directory aDirectory(rDirURL);
+
+        if (osl::FileBase::E_None != aDirectory.open())
+            return;
+
+        osl::DirectoryItem aDirectoryItem;
+
+        while (osl::FileBase::E_None == aDirectory.getNextItem(aDirectoryItem))
+        {
+            osl::FileStatus aFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName);
+
+            if (osl::FileBase::E_None == aDirectoryItem.getFileStatus(aFileStatus))
+            {
+                if (aFileStatus.isDirectory())
+                {
+                    const OUString aFileName(aFileStatus.getFileName());
+                    if (!aFileName.isEmpty())
+                        rDirs.push_back(aFileName);
+                }
+                else if (aFileStatus.isRegular())
+                {
+                    const OUString aFileName(aFileStatus.getFileName());
+                    if (!aFileName.isEmpty())
+                        rFiles.push_back(aFileName);
+
+                }
+            }
+        }
+    }
+
+    static bool deleteDirRecursively(OUString const & rDirURL)
+    {
+        std::vector<OUString> aDirs;
+        std::vector<OUString> aFiles;
+        bool bError(false);
+
+        scanDirsAndFiles(rDirURL, aDirs, aFiles);
+
+        for (const auto& sDir : aDirs)
+        {
+            const OUString aNewDirURL(rDirURL + "/" + sDir);
+            bError |= deleteDirRecursively(aNewDirURL);
+        }
+
+        for (const auto& sFile : aFiles)
+        {
+            OUString aNewFileURL(rDirURL + "/" + sFile);
+            bError |= (osl::FileBase::E_None != osl::File::remove(aNewFileURL));
+        }
+
+        bError |= (osl::FileBase::E_None != osl::Directory::remove(rDirURL));
+
+        return bError;
+    }
+
+public:
+    OUString getTempDatabasePath()
+    {
+        if (!m_pTempFileDatabaseDirectory)
+        {
+            m_pTempFileDatabaseDirectory.reset(new utl::TempFile(nullptr, true));
+            m_pTempFileDatabaseDirectory->EnableKillingFile();
+        }
+        return m_pTempFileDatabaseDirectory->GetFileName();
+    }
+
+    void reset()
+    {
+        if (m_pTempFileDatabaseDirectory)
+        {
+            deleteDirRecursively(m_pTempFileDatabaseDirectory->GetURL());
+            m_pTempFileDatabaseDirectory.reset();
+        }
+    }
+};
+
+salhelper::SingletonRef<InitNSSPrivate>* getInitNSSPrivate()
+{
+    static salhelper::SingletonRef<InitNSSPrivate> aInitNSSPrivate;
+    return &aInitNSSPrivate;
+}
+
 bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init );
 
 struct InitNSSInitialize
@@ -235,7 +329,7 @@ OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponen
 //return true - whole initialization was successful
 //param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite
 //was successful and therefore NSS_Shutdown should be called when terminating.
-bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init )
+bool nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const & rxContext, bool & out_nss_init)
 {
     // this method must be called only once, no need for additional lock
     OString sCertDir;
@@ -249,9 +343,9 @@ bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContex
 
     PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
 
-    bool bSuccess = true;
+    bool bSuccess = false;
     // there might be no profile
-    if ( !sCertDir.isEmpty() )
+    if (!sCertDir.isEmpty())
     {
         if (sCertDir.indexOf(':') == -1) //might be env var with explicit prefix
         {
@@ -267,26 +361,31 @@ bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContex
                 sCertDir = "dbm:" + sCertDir;
             }
         }
-        if( NSS_InitReadWrite( sCertDir.getStr() ) != SECSuccess )
+        if (NSS_InitReadWrite(sCertDir.getStr()) != SECSuccess)
         {
             SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with profile failed.");
             int errlen = PR_GetErrorTextLength();
-            if(errlen > 0)
+            if (errlen > 0)
             {
                 std::unique_ptr<char[]> const error(new char[errlen + 1]);
                 PR_GetErrorText(error.get());
                 SAL_INFO("xmlsecurity.xmlsec", error.get());
             }
-            bSuccess = false;
+        }
+        else
+        {
+            bSuccess = true;
         }
     }
 
-    if( sCertDir.isEmpty() || !bSuccess )
+    if (!bSuccess) // Try to create a database in temp dir
     {
-        SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS without profile.");
-        if ( NSS_NoDB_Init(nullptr) != SECSuccess )
+        SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
+        OUString rString = (*getInitNSSPrivate())->getTempDatabasePath();
+
+        if (NSS_InitReadWrite(rString.toUtf8().getStr()) != SECSuccess)
         {
-            SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS without profile failed.");
+            SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
             int errlen = PR_GetErrorTextLength();
             if(errlen > 0)
             {
@@ -294,7 +393,15 @@ bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContex
                 PR_GetErrorText(error.get());
                 SAL_INFO("xmlsecurity.xmlsec", error.get());
             }
-            return false ;
+            return false;
+        }
+        // Initialize and set empty password if needed
+        PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+        if (pSlot)
+        {
+            if (PK11_NeedUserInit(pSlot))
+                PK11_InitPin(pSlot, nullptr, nullptr);
+            PK11_FreeSlot(pSlot);
         }
     }
     out_nss_init = true;
@@ -388,6 +495,8 @@ extern "C" void nsscrypto_finalize()
     }
     PK11_LogoutAll();
     (void)NSS_Shutdown();
+
+    (*getInitNSSPrivate())->reset();
 }
 
 ONSSInitializer::ONSSInitializer(
diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
index d58d4e7b95b5..5595598d295b 100644
--- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
@@ -41,6 +41,7 @@
 #include <osl/thread.h>
 
 #include "secerror.hxx"
+#include <prerror.h>
 
 // added for password exception
 #include <com/sun/star/security/NoPasswordException.hpp>
@@ -537,15 +538,34 @@ X509Certificate_NssImpl* SecurityEnvironment_NssImpl::createAndAddCertificateFro
     if (!pCERTCertificate)
         return nullptr;
 
-    OString aTrustString = OUStringToOString(raString, RTL_TEXTENCODING_ASCII_US);
+    SECStatus aStatus;
 
+    OString aTrustString = OUStringToOString(raString, RTL_TEXTENCODING_ASCII_US);
     CERTCertTrust aTrust;
-    if (CERT_DecodeTrustString(&aTrust, aTrustString.getStr()) != SECSuccess)
+
+    aStatus = CERT_DecodeTrustString(&aTrust, aTrustString.getStr());
+
+    if (aStatus != SECSuccess)
+        return nullptr;
+
+    PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+
+    if (!pSlot)
         return nullptr;
 
-    if (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust) != SECSuccess)
+    aStatus = PK11_ImportCert(pSlot, pCERTCertificate, CK_INVALID_HANDLE, nullptr, PR_FALSE);
+
+    if (aStatus != SECSuccess)
         return nullptr;
 
+    aStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust);
+
+    if (aStatus != SECSuccess)
+        return nullptr;
+
+
+    PK11_FreeSlot(pSlot);
+
     X509Certificate_NssImpl* pX509Certificate = new X509Certificate_NssImpl();
     pX509Certificate->setCert(pCERTCertificate);
     return pX509Certificate;
@@ -933,12 +953,10 @@ xmlSecKeysMngrPtr SecurityEnvironment_NssImpl::createKeysManager() {
     // Adopt the private key of the signing certificate, if it has any.
     if (auto pCertificate = dynamic_cast<X509Certificate_NssImpl*>(m_xSigningCertificate.get()))
     {
-        SECKEYPrivateKey* pPrivateKey = pCertificate->getPrivateKey();
-        SECKEYPrivateKey* copy
-            = pPrivateKey == nullptr ? nullptr : SECKEY_CopyPrivateKey(pPrivateKey);
-        if (copy)
+        SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(pCertificate->getPrivateKey());
+        if (pPrivateKey)
         {
-            xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(copy, nullptr);
+            xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey, nullptr);
             xmlSecKeyPtr pKey = xmlSecKeyCreate();
             xmlSecKeySetValue(pKey, pKeyData);
             xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey);
@@ -965,42 +983,40 @@ SECKEYPrivateKey* SecurityEnvironment_NssImpl::insertPrivateKey(css::uno::Sequen
     if (!pSlot)
         return nullptr;
 
-    SECItem pDerPrivateKeyInfo;
-    pDerPrivateKeyInfo.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(raPrivateKey.getConstArray()));
-    pDerPrivateKeyInfo.len = raPrivateKey.getLength();
+    SECItem aDerPrivateKeyInfo;
+    aDerPrivateKeyInfo.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(raPrivateKey.getConstArray()));
+    aDerPrivateKeyInfo.len = raPrivateKey.getLength();
 
-    const unsigned int aKeyUsage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
+    const unsigned int aKeyUsage = KU_ALL;
     SECKEYPrivateKey* pPrivateKey = nullptr;
 
-    bool bPermanent = false;
-    bool bSensitive = false;
+    bool bPermanent = PR_FALSE;
+    bool bPrivate = PR_TRUE;
 
     SECStatus nStatus = PK11_ImportDERPrivateKeyInfoAndReturnKey(
-          pSlot, &pDerPrivateKeyInfo, nullptr, nullptr, bPermanent, bSensitive,
+          pSlot, &aDerPrivateKeyInfo, nullptr, nullptr, bPermanent, bPrivate,
           aKeyUsage, &pPrivateKey, nullptr);
 
     if (nStatus != SECSuccess)
         return nullptr;
 
+    PK11_FreeSlot(pSlot);
+
     return pPrivateKey;
 }
 
 uno::Reference<security::XCertificate> SecurityEnvironment_NssImpl::createDERCertificateWithPrivateKey(
         Sequence<sal_Int8> const & raDERCertificate, Sequence<sal_Int8> const & raPrivateKey)
 {
-
     SECKEYPrivateKey* pPrivateKey = insertPrivateKey(raPrivateKey);
 
     if (!pPrivateKey)
         return uno::Reference<security::XCertificate>();
 
-    X509Certificate_NssImpl* pX509Certificate = createAndAddCertificateFromPackage(raDERCertificate, "TCu,Cu,Tu");
-
+    X509Certificate_NssImpl* pX509Certificate = createAndAddCertificateFromPackage(raDERCertificate, "TCu,TCu,TCu");
     if (!pX509Certificate)
         return uno::Reference<security::XCertificate>();
 
-    pX509Certificate->setCustomPrivateKey(pPrivateKey);
-
     return pX509Certificate;
 }
 
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
index 1bda73af613b..1b08b561f902 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
@@ -45,8 +45,7 @@ using ::com::sun::star::security::XCertificate ;
 using ::com::sun::star::util::DateTime ;
 
 X509Certificate_NssImpl::X509Certificate_NssImpl() :
-    m_pCert(nullptr),
-    m_pPrivateKey(nullptr)
+    m_pCert(nullptr)
 {
 }
 
@@ -331,25 +330,13 @@ void X509Certificate_NssImpl::setRawCert( const Sequence< sal_Int8 >& rawCert )
     m_pCert = cert ;
 }
 
-void X509Certificate_NssImpl::setCustomPrivateKey(SECKEYPrivateKey* pPrivateKey)
-{
-    m_pPrivateKey = pPrivateKey;
-}
-
 SECKEYPrivateKey* X509Certificate_NssImpl::getPrivateKey()
 {
-    if (m_pPrivateKey)
-    {
-        return m_pPrivateKey;
-    }
-    else
+    if (m_pCert && m_pCert->slot)
     {
-        if (m_pCert && m_pCert->slot)
-        {
-            SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr);
-            if (pPrivateKey)
-                return pPrivateKey;
-        }
+        SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr);
+        if (pPrivateKey)
+            return pPrivateKey;
     }
     return nullptr;
 }
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
index 8f0fd2ac4287..e50cf1025166 100644
--- a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
@@ -41,7 +41,6 @@ class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
 {
     private:
         CERTCertificate* m_pCert;
-        SECKEYPrivateKey* m_pPrivateKey;
 
     public:
         X509Certificate_NssImpl() ;
@@ -94,7 +93,6 @@ class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
 
         /// @throws css::uno::RuntimeException
         void setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) ;
-        void setCustomPrivateKey(SECKEYPrivateKey* pPrivateKey);
         SECKEYPrivateKey* getPrivateKey();
 
         // XServiceInfo
commit 368830fbaef27d3a392d09e5f5c9aa35859b792a
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Dec 31 10:09:03 2018 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Jan 3 07:34:26 2019 +0100

    Remove some useless whitespaces
    
    Reviewed-on: https://gerrit.libreoffice.org/65764
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit a8d51dc85627514ce7f983eb4e0514ef00f84b1e)
    
    Change-Id: Iebf7add3dd937afb6dad07a10ecbe768c0a79d36

diff --git a/sfx2/source/appl/appopen.cxx b/sfx2/source/appl/appopen.cxx
index 6c5d833af317..4992156f2fa9 100644
--- a/sfx2/source/appl/appopen.cxx
+++ b/sfx2/source/appl/appopen.cxx
@@ -675,9 +675,9 @@ void SfxApplication::OpenDocExec_Impl( SfxRequest& rReq )
             // intercept all incoming interactions and provide useful information
             // later if the following transaction was finished.
 
-            ::sfx2::PreventDuplicateInteraction*                 pHandler       = new ::sfx2::PreventDuplicateInteraction(::comphelper::getProcessComponentContext());
-            css::uno::Reference< css::task::XInteractionHandler >     xHandler       (static_cast< css::task::XInteractionHandler* >(pHandler), css::uno::UNO_QUERY);
-            css::uno::Reference< css::task::XInteractionHandler >     xWrappedHandler;
+            sfx2::PreventDuplicateInteraction* pHandler = new sfx2::PreventDuplicateInteraction(comphelper::getProcessComponentContext());
+            uno::Reference<task::XInteractionHandler> xHandler(static_cast< css::task::XInteractionHandler* >(pHandler), css::uno::UNO_QUERY);
+            uno::Reference<task::XInteractionHandler> xWrappedHandler;
 
             // wrap existing handler or create new UUI handler
             const SfxUnoAnyItem* pInteractionItem = rReq.GetArg<SfxUnoAnyItem>(SID_INTERACTIONHANDLER);
@@ -693,8 +693,8 @@ void SfxApplication::OpenDocExec_Impl( SfxRequest& rReq )
             rReq.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::makeAny(xHandler)) );
 
             // define rules for this handler
-            css::uno::Type                                            aInteraction = ::cppu::UnoType<css::task::ErrorCodeRequest>::get();
-            ::sfx2::PreventDuplicateInteraction::InteractionInfo aRule        (aInteraction, 1);
+            css::uno::Type aInteraction = ::cppu::UnoType<css::task::ErrorCodeRequest>::get();
+            ::sfx2::PreventDuplicateInteraction::InteractionInfo aRule(aInteraction, 1);
             pHandler->addInteractionRule(aRule);
 
             if (!aDocService.isEmpty())
@@ -816,9 +816,9 @@ void SfxApplication::OpenDocExec_Impl( SfxRequest& rReq )
     // Mark without URL cannot be handled by hyperlink code
     if ( bHyperlinkUsed && !aFileName.isEmpty() && aFileName[0] != '#' )
     {
-        Reference< css::document::XTypeDetection > xTypeDetection( ::comphelper::getProcessServiceFactory()->createInstance(
-                                                                       "com.sun.star.document.TypeDetection"),
-                                                                   UNO_QUERY );
+        uno::Reference<document::XTypeDetection> xTypeDetection(
+            comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"), UNO_QUERY);
+
         if ( xTypeDetection.is() )
         {
             URL             aURL;
diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx
index 509d3699a294..b0b57ee2758d 100644
--- a/xmlsecurity/source/helper/documentsignaturehelper.cxx
+++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx
@@ -521,17 +521,17 @@ bool DocumentSignatureHelper::equalsReferenceUriManifestPath(
 
 OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()
 {
-    return OUString(  "documentsignatures.xml"  );
+    return OUString("documentsignatures.xml");
 }
 
 OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName()
 {
-    return OUString(  "macrosignatures.xml"  );
+    return OUString("macrosignatures.xml");
 }
 
 OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName()
 {
-    return OUString(  "packagesignatures.xml"  );
+    return OUString("packagesignatures.xml");
 }
 
 void DocumentSignatureHelper::writeDigestMethod(
commit ec17d9778b26f762af30c964a6170d4933cdcea4
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Dec 26 20:46:16 2018 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Jan 3 07:34:23 2019 +0100

    lok: add test signing DOCX -> testInsertCertificate_PEM_DOCX
    
    Change-Id: I1918041793935b012e60fe64073480ed4b9581d5
    Reviewed-on: https://gerrit.libreoffice.org/65630
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 936f6a85649c0fd71eee484e7399d445f4040586)

diff --git a/desktop/qa/data/blank_text.docx b/desktop/qa/data/blank_text.docx
new file mode 100644
index 000000000000..028a35b6ca58
Binary files /dev/null and b/desktop/qa/data/blank_text.docx differ
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 18e20c8fd4d7..78f064a49c0a 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -124,6 +124,7 @@ public:
     void testGetSignatureState_Signed();
     void testInsertCertificate_DER_ODT();
     void testInsertCertificate_PEM_ODT();
+    void testInsertCertificate_PEM_DOCX();
     void testABI();
 
     CPPUNIT_TEST_SUITE(DesktopLOKTest);
@@ -171,6 +172,7 @@ public:
     CPPUNIT_TEST(testGetSignatureState_NonSigned);
     CPPUNIT_TEST(testInsertCertificate_DER_ODT);
     CPPUNIT_TEST(testInsertCertificate_PEM_ODT);
+    CPPUNIT_TEST(testInsertCertificate_PEM_DOCX);
     CPPUNIT_TEST(testABI);
     CPPUNIT_TEST_SUITE_END();
 
@@ -2420,6 +2422,68 @@ void DesktopLOKTest::testInsertCertificate_PEM_ODT()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void DesktopLOKTest::testInsertCertificate_PEM_DOCX()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    // Load the document, save it into a temp file and load that file again
+    LibLODocument_Impl* pDocument = loadDoc("blank_text.docx");
+    utl::TempFile aTempFile;
+    aTempFile.EnableKillingFile();
+    CPPUNIT_ASSERT(pDocument->pClass->saveAs(pDocument, aTempFile.GetURL().toUtf8().getStr(), "docx", nullptr));
+    closeDoc();
+
+    mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
+    pDocument = new LibLODocument_Impl(mxComponent);
+
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(mxComponent.is());
+    pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
+    Scheduler::ProcessEventsToIdle();
+
+    std::vector<unsigned char> aCertificate;
+    std::vector<unsigned char> aPrivateKey;
+
+    {
+        readFileIntoByteVector("test-cert-chain-1.pem", aCertificate);
+
+        bool bResult = pDocument->m_pDocumentClass->addCertificate(
+                            pDocument, aCertificate.data(), int(aCertificate.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    {
+        readFileIntoByteVector("test-cert-chain-2.pem", aCertificate);
+
+        bool bResult = pDocument->m_pDocumentClass->addCertificate(
+                            pDocument, aCertificate.data(), int(aCertificate.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    {
+        readFileIntoByteVector("test-cert-chain-3.pem", aCertificate);
+
+        bool bResult = pDocument->m_pDocumentClass->addCertificate(
+                            pDocument, aCertificate.data(), int(aCertificate.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    {
+        readFileIntoByteVector("test-cert-signing.pem", aCertificate);
+        readFileIntoByteVector("test-PK-signing.pem", aPrivateKey);
+
+        bool bResult = pDocument->m_pDocumentClass->insertCertificate(pDocument,
+                            aCertificate.data(), int(aCertificate.size()),
+                            aPrivateKey.data(), int(aPrivateKey.size()));
+        CPPUNIT_ASSERT(bResult);
+    }
+
+    int nState = pDocument->m_pDocumentClass->getSignatureState(pDocument);
+    CPPUNIT_ASSERT_EQUAL(int(5), nState);
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 namespace {
 
 size_t documentClassOffset(int i)
commit e41179f81ba8e8fd5b44e5d1dc0484a120f1e401
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Dec 26 20:44:57 2018 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Jan 3 07:34:19 2019 +0100

    lok: simplify and cleanup testInsertCertificate_{PEM,DER}_ODT
    
    Change-Id: I61891d1295a342e546cab56ef80315c9f5018f90
    Reviewed-on: https://gerrit.libreoffice.org/65629
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 5cd86cacc1ea69bcf94d298a385e4f711e9bce3c)

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index e7858c625106..18e20c8fd4d7 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -60,6 +60,8 @@ public:
     {
     }
 
+    void readFileIntoByteVector(OUString const & sFilename, std::vector<sal_uInt8> & rByteVector);
+
     virtual void setUp() override
     {
         UnoApiTest::setUp();
@@ -120,8 +122,8 @@ public:
     void testExtractParameter();
     void testGetSignatureState_NonSigned();
     void testGetSignatureState_Signed();
-    void testInsertCertificate();
-    void testInsertCertificatePEM();
+    void testInsertCertificate_DER_ODT();
+    void testInsertCertificate_PEM_ODT();
     void testABI();
 
     CPPUNIT_TEST_SUITE(DesktopLOKTest);
@@ -167,8 +169,8 @@ public:
     CPPUNIT_TEST(testExtractParameter);
     CPPUNIT_TEST(testGetSignatureState_Signed);
     CPPUNIT_TEST(testGetSignatureState_NonSigned);
-    CPPUNIT_TEST(testInsertCertificate);
-    CPPUNIT_TEST(testInsertCertificatePEM);
+    CPPUNIT_TEST(testInsertCertificate_DER_ODT);
+    CPPUNIT_TEST(testInsertCertificate_PEM_ODT);
     CPPUNIT_TEST(testABI);
     CPPUNIT_TEST_SUITE_END();
 
@@ -2250,6 +2252,16 @@ void DesktopLOKTest::testExtractParameter()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void DesktopLOKTest::readFileIntoByteVector(OUString const & sFilename, std::vector<unsigned char> & rByteVector)
+{
+    rByteVector.clear();
+    OUString aURL;
+    createFileURL(sFilename, aURL);
+    SvFileStream aStream(aURL, StreamMode::READ);
+    rByteVector.resize(aStream.remainingSize());
+    aStream.ReadBytes(rByteVector.data(), aStream.remainingSize());
+}
+
 void DesktopLOKTest::testGetSignatureState_Signed()
 {
     comphelper::LibreOfficeKit::setActive();
@@ -2259,28 +2271,16 @@ void DesktopLOKTest::testGetSignatureState_Signed()
     int nState = pDocument->m_pDocumentClass->getSignatureState(pDocument);
     CPPUNIT_ASSERT_EQUAL(int(4), nState);
 
+    std::vector<unsigned char> aCertificate;
     {
-        OUString aCertificateURL;
-        createFileURL("rootCA.der", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
+        readFileIntoByteVector("rootCA.der", aCertificate);
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
         CPPUNIT_ASSERT(bResult);
     }
 
     {
-        OUString aCertificateURL;
-        createFileURL("intermediateRootCA.der", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
-
+        readFileIntoByteVector("intermediateRootCA.der", aCertificate);
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
         CPPUNIT_ASSERT(bResult);
@@ -2303,7 +2303,7 @@ void DesktopLOKTest::testGetSignatureState_NonSigned()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
-void DesktopLOKTest::testInsertCertificate()
+void DesktopLOKTest::testInsertCertificate_DER_ODT()
 {
     comphelper::LibreOfficeKit::setActive();
 
@@ -2322,13 +2322,11 @@ void DesktopLOKTest::testInsertCertificate()
     pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
     Scheduler::ProcessEventsToIdle();
 
+    std::vector<unsigned char> aCertificate;
+    std::vector<unsigned char> aPrivateKey;
+
     {
-        OUString aCertificateURL;
-        createFileURL("rootCA.der", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
+        readFileIntoByteVector("rootCA.der", aCertificate);
 
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
@@ -2336,13 +2334,7 @@ void DesktopLOKTest::testInsertCertificate()
     }
 
     {
-        OUString aCertificateURL;
-        createFileURL("intermediateRootCA.der", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
+        readFileIntoByteVector("intermediateRootCA.der", aCertificate);
 
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
@@ -2350,20 +2342,8 @@ void DesktopLOKTest::testInsertCertificate()
     }
 
     {
-        OUString aCertificateURL;
-        createFileURL("certificate.der", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
-
-        OUString aPrivateKeyURL;
-        createFileURL("certificatePrivateKey.der", aPrivateKeyURL);
-        SvFileStream aPrivateKeyStream(aPrivateKeyURL, StreamMode::READ);
-        std::vector<unsigned char> aPrivateKey;
-        aPrivateKey.resize(aPrivateKeyStream.remainingSize());
-        aPrivateKeyStream.ReadBytes(aPrivateKey.data(), aPrivateKeyStream.remainingSize());
+        readFileIntoByteVector("certificate.der", aCertificate);
+        readFileIntoByteVector("certificatePrivateKey.der", aPrivateKey);
 
         bool bResult = pDocument->m_pDocumentClass->insertCertificate(pDocument,
                             aCertificate.data(), int(aCertificate.size()),
@@ -2378,7 +2358,7 @@ void DesktopLOKTest::testInsertCertificate()
 }
 
 
-void DesktopLOKTest::testInsertCertificatePEM()
+void DesktopLOKTest::testInsertCertificate_PEM_ODT()
 {
     comphelper::LibreOfficeKit::setActive();
 
@@ -2397,13 +2377,11 @@ void DesktopLOKTest::testInsertCertificatePEM()
     pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}");
     Scheduler::ProcessEventsToIdle();
 
+    std::vector<unsigned char> aCertificate;
+    std::vector<unsigned char> aPrivateKey;
+
     {
-        OUString aCertificateURL;
-        createFileURL("test-cert-chain-1.pem", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
+        readFileIntoByteVector("test-cert-chain-1.pem", aCertificate);
 
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
@@ -2411,13 +2389,7 @@ void DesktopLOKTest::testInsertCertificatePEM()
     }
 
     {
-        OUString aCertificateURL;
-        createFileURL("test-cert-chain-2.pem", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
+        readFileIntoByteVector("test-cert-chain-2.pem", aCertificate);
 
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
@@ -2425,13 +2397,7 @@ void DesktopLOKTest::testInsertCertificatePEM()
     }
 
     {
-        OUString aCertificateURL;
-        createFileURL("test-cert-chain-3.pem", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
+        readFileIntoByteVector("test-cert-chain-3.pem", aCertificate);
 
         bool bResult = pDocument->m_pDocumentClass->addCertificate(
                             pDocument, aCertificate.data(), int(aCertificate.size()));
@@ -2439,20 +2405,8 @@ void DesktopLOKTest::testInsertCertificatePEM()
     }
 
     {
-        OUString aCertificateURL;
-        createFileURL("test-cert-signing.pem", aCertificateURL);
-        SvFileStream aCertificateStream(aCertificateURL, StreamMode::READ);
-        std::vector<unsigned char> aCertificate;
-        aCertificate.resize(aCertificateStream.remainingSize());
-        aCertificateStream.ReadBytes(aCertificate.data(), aCertificateStream.remainingSize());
-
-
-        OUString aPrivateKeyURL;
-        createFileURL("test-PK-signing.pem", aPrivateKeyURL);
-        SvFileStream aPrivateKeyStream(aPrivateKeyURL, StreamMode::READ);
-        std::vector<unsigned char> aPrivateKey;
-        aPrivateKey.resize(aPrivateKeyStream.remainingSize());
-        aPrivateKeyStream.ReadBytes(aPrivateKey.data(), aPrivateKeyStream.remainingSize());
+        readFileIntoByteVector("test-cert-signing.pem", aCertificate);
+        readFileIntoByteVector("test-PK-signing.pem", aPrivateKey);
 
         bool bResult = pDocument->m_pDocumentClass->insertCertificate(pDocument,
                             aCertificate.data(), int(aCertificate.size()),
commit 540f4c06a025ede65addf3b894feab7b9ffece12
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Dec 24 15:11:30 2018 +0100
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Jan 3 07:34:03 2019 +0100

    Fix signing empty Configurations2/accelerator/current.xml
    
    When determining if a file is an XML file for siging, we need to
    read the manifest file to get an accurate detection. In case when
    we were signing in the GUI the manifest file was read when the
    storage was set. When we didn't sign over the GUI, the manifest
    was never read: the code was only present in the GUI code -
    "documentsignaturesdialog.cxx" so the detection was wrong and
    isXML returned "true" for current.xml.
    With this we move the manifest reading to DigitalSignatureManager,
    where the manifest is read when needed.
    
    Reviewed-on: https://gerrit.libreoffice.org/65600
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 49fcd3bbb30f93763fc5cb80fa6ac5cec5d00834)
    
    Change-Id: If45a32af6410bc5f7c5afdb976b182bd69ab7d6b

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 2b571921738c..e7858c625106 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -2371,6 +2371,9 @@ void DesktopLOKTest::testInsertCertificate()
         CPPUNIT_ASSERT(bResult);
     }
 
+    int nState = pDocument->m_pDocumentClass->getSignatureState(pDocument);
+    CPPUNIT_ASSERT_EQUAL(int(1), nState);
+
     comphelper::LibreOfficeKit::setActive(false);
 }
 
@@ -2457,6 +2460,9 @@ void DesktopLOKTest::testInsertCertificatePEM()
         CPPUNIT_ASSERT(bResult);
     }
 
+    int nState = pDocument->m_pDocumentClass->getSignatureState(pDocument);
+    CPPUNIT_ASSERT_EQUAL(int(1), nState);
+
     comphelper::LibreOfficeKit::setActive(false);
 }
 
diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx
index bae54619cbd5..6c70e55224dd 100644
--- a/xmlsecurity/inc/documentsignaturemanager.hxx
+++ b/xmlsecurity/inc/documentsignaturemanager.hxx
@@ -59,6 +59,8 @@ public:
      * differently when they are signed (c14n transformation)
      */
     bool isXML(const OUString& rURI);
+    bool readManifest();
+
     SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, bool bTempStream);
     /// Add a new signature, using xCert as a signing certificate, and rDescription as description.
     bool add(const css::uno::Reference<css::security::XCertificate>& xCert,
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index 8a1ba46860a6..4ac46e1d4163 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -36,7 +36,6 @@
 #include <com/sun/star/security/CertificateKind.hpp>
 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
-#include <com/sun/star/packages/manifest/ManifestReader.hpp>
 #include <com/sun/star/system/SystemShellExecute.hpp>
 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
 #include <com/sun/star/system/SystemShellExecuteException.hpp>
@@ -232,26 +231,6 @@ void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed
 {
     maSignatureManager.mxStore = rxStore;
     maSignatureManager.maSignatureHelper.SetStorage( maSignatureManager.mxStore, m_sODFVersion);
-
-    Reference < css::packages::manifest::XManifestReader > xReader =
-        css::packages::manifest::ManifestReader::create(mxCtx);
-
-    uno::Reference<container::XNameAccess> xNameAccess(rxStore, uno::UNO_QUERY);
-    if (!xNameAccess.is())
-        return;
-
-    if (xNameAccess->hasByName("META-INF"))
-    {
-        //Get the manifest.xml
-        Reference < css::embed::XStorage > xSubStore(rxStore->openStorageElement(
-                    "META-INF", css::embed::ElementModes::READ), UNO_QUERY_THROW);
-
-        Reference< css::io::XInputStream > xStream(
-            xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ),
-            UNO_QUERY_THROW);
-
-        maSignatureManager.m_manifest = xReader->readManifestSequence(xStream);
-    }
 }
 
 void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
index c65b73c3b85d..e95b92be1e28 100644
--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -29,6 +29,8 @@
 #include <com/sun/star/embed/XTransactedObject.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/packages/manifest/ManifestReader.hpp>
 
 #include <comphelper/storagehelper.hxx>
 #include <rtl/ustrbuf.hxx>
@@ -119,6 +121,40 @@ bool DocumentSignatureManager::IsXAdESRelevant()
 }
 #endif
 
+bool DocumentSignatureManager::readManifest()
+{
+    // Check if manifest was already read
+    if (m_manifest.getLength() > 0)
+        return true;
+
+    if (!mxContext.is())
+        return false;
+
+    if (!mxStore.is())
+        return false;
+
+    uno::Reference<packages::manifest::XManifestReader> xReader
+        = packages::manifest::ManifestReader::create(mxContext);
+
+    uno::Reference<container::XNameAccess> xNameAccess(mxStore, uno::UNO_QUERY);
+    if (!xNameAccess.is())
+        return false;
+
+    if (xNameAccess->hasByName("META-INF"))
+    {
+        //Get the manifest.xml
+        uno::Reference<embed::XStorage> xSubStore(
+            mxStore->openStorageElement("META-INF", embed::ElementModes::READ), uno::UNO_QUERY_THROW);
+
+        uno::Reference<io::XInputStream> xStream(
+            xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ),
+            uno::UNO_QUERY_THROW);
+
+        m_manifest = xReader->readManifestSequence(xStream);
+    }
+    return true;
+}
+
 /* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
     We use the manifest to find out if a file is xml and if it is encrypted.
     The parameter is an encoded uri. However, the manifest contains paths. Therefore
@@ -134,27 +170,30 @@ bool DocumentSignatureManager::isXML(const OUString& rURI)
     const OUString sPropMediaType("MediaType");
     const OUString sPropDigest("Digest");
 
-    for (int i = 0; i < m_manifest.getLength(); i++)
+    if (readManifest())
     {
-        const uno::Sequence<beans::PropertyValue>& entry = m_manifest[i];
-        OUString sPath, sMediaType;
-        bool bEncrypted = false;
-        for (int j = 0; j < entry.getLength(); j++)
+        for (int i = 0; i < m_manifest.getLength(); i++)
         {
-            const beans::PropertyValue& prop = entry[j];
-
-            if (prop.Name == sPropFullPath)
-                prop.Value >>= sPath;
-            else if (prop.Name == sPropMediaType)
-                prop.Value >>= sMediaType;
-            else if (prop.Name == sPropDigest)
-                bEncrypted = true;
-        }
-        if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
-        {
-            bIsXML = sMediaType == "text/xml" && ! bEncrypted;
-            bPropsAvailable = true;
-            break;
+            const uno::Sequence<beans::PropertyValue>& entry = m_manifest[i];
+            OUString sPath, sMediaType;
+            bool bEncrypted = false;
+            for (int j = 0; j < entry.getLength(); j++)
+            {
+                const beans::PropertyValue& prop = entry[j];
+
+                if (prop.Name == sPropFullPath)
+                    prop.Value >>= sPath;
+                else if (prop.Name == sPropMediaType)
+                    prop.Value >>= sMediaType;
+                else if (prop.Name == sPropDigest)
+                    bEncrypted = true;
+            }
+            if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
+            {
+                bIsXML = sMediaType == "text/xml" && !bEncrypted;
+                bPropsAvailable = true;
+                break;
+            }
         }
     }
     if (!bPropsAvailable)


More information about the Libreoffice-commits mailing list