[Libreoffice-commits] core.git: 3 commits - vcl/Library_vcl.mk vcl/source

Tor Lillqvist tml at collabora.com
Thu Feb 19 04:28:02 PST 2015


 vcl/Library_vcl.mk                |    2 
 vcl/source/gdi/pdfwriter_impl.cxx |  208 ++++++++++++++++++++++++++++++--------
 2 files changed, 171 insertions(+), 39 deletions(-)

New commits:
commit 27d7aea00d22ad3fcdff2e7b267be1cf5c28d43c
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Feb 19 13:57:52 2015 +0200

    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

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index e8df725..e114ae3 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 2f74f94..bb0c3f5 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)
commit 2ddfaa6d323b5db2f59f06f7708c5209549abeee
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Feb 19 11:34:52 2015 +0200

    tdf#84881: reqPolicy and certReq are optional
    
    Change-Id: Ia5687bf2d68eef06aeb618d5387c663807d24560

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 4865918..2f74f94 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6156,9 +6156,9 @@ const SEC_ASN1Template TimeStampReq_Template[] =
     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(TimeStampReq) },
     { SEC_ASN1_INTEGER, offsetof(TimeStampReq, version), 0, 0 },
     { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(TimeStampReq, messageImprint), SEC_ASN1_SUB(MessageImprint_Template), 0 },
-    { SEC_ASN1_OBJECT_ID, offsetof(TimeStampReq, reqPolicy), 0, 0 },
+    { SEC_ASN1_OBJECT_ID | SEC_ASN1_OPTIONAL, offsetof(TimeStampReq, reqPolicy), 0, 0 },
     { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, offsetof(TimeStampReq, nonce), 0, 0 },
-    { SEC_ASN1_BOOLEAN, offsetof(TimeStampReq, certReq), 0, 0 },
+    { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, offsetof(TimeStampReq, certReq), 0, 0 },
     { SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(TimeStampReq, extensions), SEC_ASN1_SUB(Extensions_Template), 0 },
     { 0, 0, 0, 0 }
 };
@@ -6339,10 +6339,9 @@ bool PDFWriterImpl::finalizeSignature()
         src.nonce.data = reinterpret_cast<unsigned char*>(&nNonce);
         src.nonce.len = sizeof(nNonce);
 
-        unsigned char cFalse = false;
-        src.certReq.type = siUnsignedInteger;
-        src.certReq.data = &cFalse;
-        src.certReq.len = sizeof(cFalse);
+        src.certReq.type = siBuffer;
+        src.certReq.data = NULL;
+        src.certReq.len = 0;
 
         src.extensions = NULL;
 
commit 159a4c3c75e3a7aecbf1656f3254331892098ba7
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Feb 19 11:08:33 2015 +0200

    tdf#84881: WiP: Fill in more fields of the TimeStampReq
    
    Use the digestAlg in the NSSCMSSignerInfo, once we have it, as
    hashAlgorithm. Use a random number as nonce.
    
    Temporarily, dump the TimeStampReq object to a file for inspection in a
    DBG_UTIL build.
    
    Change-Id: I696271b3ccc6cef86a70bc78f86d6eae27a4af77

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index edd69c9..4865918 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -34,6 +34,7 @@
 #include <com/sun/star/util/URL.hpp>
 #include <com/sun/star/util/URLTransformer.hpp>
 #include <comphelper/processfactory.hxx>
+#include <comphelper/random.hxx>
 #include <comphelper/string.hxx>
 #include <cppuhelper/implbase1.hxx>
 #include <i18nlangtag/languagetag.hxx>
