summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2018-11-09 08:47:49 +0100
committerTomaž Vajngerl <quikee@gmail.com>2018-11-09 09:06:51 +0100
commit37e1e208c218077c46c5370d2caf5be722e7452e (patch)
treedd46c674be49a6dffec9e0eaf0a90a4ae0a3fb73
parent40442bfaa6da0730422ba7e057a3ef2ecde88ffc (diff)
add "sign" function to infobar to sign with a one-time cert.
In addition: - add methods to transport the certificate chain, signing certificate and signing certificate to WSD - add conversion of PEM cert. format to DER - add transporting the certificate chain to the LO core - run the signing function with the signing cert. and the private key Change-Id: I1a005e88cacbd81144df40d315197561401db427 Reviewed-on: https://gerrit.libreoffice.org/63156 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--kit/ChildSession.cpp100
-rw-r--r--loleaflet/js/toolbar.js4
-rw-r--r--loleaflet/src/control/Signing.js17
3 files changed, 118 insertions, 3 deletions
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index 4e6c3ef7a..b775c6784 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -21,8 +21,11 @@
#include <Poco/Net/WebSocket.h>
#include <Poco/StringTokenizer.h>
#include <Poco/URI.h>
+#include <Poco/BinaryReader.h>
+#include <Poco/Base64Decoder.h>
#include <common/FileUtil.hpp>
+#include <common/JsonUtil.hpp>
#include "KitHelper.hpp"
#include <Log.hpp>
#include <Png.hpp>
@@ -245,7 +248,9 @@ bool ChildSession::_handleInput(const char *buffer, int length)
tokens[0] == "saveas" ||
tokens[0] == "useractive" ||
tokens[0] == "userinactive" ||
- tokens[0] == "windowcommand");
+ tokens[0] == "windowcommand" ||
+ tokens[0] == "asksignaturestatus" ||
+ tokens[0] == "signdocument");
if (tokens[0] == "clientzoom")
{
@@ -1112,9 +1117,98 @@ bool ChildSession::sendWindowCommand(const char* /*buffer*/, int /*length*/, con
return true;
}
-bool ChildSession::signDocumentContent(const char* /*buffer*/, int /*length*/, const std::vector<std::string>& /*tokens*/)
+namespace
{
- return true;
+
+std::string extractCertificate(const std::string & certificate)
+{
+ const std::string header("-----BEGIN CERTIFICATE-----");
+ const std::string 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 + std::string(header).length();
+ pos2 = pos2 - pos1;
+
+ return certificate.substr(pos1, pos2);
+}
+
+std::string extractPrivateKey(const std::string & privateKey)
+{
+ const std::string header("-----BEGIN PRIVATE KEY-----");
+ const std::string 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 + std::string(header).length();
+ pos2 = pos2 - pos1;
+
+ return privateKey.substr(pos1, pos2);
+}
+
+std::vector<unsigned char> decodeBase64(const std::string & inputBase64)
+{
+ std::istringstream stream(inputBase64);
+ Poco::Base64Decoder base64Decoder(stream);
+ std::istreambuf_iterator<char> eos;
+ return std::vector<unsigned char>(std::istreambuf_iterator<char>(base64Decoder), eos);
+}
+
+}
+
+bool ChildSession::signDocumentContent(const char* buffer, int length, const std::vector<std::string>& /*tokens*/)
+{
+ bool bResult = true;
+
+ const std::string firstLine = getFirstLine(buffer, length);
+ const char* data = buffer + firstLine.size() + 1;
+ const int size = length - firstLine.size() - 1;
+ std::string json(data, size);
+
+ Poco::JSON::Parser parser;
+ Poco::JSON::Object::Ptr root = parser.parse(json).extract<Poco::JSON::Object::Ptr>();
+
+ for (auto& chainPtr : *root->getArray("chain"))
+ {
+ assert(chainPtr.isString());
+ std::string chainCertificate = chainPtr;
+ std::vector<unsigned char> binaryChainCertificate = decodeBase64(extractCertificate(chainCertificate));
+
+ bResult = getLOKitDocument()->addCertificate(
+ binaryChainCertificate.data(),
+ binaryChainCertificate.size());
+
+ if (!bResult)
+ return false;
+ }
+
+ std::string x509Certificate = JsonUtil::getJSONValue<std::string>(root, "x509Certificate");
+ std::vector<unsigned char> binaryCertificate = decodeBase64(extractCertificate(x509Certificate));
+
+ std::string privateKey = JsonUtil::getJSONValue<std::string>(root, "privateKey");
+ std::vector<unsigned char> binaryPrivateKey = decodeBase64(extractPrivateKey(privateKey));
+
+ bResult = getLOKitDocument()->insertCertificate(
+ binaryCertificate.data(), binaryCertificate.size(),
+ binaryPrivateKey.data(), binaryPrivateKey.size());
+
+ return bResult;
}
bool ChildSession::askSignatureStatus(const char* /*buffer*/, int /*length*/, const std::vector<std::string>& /*tokens*/)
diff --git a/loleaflet/js/toolbar.js b/loleaflet/js/toolbar.js
index 53a3a1b7b..51b84902c 100644
--- a/loleaflet/js/toolbar.js
+++ b/loleaflet/js/toolbar.js
@@ -234,6 +234,9 @@ function onClick(e, id, item, subItem) {
else if (id === 'logout') {
map.signingLogout();
}
+ else if (id === 'sign') {
+ map.signDocument();
+ }
}
function setBorders(left, right, bottom, top, horiz, vert) {
@@ -767,6 +770,7 @@ function createToolbar() {
items: [
{type: 'html', id: 'left'},
{type: 'html', id: 'logo', html: '<p><b>Vereign</b></p>'},
+ {type: 'button', id: 'sign', caption: 'Sign', img: '', hint: _('Sign document')},
{type: 'break' },
{type: 'html', id: 'user-label', html: '<p>User:</p>'},
{type: 'html', id: 'user', html: '<none>'},
diff --git a/loleaflet/src/control/Signing.js b/loleaflet/src/control/Signing.js
index 58191aa4d..0264d2b0c 100644
--- a/loleaflet/src/control/Signing.js
+++ b/loleaflet/src/control/Signing.js
@@ -34,6 +34,23 @@ L.Map.include({
showSignDocument: function() {
this.signingLogin();
},
+ signDocument: function() {
+ if (library) {
+ var map = this;
+ library.getCurrentlyLoggedInUUID().then(function(result) {
+ if (isSuccess(result)) {
+ var UUID = result.data;
+ library.getOneTimeCertificateByPassport(UUID).then(function(result) {
+ if (isSuccess(result)) {
+ var otp = result.data;
+ var blob = new Blob(['signdocument\n', JSON.stringify(otp)]);
+ map._socket.sendMessage(blob);
+ }
+ });
+ }
+ });
+ }
+ },
signingLogout: function() {
if (library) {
library.logout().then(function(result) {