[Libreoffice-commits] core.git: 5 commits - vcl/source

Tor Lillqvist tml at collabora.com
Mon Feb 23 05:31:36 PST 2015


 vcl/source/gdi/pdfwriter_impl.cxx |  260 +++++++++++++++++++++++++++++++++++---
 1 file changed, 243 insertions(+), 17 deletions(-)

New commits:
commit 7d7c2ab1dffa82cfc0e2d6b15702d965b8b0245b
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Feb 23 15:27:01 2015 +0200

    tdf#84881: Call NSS_CMSSignerInfo_AddSigningTime() only if not using a TSA
    
    Something is still wrong, Adobe Reader still says the PDF is signed with the
    local machine's timestamp, though.
    
    Change-Id: Ic9ed3190901025be48e1de191df976e1aa454822

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 3cc60d0..3ac6de7 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6987,16 +6987,15 @@ bool PDFWriterImpl::finalizeSignature()
             return false;
         }
     }
-
-    if (NSS_CMSSignerInfo_IncludeCerts(cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)
+    else if (NSS_CMSSignerInfo_AddSigningTime(cms_signer, PR_Now()) != SECSuccess)
     {
-        SAL_WARN("vcl.pdfwriter", "PDF signing: can't include cert chain.");
+        SAL_WARN("vcl.pdfwriter", "PDF signing: can't add signing time.");
         return false;
     }
 
-    if (NSS_CMSSignerInfo_AddSigningTime(cms_signer, PR_Now()) != SECSuccess)
+    if (NSS_CMSSignerInfo_IncludeCerts(cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)
     {
-        SAL_WARN("vcl.pdfwriter", "PDF signing: can't add signing time.");
+        SAL_WARN("vcl.pdfwriter", "PDF signing: can't include cert chain.");
         return false;
     }
 
commit d1132ff3895aa67ed662446ef6f43612124455ae
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Feb 23 14:55:07 2015 +0200

    tdf#84881: Actually check the status of the time stamp response
    
    Change-Id: If8d64b1e03c8318cd3329cd258131fddeb86fa7b

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 9d14f13..3cc60d0 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6941,6 +6941,13 @@ bool PDFWriterImpl::finalizeSignature()
 
         SAL_INFO("vcl.pdfwriter", "TimeStampResp received and decoded, status=" << PKIStatusInfoToString(response.status));
 
+        if (response.status.status.len != 1 ||
+            (response.status.status.data[0] != 0 && response.status.status.data[0] != 1))
+        {
+            SAL_WARN("vcl.pdfwriter", "PDF signing: Timestamp request was not granted");
+            return false;
+        }
+
         NSSCMSAttribute timestamp;
 
         timestamp.type.type = siBuffer;
commit e075fec6e18b24f4037c11f015e870a470fa8ef8
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Feb 23 14:51:06 2015 +0200

    Copy SEC_StringToOID() and NSS_CMSSignerInfo_AddUnauthAttr() here
    
    Despite being declared in a public header, they are not exported from
    libsmime, so copy them here. Sigh.
    
    Fix fallout from fe480d8136b204c8dc6c68916cce7e816f8b9c48.
    
    Change-Id: I9ecba690a66c263528e5c12738d60cacec4f14ee

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 5f1be3d..9d14f13 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -74,6 +74,7 @@
 #include "nss.h"
 #include "cert.h"
 #include "hasht.h"
+#include "secerr.h"
 #include "sechash.h"
 #include "cms.h"
 #include "cmst.h"
@@ -6399,6 +6400,221 @@ OUString PKIStatusInfoToString(const PKIStatusInfo& rStatusInfo)
     return result;
 }
 
+// SEC_StringToOID() and NSS_CMSSignerInfo_AddUnauthAttr() are
+// not exported from libsmime, so copy them here. Sigh.
+
+SECStatus
+my_SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len)
+{
+    PRUint32 decimal_numbers = 0;
+    PRUint32 result_bytes = 0;
+    SECStatus rv;
+    PRUint8 result[1024];
+
+    static const PRUint32 max_decimal = (0xffffffff / 10);
+    static const char OIDstring[] = {"OID."};
+
+    if (!from || !to) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+    return SECFailure;
+    }
+    if (!len) {
+        len = PL_strlen(from);
+    }
+    if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
+        from += 4; /* skip leading "OID." if present */
+    len  -= 4;
+    }
+    if (!len) {
+bad_data:
+        PORT_SetError(SEC_ERROR_BAD_DATA);
+    return SECFailure;
+    }
+    do {
+    PRUint32 decimal = 0;
+        while (len > 0 && isdigit(*from)) {
+        PRUint32 addend = (*from++ - '0');
+        --len;
+        if (decimal > max_decimal)  /* overflow */
+            goto bad_data;
+        decimal = (decimal * 10) + addend;
+        if (decimal < addend)   /* overflow */
+        goto bad_data;
+    }
+    if (len != 0 && *from != '.') {
+        goto bad_data;
+    }
+    if (decimal_numbers == 0) {
+        if (decimal > 2)
+            goto bad_data;
+        result[0] = decimal * 40;
+        result_bytes = 1;
+    } else if (decimal_numbers == 1) {
+        if (decimal > 40)
+            goto bad_data;
+        result[0] += decimal;
+    } else {
+        /* encode the decimal number,  */
+        PRUint8 * rp;
+        PRUint32 num_bytes = 0;
+        PRUint32 tmp = decimal;
+        while (tmp) {
+            num_bytes++;
+        tmp >>= 7;
+        }
+        if (!num_bytes )
+            ++num_bytes;  /* use one byte for a zero value */
+        if (num_bytes + result_bytes > sizeof result)
+            goto bad_data;
+        tmp = num_bytes;
+        rp = result + result_bytes - 1;
+        rp[tmp] = (PRUint8)(decimal & 0x7f);
+        decimal >>= 7;
+        while (--tmp > 0) {
+        rp[tmp] = (PRUint8)(decimal | 0x80);
+        decimal >>= 7;
+        }
+        result_bytes += num_bytes;
+    }
+    ++decimal_numbers;
+    if (len > 0) { /* skip trailing '.' */
+        ++from;
+        --len;
+    }
+    } while (len > 0);
+    /* now result contains result_bytes of data */
+    if (to->data && to->len >= result_bytes) {
+        PORT_Memcpy(to->data, result, to->len = result_bytes);
+    rv = SECSuccess;
+    } else {
+        SECItem result_item = {siBuffer, NULL, 0 };
+    result_item.data = result;
+    result_item.len  = result_bytes;
+    rv = SECITEM_CopyItem(pool, to, &result_item);
+    }
+    return rv;
+}
+
+NSSCMSAttribute *
+my_NSS_CMSAttributeArray_FindAttrByOidTag(NSSCMSAttribute **attrs, SECOidTag oidtag, PRBool only)
+{
+    SECOidData *oid;
+    NSSCMSAttribute *attr1, *attr2;
+
+    if (attrs == NULL)
+        return NULL;
+
+    oid = SECOID_FindOIDByTag(oidtag);
+    if (oid == NULL)
+        return NULL;
+
+    while ((attr1 = *attrs++) != NULL) {
+    if (attr1->type.len == oid->oid.len && PORT_Memcmp (attr1->type.data,
+                                oid->oid.data,
+                                oid->oid.len) == 0)
+        break;
+    }
+
+    if (attr1 == NULL)
+        return NULL;
+
+    if (!only)
+        return attr1;
+
+    while ((attr2 = *attrs++) != NULL) {
+    if (attr2->type.len == oid->oid.len && PORT_Memcmp (attr2->type.data,
+                                oid->oid.data,
+                                oid->oid.len) == 0)
+        break;
+    }
+
+    if (attr2 != NULL)
+        return NULL;
+
+    return attr1;
+}
+
+SECStatus
+my_NSS_CMSArray_Add(PLArenaPool *poolp, void ***array, void *obj)
+{
+    void **p;
+    int n;
+    void **dest;
+
+    PORT_Assert(array != NULL);
+    if (array == NULL)
+        return SECFailure;
+
+    if (*array == NULL) {
+    dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *));
+    n = 0;
+    } else {
+    n = 0; p = *array;
+    while (*p++)
+        n++;
+    dest = (void **)PORT_ArenaGrow (poolp,
+                  *array,
+                  (n + 1) * sizeof(void *),
+                  (n + 2) * sizeof(void *));
+    }
+
+    if (dest == NULL)
+        return SECFailure;
+
+    dest[n] = obj;
+    dest[n+1] = NULL;
+    *array = dest;
+    return SECSuccess;
+}
+
+SECOidTag
+my_NSS_CMSAttribute_GetType(NSSCMSAttribute *attr)
+{
+    SECOidData *typetag;
+
+    typetag = SECOID_FindOID(&(attr->type));
+    if (typetag == NULL)
+        return SEC_OID_UNKNOWN;
+
+    return typetag->offset;
+}
+
+SECStatus
+my_NSS_CMSAttributeArray_AddAttr(PLArenaPool *poolp, NSSCMSAttribute ***attrs, NSSCMSAttribute *attr)
+{
+    NSSCMSAttribute *oattr;
+    void *mark;
+    SECOidTag type;
+
+    mark = PORT_ArenaMark(poolp);
+
+    /* find oidtag of attr */
+    type = my_NSS_CMSAttribute_GetType(attr);
+
+    /* see if we have one already */
+    oattr = my_NSS_CMSAttributeArray_FindAttrByOidTag(*attrs, type, PR_FALSE);
+    PORT_Assert (oattr == NULL);
+    if (oattr != NULL)
+        goto loser; /* XXX or would it be better to replace it? */
+
+    /* no, shove it in */
+    if (my_NSS_CMSArray_Add(poolp, reinterpret_cast<void ***>(attrs), (void *)attr) != SECSuccess)
+        goto loser;
+
+    PORT_ArenaUnmark(poolp, mark);
+    return SECSuccess;
+
+loser:
+    PORT_ArenaRelease(poolp, mark);
+    return SECFailure;
+}
+
+SECStatus
+my_NSS_CMSSignerInfo_AddUnauthAttr(NSSCMSSignerInfo *signerinfo, NSSCMSAttribute *attr)
+{
+    return my_NSS_CMSAttributeArray_AddAttr(signerinfo->cmsg->poolp, &(signerinfo->unAuthAttr), attr);
+}
+
 #if 0
 {
 #endif
@@ -6725,11 +6941,6 @@ bool PDFWriterImpl::finalizeSignature()
 
         SAL_INFO("vcl.pdfwriter", "TimeStampResp received and decoded, status=" << PKIStatusInfoToString(response.status));
 
-#if 0   // SEC_StringToOID() and NSS_CMSSignerInfo_AddUnauthAttr() are
-        // not exported from libsmime, need to think of some other
-        // approach. (As such I don't know if the code below would do
-        // the right thing even if they were.)
-
         NSSCMSAttribute timestamp;
 
         timestamp.type.type = siBuffer;
@@ -6750,7 +6961,7 @@ bool PDFWriterImpl::finalizeSignature()
         // id-aa-timeStampToken OBJECT IDENTIFIER ::= { iso(1)
         // member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)
         // smime(16) aa(2) 14 }
-        if (SEC_StringToOID(NULL, &typetag.oid, "1.2.840.113549.1.9.16.14", 0) != SECSuccess)
+        if (my_SEC_StringToOID(NULL, &typetag.oid, "1.2.840.113549.1.9.16.14", 0) != SECSuccess)
         {
             SAL_WARN("vcl.pdfwriter", "PDF signing: SEC_StringToOID failed");
             return false;
@@ -6761,14 +6972,13 @@ bool PDFWriterImpl::finalizeSignature()
         typetag.supportedExtension = UNSUPPORTED_CERT_EXTENSION; // ???
         timestamp.typeTag = &typetag;
 
-        timestamp.encoded = PR_FALSE;
+        timestamp.encoded = PR_TRUE;
 
-        if (NSS_CMSSignerInfo_AddUnauthAttr(cms_signer, &timestamp) != SECSuccess)
+        if (my_NSS_CMSSignerInfo_AddUnauthAttr(cms_signer, &timestamp) != SECSuccess)
         {
             SAL_WARN("vcl.pdfwriter", "PDF signing: can't add timestamp attribute");
             return false;
         }
-#endif
     }
 
     if (NSS_CMSSignerInfo_IncludeCerts(cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)
commit 639730a75294346d4195539c26f466f14d030802
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Feb 23 14:42:08 2015 +0200

    tdf#84881: Unclear what the PKIStatusInfo::statusString is
    
    Anyway, we can't assume that a string from an external source is correctly
    formed UTF-8.
    
    Change-Id: Ic906c7047b933388d5b51b23095a5a3d4ac7e508

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index b0ec568..5f1be3d 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6385,10 +6385,12 @@ OUString PKIStatusInfoToString(const PKIStatusInfo& rStatusInfo)
         result += PKIStatusToString(rStatusInfo.status.data[0]);
     else
         result += "unknown (len=" + OUString::number(rStatusInfo.status.len);
-    if (rStatusInfo.statusString.data != NULL)
-        result += ",statusString='" +
-            OUString::fromUtf8(OString(reinterpret_cast<const sal_Char*>(rStatusInfo.statusString.data), rStatusInfo.statusString.len)) +
-            "'";
+
+    // FIXME: Perhaps look at rStatusInfo.statusString.data but note
+    // that we of course can't assume it contains proper UTF-8. After
+    // all, it is data from an external source. Also, RFC3161 claims
+    // it should be a SEQUENCE (1..MAX) OF UTF8String, but another
+    // source claimed it would be a single UTF8String, hmm?
 
     // FIXME: Worth it to decode failInfo to cleartext, probably not at least as long as this is only for a SAL_INFO
 
commit f4f08203ba4acebb4ae3143323ca508fdc0644bd
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Feb 23 14:21:53 2015 +0200

    tdf#84881: Dump also the CMS data in a DBG_UTIL build
    
    Change-Id: I651041a86083eb49aad9a96f6f379149c21854f3

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 2e31647..b0ec568 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6833,6 +6833,14 @@ bool PDFWriterImpl::finalizeSignature()
 
     free(pass);
 
+#ifdef DBG_UTIL
+    {
+        FILE *out = fopen("PDFWRITER.cms.data", "wb");
+        fwrite(cms_output.data, cms_output.len, 1, out);
+        fclose(out);
+    }
+#endif
+
     OStringBuffer cms_hexbuffer;
 
     for (unsigned int i = 0; i < cms_output.len ; i++)


More information about the Libreoffice-commits mailing list