summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2015-02-19 13:57:52 +0200
committerTor Lillqvist <tml@collabora.com>2015-02-19 14:07:42 +0200
commit27d7aea00d22ad3fcdff2e7b267be1cf5c28d43c (patch)
treeb9e3c74fa31ed699a71c68b06f61baf3d84e9697
parent2ddfaa6d323b5db2f59f06f7708c5209549abeee (diff)
tdf#84881: Work in progress: Perform the RFC3161 interaction with the TSA
Use libcurl to perform the request and get the response. Improve error messages (only use SAL_WARN, though, so sadly not visible to end-users). Still to do: Decode the response and attach it to the signature. Implement request encoding and response decoding for Windows. I probably should extend (and rename) the HashContextScope class to handle all resources that need explicit deallocation, instead of calling curl_slist_free_all(), curl_easy_cleanup() and SECITEM_FreeItem() in so many places. The error handling of the PDF export functionality would need to be re-designed so that we could show actual error messages to the user instead of generic "signing failed" ones. But that is typical for much of our code... Change-Id: I6288de3f09021f8e0f385870143fefffbac2a706
-rw-r--r--vcl/Library_vcl.mk2
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx125
2 files changed, 121 insertions, 6 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index e8df725ebe32..e114ae301909 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -59,6 +59,8 @@ $(eval $(call gb_Library_use_custom_headers,vcl,\
))
$(eval $(call gb_Library_use_externals,vcl,\
+ $(if $(filter LINUX MACOSX,$(OS)), \
+ curl) \
jpeg \
$(if $(filter-out WNT,$(OS)), \
nss3 \
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 2f74f941ff01..bb0c3f59f722 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -77,6 +77,9 @@
#include "sechash.h"
#include "cms.h"
#include "cmst.h"
+
+// We use curl for RFC3161 time stamp requests
+#include <curl/curl.h>
#endif
#ifdef _WIN32
@@ -6163,12 +6166,20 @@ const SEC_ASN1Template TimeStampReq_Template[] =
{ 0, 0, 0, 0 }
};
+size_t AppendToBuffer(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ OStringBuffer *pBuffer = reinterpret_cast<OStringBuffer*>(userdata);
+ pBuffer->append(ptr, size*nmemb);
+
+ return size*nmemb;
+}
+
#if 0
{
#endif
} // anonymous namespace
-#endif
+#endif // !defined(ANDROID) && !defined(IOS) && !defined(_WIN32)
#ifdef _WIN32
@@ -6345,19 +6356,121 @@ bool PDFWriterImpl::finalizeSignature()
src.extensions = NULL;
- SECItem* item = SEC_ASN1EncodeItem(NULL, NULL, &src, TimeStampReq_Template);
- SAL_INFO("vcl.pdfwriter", "item=" << item << " data=" << (item ? (void*)item->data : nullptr) << " len=" << (item ? item->len : -1));
+ SECItem* timestamp_request = SEC_ASN1EncodeItem(NULL, NULL, &src, TimeStampReq_Template);
+ if (timestamp_request == NULL)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: SEC_ASN1EncodeItem failed");
+ return false;
+ }
+
+ if (timestamp_request->data == NULL)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: SEC_ASN1EncodeItem succeeded but got NULL data");
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ SAL_INFO("vcl.pdfwriter", "request len=" << (timestamp_request ? timestamp_request->len : -1));
#ifdef DBG_UTIL
- if (item && item->data)
{
FILE *out = fopen("PDFWRITER.timestampreq.data", "wb");
- fwrite(item->data, item->len, 1, out);
+ fwrite(timestamp_request->data, timestamp_request->len, 1, out);
+ fclose(out);
+ }
+#endif
+
+ // Send time stamp request to TSA server, receive response
+
+ CURL* curl = curl_easy_init();
+ struct curl_slist* slist = NULL;
+
+ if (!curl)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_init failed");
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ SAL_INFO("vcl.pdfwriter", "Setting curl to verbose: " << (curl_easy_setopt(curl, CURLOPT_VERBOSE, 1) == CURLE_OK ? "OK" : "FAIL"));
+
+ if (curl_easy_setopt(curl, CURLOPT_URL, OUStringToOString(m_aContext.SignTSA, RTL_TEXTENCODING_UTF8).getStr()) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_setopt(CURLOPT_URL) failed");
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ slist = curl_slist_append(slist, "Content-Type: application/timestamp-query");
+ slist = curl_slist_append(slist, "Accept: application/timestamp-reply");
+
+ if (curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_setopt(CURLOPT_HTTPHEADER) failed");
+ curl_slist_free_all(slist);
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ if (curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, timestamp_request->len) != CURLE_OK ||
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, timestamp_request->data) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_setopt(CURLOPT_POSTFIELDSIZE or CURLOPT_POSTFIELDS) failed");
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ OStringBuffer reply_buffer;
+
+ if (curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reply_buffer) != CURLE_OK ||
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, AppendToBuffer) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_setopt(CURLOPT_WRITEDATA or CURLOPT_WRITEFUNCTION) failed");
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ if (curl_easy_setopt(curl, CURLOPT_POST, 1) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_setopt(CURLOPT_POST) failed");
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ char error_buffer[CURL_ERROR_SIZE];
+ if (curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_setopt(CURLOPT_ERRORBUFFER) failed");
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+ if (curl_easy_perform(curl) != CURLE_OK)
+ {
+ SAL_WARN("vcl.pdfwriter", "PDF signing: curl_easy_perform failed: " << error_buffer);
+ curl_easy_cleanup(curl);
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
+ return false;
+ }
+
+#ifdef DBG_UTIL
+ {
+ FILE *out = fopen("PDFWRITER.reply.data", "wb");
+ fwrite(reply_buffer.getStr(), reply_buffer.getLength(), 1, out);
fclose(out);
}
#endif
- SECITEM_FreeItem(item, PR_TRUE);
+ curl_slist_free_all(slist);
+ curl_easy_cleanup(curl);
+
+ SECITEM_FreeItem(timestamp_request, PR_TRUE);
}
if (NSS_CMSSignerInfo_IncludeCerts(cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)