summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2018-12-31 12:27:39 +0100
committerTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2019-01-03 07:34:39 +0100
commit277f4e186ce4a3f109c470b54a0accdb6c74e8cb (patch)
tree38e8b63430804013f810560a6e62c728fd14c8be /desktop
parent48595091cae4248711c4fc48e68887e9f138c8ad (diff)
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@gmail.com> (cherry picked from commit a8cb7cf68ff661b502e7c006fe4330098b5b0944) Change-Id: Id6f242e817f594aa672f94f9c6f9b34e4035d46a
Diffstat (limited to 'desktop')
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx62
-rw-r--r--desktop/source/lib/init.cxx78
2 files changed, 140 insertions, 0 deletions
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)