@@ -6039,6 +6040,13 @@ public:
 };
 
 /*
+AlgorithmIdentifier  ::=  SEQUENCE  {
+     algorithm  OBJECT IDENTIFIER,
+     parameters ANY DEFINED BY algorithm OPTIONAL  }
+                   -- contains a value of the type
+                   -- registered for use with the
+                   -- algorithm object identifier value
+
 MessageImprint ::= SEQUENCE  {
     hashAlgorithm AlgorithmIdentifier,
     hashedMessage OCTET STRING  }
@@ -6080,6 +6088,8 @@ typedef struct {
 } Accuracy;
 
 /*
+TSAPolicyId ::= OBJECT IDENTIFIER
+
 TimeStampReq ::= SEQUENCE  {
     version            INTEGER  { v1(1) },
     messageImprint     MessageImprint,
@@ -6271,42 +6281,6 @@ bool PDFWriterImpl::finalizeSignature()
     HASH_End(hc.get(), digest.data, &digest.len, SHA1_LENGTH);
     hc.clear();
 
-    TimeStampReq src;
-
-    unsigned char cOne = 1;
-    src.version.type = siUnsignedInteger;
-    src.version.data = &cOne;
-    src.version.len = sizeof(cOne);
-
-    // FIXME, use proper contents
-    src.messageImprint.hashAlgorithm.algorithm.type = siBuffer;
-    src.messageImprint.hashAlgorithm.algorithm.data = NULL;
-    src.messageImprint.hashAlgorithm.algorithm.len = 0;
-    src.messageImprint.hashAlgorithm.parameters.type = siBuffer;
-    src.messageImprint.hashAlgorithm.parameters.data = NULL;
-    src.messageImprint.hashAlgorithm.parameters.len = 0;
-    src.messageImprint.hashedMessage = digest;
-
-    src.reqPolicy.type = siBuffer;
-    src.reqPolicy.data = NULL;
-    src.reqPolicy.len = 0;
-
-    // FIXME, need a proper nonce
-    src.nonce.type = siBuffer;
-    src.nonce.data = NULL;
-    src.nonce.len = 0;
-
-    unsigned char cFalse = false;
-    src.certReq.type = siUnsignedInteger;
-    src.certReq.data = &cFalse;
-    src.certReq.len = sizeof(cFalse);
-
-    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_FreeItem(item, PR_TRUE);
-
     NSSCMSMessage *cms_msg = NSS_CMSMessage_Create(NULL);
     if (!cms_msg)
     {
@@ -6343,6 +6317,50 @@ bool PDFWriterImpl::finalizeSignature()
         return false;
     }
 
+    // Now we have the hash algorithm as a SECItem available in cms_siger->digestAlg
+    if( !m_aContext.SignTSA.isEmpty() )
+    {
+        TimeStampReq src;
+
+        unsigned char cOne = 1;
+        src.version.type = siUnsignedInteger;
+        src.version.data = &cOne;
+        src.version.len = sizeof(cOne);
+
+        src.messageImprint.hashAlgorithm = cms_signer->digestAlg;
+        src.messageImprint.hashedMessage = digest;
+
+        src.reqPolicy.type = siBuffer;
+        src.reqPolicy.data = NULL;
+        src.reqPolicy.len = 0;
+
+        unsigned int nNonce = comphelper::rng::uniform_uint_distribution(0, SAL_MAX_UINT32);
+        src.nonce.type = siUnsignedInteger;
+        src.nonce.data = reinterpret_cast<unsigned char*>(&nNonce);
+        src.nonce.len = sizeof(nNonce);
+
+        unsigned char cFalse = false;
+        src.certReq.type = siUnsignedInteger;
+        src.certReq.data = &cFalse;
+        src.certReq.len = sizeof(cFalse);
+
+        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));
+
+#ifdef DBG_UTIL
+        if (item && item->data)
+        {
+            FILE *out = fopen("PDFWRITER.timestampreq.data", "wb");
+            fwrite(item->data, item->len, 1, out);
+            fclose(out);
+        }
+#endif
+
+        SECITEM_FreeItem(item, PR_TRUE);
+    }
+
     if (NSS_CMSSignerInfo_IncludeCerts(cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)
     {
         SAL_WARN("vcl.pdfwriter", "PDF signing: can't include cert chain.");


More information about the Libreoffice-commits mailing list