[Libreoffice-commits] core.git: 2 commits - external/libxmlsec xmlsecurity/source

Miklos Vajna vmiklos at collabora.co.uk
Mon Jan 25 09:27:15 PST 2016


 external/libxmlsec/xmlsec1-ooxml.patch.1          |  248 ++++++++++++++++++++--
 xmlsecurity/source/helper/ooxmlsecparser.cxx      |   27 ++
 xmlsecurity/source/helper/ooxmlsecparser.hxx      |    4 
 xmlsecurity/source/helper/xmlsignaturehelper2.cxx |   22 +
 xmlsecurity/source/helper/xsecctl.hxx             |    1 
 5 files changed, 273 insertions(+), 29 deletions(-)

New commits:
commit 937eb672f43fd26cea5f7dcf559f9ed3f662b804
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Jan 25 18:08:18 2016 +0100

    libxmlsec: canonize in the OOXML RelationshipTransform
    
    This is still a skeleton, but now we canonize the incoming data, not just
    eat it and output nothing -> at the end we don't hit an assertion that
    the output of the transform chain is nothing.
    
    Change-Id: I28509b8a493c6bf6cdcbb23b95ae7de8947790c1

diff --git a/external/libxmlsec/xmlsec1-ooxml.patch.1 b/external/libxmlsec/xmlsec1-ooxml.patch.1
index 8a1dbe3..af92fbb 100644
--- a/external/libxmlsec/xmlsec1-ooxml.patch.1
+++ b/external/libxmlsec/xmlsec1-ooxml.patch.1
@@ -1,15 +1,15 @@
-From b7fb2699e3c383ae40f29369dc57afbd0d52004c Mon Sep 17 00:00:00 2001
+From 1770428d30a77e7c5e3344687369d83e04201f0b Mon Sep 17 00:00:00 2001
 From: Miklos Vajna <vmiklos at collabora.co.uk>
 Date: Mon, 25 Jan 2016 09:50:03 +0100
 Subject: [PATCH] OOXML Relationship Transform skeleton
 
 ---
- include/xmlsec/strings.h    |  3 ++
- include/xmlsec/transforms.h |  4 +++
- src/strings.c               |  3 ++
- src/transforms.c            | 11 ++++++
- src/xpath.c                 | 82 +++++++++++++++++++++++++++++++++++++++++++++
- 5 files changed, 103 insertions(+)
+ include/xmlsec/strings.h    |   3 +
+ include/xmlsec/transforms.h |   4 +
+ src/strings.c               |   3 +
+ src/transforms.c            |  11 ++
+ src/xpath.c                 | 279 ++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 300 insertions(+)
 
 diff --git a/include/xmlsec/strings.h b/include/xmlsec/strings.h
 index 07afb9d..9c72d1b 100644
@@ -77,10 +77,18 @@ index 2ed3fe8..9e5ad27 100644
      if(xmlSecTransformIdsRegister(xmlSecTransformXsltId) < 0) {
  	xmlSecError(XMLSEC_ERRORS_HERE,
 diff --git a/src/xpath.c b/src/xpath.c
-index 8b0b4f8..63b02d4 100644
+index 8b0b4f8..ddcd95d 100644
 --- a/src/xpath.c
 +++ b/src/xpath.c
-@@ -1144,5 +1144,87 @@ xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last,
+@@ -17,6 +17,7 @@
+ #include <libxml/xpath.h>
+ #include <libxml/xpathInternals.h>
+ #include <libxml/xpointer.h>
++#include <libxml/c14n.h>
+ 
+ #include <xmlsec/xmlsec.h>
+ #include <xmlsec/xmltree.h>
+@@ -1144,5 +1145,283 @@ xmlSecTransformVisa3DHackExecute(xmlSecTransformPtr transform, int last,
      return(0);
  }
  
@@ -95,8 +103,8 @@ index 8b0b4f8..63b02d4 100644
 +
 +static int xmlSecRelationshipInitialize (xmlSecTransformPtr transform);
 +static void xmlSecRelationshipFinalize (xmlSecTransformPtr transform);
-+static int xmlSecRelationshipReadNode (xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx);
-+static int xmlSecRelationshipExecute (xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx);
++static int xmlSecTransformRelationshipPopBin(xmlSecTransformPtr transform, xmlSecByte* data, xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx);
++static int xmlSecTransformRelationshipPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes, xmlSecTransformCtxPtr transformCtx);
 +
 +static xmlSecTransformKlass xmlSecRelationshipKlass =
 +{
@@ -108,17 +116,17 @@ index 8b0b4f8..63b02d4 100644
 +    xmlSecTransformUsageDSigTransform, /* xmlSecAlgorithmUsage usage; */
 +    xmlSecRelationshipInitialize, /* xmlSecTransformInitializeMethod initialize; */
 +    xmlSecRelationshipFinalize, /* xmlSecTransformFinalizeMethod finalize; */
-+    xmlSecRelationshipReadNode, /* xmlSecTransformNodeReadMethod readNode; */
++    NULL, /* xmlSecTransformNodeReadMethod readNode; */
 +    NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
 +    NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
 +    NULL, /* xmlSecTransformSetKeyMethod setKey; */
 +    NULL, /* xmlSecTransformValidateMethod validate; */
 +    xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
-+    xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
-+    xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
-+    NULL, /* xmlSecTransformPushXmlMethod pushXml; */
++    NULL, /* xmlSecTransformPushBinMethod pushBin; */
++    xmlSecTransformRelationshipPopBin, /* xmlSecTransformPopBinMethod popBin; */
++    xmlSecTransformRelationshipPushXml, /* xmlSecTransformPushXmlMethod pushXml; */
 +    NULL, /* xmlSecTransformPopXmlMethod popXml; */
-+    xmlSecRelationshipExecute, /* xmlSecTransformExecuteMethod execute; */
++    NULL, /* xmlSecTransformExecuteMethod execute; */
 +    NULL, /* void* reserved0; */
 +    NULL, /* void* reserved1; */
 +};
@@ -137,7 +145,7 @@ index 8b0b4f8..63b02d4 100644
 +
 +    ctx = xmlSecRelationshipGetCtx(transform);
 +    xmlSecAssert2(ctx != NULL, -1);
- 
++
 +    /* initialize context */
 +    memset(ctx, 0, sizeof(xmlSecRelationshipCtx));
 +    return 0;
@@ -155,18 +163,214 @@ index 8b0b4f8..63b02d4 100644
 +
 +    if (ctx->parserCtx != NULL)
 +	xmlFreeParserCtxt(ctx->parserCtx);
- 
++
 +    memset(ctx, 0, sizeof(xmlSecRelationshipCtx));
 +}
 +
-+static int xmlSecRelationshipReadNode(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx)
++static int xmlSecTransformRelationshipPushXml(xmlSecTransformPtr transform, xmlSecNodeSetPtr nodes, xmlSecTransformCtxPtr transformCtx)
 +{
-+    return 0;
++    xmlOutputBufferPtr buf;
++    int ret;
++
++    xmlSecAssert2(nodes != NULL, -1);
++    xmlSecAssert2(nodes->doc != NULL, -1);
++    xmlSecAssert2(transformCtx != NULL, -1);
++
++    /* check/update current transform status */
++    switch(transform->status)
++    {
++    case xmlSecTransformStatusNone:
++	transform->status = xmlSecTransformStatusWorking;
++	break;
++    case xmlSecTransformStatusWorking:
++    case xmlSecTransformStatusFinished:
++	return(0);
++    default:
++	xmlSecError(XMLSEC_ERRORS_HERE,
++		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++		    NULL,
++		    XMLSEC_ERRORS_R_INVALID_STATUS,
++		    "status=%d", transform->status);
++	return(-1);
++    }
++    xmlSecAssert2(transform->status == xmlSecTransformStatusWorking, -1);
++
++    /* prepare output buffer: next transform or ourselves */
++    if(transform->next != NULL)
++    {
++	buf = xmlSecTransformCreateOutputBuffer(transform->next, transformCtx);
++	if(buf == NULL)
++	{
++	    xmlSecError(XMLSEC_ERRORS_HERE,
++			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			"xmlSecTransformCreateOutputBuffer",
++			XMLSEC_ERRORS_R_XMLSEC_FAILED,
++			XMLSEC_ERRORS_NO_MESSAGE);
++	    return(-1);
++	}
++    } else
++    {
++	buf = xmlSecBufferCreateOutputBuffer(&(transform->outBuf));
++	if (buf == NULL)
++	{
++	    xmlSecError(XMLSEC_ERRORS_HERE,
++			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			"xmlSecBufferCreateOutputBuffer",
++			XMLSEC_ERRORS_R_XMLSEC_FAILED,
++			XMLSEC_ERRORS_NO_MESSAGE);
++	    return(-1);
++	}
++    }
+ 
++    ret = xmlC14NExecute(nodes->doc, (xmlC14NIsVisibleCallback)xmlSecNodeSetContains, nodes, XML_C14N_1_0, NULL, 0, buf);
++    if (ret < 0)
++    {
++	xmlSecError(XMLSEC_ERRORS_HERE,
++		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++		    "xmlC14NExecute",
++		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
++		    XMLSEC_ERRORS_NO_MESSAGE);
++	xmlOutputBufferClose(buf);
++	return(-1);
++    }
+ 
++    ret = xmlOutputBufferClose(buf);
++    if (ret < 0)
++    {
++	xmlSecError(XMLSEC_ERRORS_HERE,
++		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++		    "xmlOutputBufferClose",
++		    XMLSEC_ERRORS_R_XML_FAILED,
++		    XMLSEC_ERRORS_NO_MESSAGE);
++	return(-1);
++    }
++    transform->status = xmlSecTransformStatusFinished;
++    return(0);
 +}
 +
-+static int xmlSecRelationshipExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx)
++static int xmlSecTransformRelationshipPopBin(xmlSecTransformPtr transform, xmlSecByte* data, xmlSecSize maxDataSize, xmlSecSize* dataSize, xmlSecTransformCtxPtr transformCtx)
 +{
-+    return 0;
++    xmlSecBufferPtr out;
++    int ret;
++
++    xmlSecAssert2(data != NULL, -1);
++    xmlSecAssert2(dataSize != NULL, -1);
++    xmlSecAssert2(transformCtx != NULL, -1);
++
++    out = &(transform->outBuf);
++    if (transform->status == xmlSecTransformStatusNone)
++    {
++	xmlOutputBufferPtr buf;
++
++	xmlSecAssert2(transform->inNodes == NULL, -1);
++
++	/* todo: isn't it an error? */
++	if (transform->prev == NULL)
++	{
++	    (*dataSize) = 0;
++	    transform->status = xmlSecTransformStatusFinished;
++	    return(0);
++	}
++
++	/* get xml data from previous transform */
++	ret = xmlSecTransformPopXml(transform->prev, &(transform->inNodes), transformCtx);
++	if (ret < 0)
++	{
++	    xmlSecError(XMLSEC_ERRORS_HERE,
++			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			"xmlSecTransformPopXml",
++			XMLSEC_ERRORS_R_XMLSEC_FAILED,
++			XMLSEC_ERRORS_NO_MESSAGE);
++	    return(-1);
++	}
++
++	/* dump everything to internal buffer */
++	buf = xmlSecBufferCreateOutputBuffer(out);
++	if (buf == NULL)
++	{
++	    xmlSecError(XMLSEC_ERRORS_HERE,
++			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			"xmlSecBufferCreateOutputBuffer",
++			XMLSEC_ERRORS_R_XMLSEC_FAILED,
++			XMLSEC_ERRORS_NO_MESSAGE);
++	    return(-1);
++	}
++
++        ret = xmlC14NExecute(transform->inNodes->doc, (xmlC14NIsVisibleCallback)xmlSecNodeSetContains, transform->inNodes, XML_C14N_1_0, NULL, 0, buf);
++        if (ret < 0)
++	{
++            xmlSecError(XMLSEC_ERRORS_HERE,
++			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			"xmlSecTransformC14NExecute",
++			XMLSEC_ERRORS_R_XMLSEC_FAILED,
++			XMLSEC_ERRORS_NO_MESSAGE);
++	    xmlOutputBufferClose(buf);
++	    return(-1);
++	}
++	ret = xmlOutputBufferClose(buf);
++	if (ret < 0)
++	{
++	    xmlSecError(XMLSEC_ERRORS_HERE,
++			xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			"xmlOutputBufferClose",
++			XMLSEC_ERRORS_R_XML_FAILED,
++			XMLSEC_ERRORS_NO_MESSAGE);
++	    return(-1);
++	}
++	transform->status = xmlSecTransformStatusWorking;
++    }
++
++    if (transform->status == xmlSecTransformStatusWorking)
++    {
++	xmlSecSize outSize;
++
++	/* return chunk after chunk */
++	outSize = xmlSecBufferGetSize(out);
++	if (outSize > maxDataSize)
++	{
++	    outSize = maxDataSize;
++	}
++	if (outSize > XMLSEC_TRANSFORM_BINARY_CHUNK)
++	{
++	    outSize = XMLSEC_TRANSFORM_BINARY_CHUNK;
++	}
++	if (outSize > 0)
++	{
++	    xmlSecAssert2(xmlSecBufferGetData(&(transform->outBuf)), -1);
++
++	    memcpy(data, xmlSecBufferGetData(&(transform->outBuf)), outSize);
++	    ret = xmlSecBufferRemoveHead(&(transform->outBuf), outSize);
++            if (ret < 0)
++	    {
++		xmlSecError(XMLSEC_ERRORS_HERE,
++			    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++			    "xmlSecBufferRemoveHead",
++			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
++			    "size=%d", outSize);
++		return(-1);
++	    }
++	}
++	else if (xmlSecBufferGetSize(out) == 0)
++	    transform->status = xmlSecTransformStatusFinished;
++	(*dataSize) = outSize;
++    }
++    else if (transform->status == xmlSecTransformStatusFinished)
++    {
++	/* the only way we can get here is if there is no output */
++	xmlSecAssert2(xmlSecBufferGetSize(out) == 0, -1);
++	(*dataSize) = 0;
++    }
++    else
++    {
++	xmlSecError(XMLSEC_ERRORS_HERE,
++		    xmlSecErrorsSafeString(xmlSecTransformGetName(transform)),
++		    NULL,
++		    XMLSEC_ERRORS_R_INVALID_STATUS,
++		    "status=%d", transform->status);
++	return(-1);
++    }
++
++    return(0);
 +}
 -- 
 2.6.2
commit 0dac6d1f179c286dd7aea2d9ef7c37db8323fa37
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Jan 25 15:34:38 2016 +0100

    xmlsecurity: implement OOXML stream references
    
    With this, if see an URI like:
    
    /_rels/.rels?ContentType=application/vnd.openxmlformats-package.relationships+xml
    
    Then it is properly detected that it's the .rels stream of the _rels
    storage, and UriBindingHelper will serve that stream (when looked up by
    name later) to libxmlsec.
    
    Change-Id: Iac62cb170c0aa8bb92c40311fb7b248e96c25dde

diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx
index 4bc7274..4c930d1 100644
--- a/xmlsecurity/source/helper/ooxmlsecparser.cxx
+++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx
@@ -19,6 +19,7 @@ OOXMLSecParser::OOXMLSecParser(XSecController* pXSecController)
     ,m_bInX509Certificate(false)
     ,m_bInMdssiValue(false)
     ,m_bInSignatureComments(false)
+    ,m_bReferenceUnresolved(false)
 {
 }
 
@@ -56,7 +57,23 @@ throw (xml::sax::SAXException, uno::RuntimeException, std::exception)
         OUString aURI = xAttribs->getValueByName("URI");
         if (aURI.startsWith("#"))
             m_pXSecController->addReference(aURI.copy(1));
-        // TODO else
+        else
+        {
+            m_aReferenceURI = aURI;
+            m_bReferenceUnresolved = true;
+        }
+    }
+    else if (rName == "Transform")
+    {
+        if (m_bReferenceUnresolved)
+        {
+            OUString aAlgorithm = xAttribs->getValueByName("Algorithm");
+            if (aAlgorithm == ALGO_RELATIONSHIP)
+            {
+                m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/false);
+                m_bReferenceUnresolved = false;
+            }
+        }
     }
     else if (rName == "DigestValue")
     {
@@ -93,7 +110,15 @@ void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) throw (xml::sax:
     if (rName == "SignedInfo")
         m_pXSecController->setReferenceCount();
     else if (rName == "Reference")
+    {
+        if (m_bReferenceUnresolved)
+        {
+            // No transform algorithm found, assume binary.
+            m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/true);
+            m_bReferenceUnresolved = false;
+        }
         m_pXSecController->setDigestValue(m_aDigestValue);
+    }
     else if (rName == "DigestValue")
         m_bInDigestValue = false;
     else if (rName == "SignatureValue")
diff --git a/xmlsecurity/source/helper/ooxmlsecparser.hxx b/xmlsecurity/source/helper/ooxmlsecparser.hxx
index c7ac953..73ac0b2 100644
--- a/xmlsecurity/source/helper/ooxmlsecparser.hxx
+++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx
@@ -39,6 +39,10 @@ class OOXMLSecParser: public cppu::WeakImplHelper
     OUString m_aMdssiValue;
     bool m_bInSignatureComments;
     OUString m_aSignatureComments;
+    /// Last seen <Reference URI="...">.
+    OUString m_aReferenceURI;
+    /// Already called addStreamReference() for this reference.
+    bool m_bReferenceUnresolved;
 
 public:
     OOXMLSecParser(XSecController* pXSecController);
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper2.cxx b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx
index 40407d5..89f6bbc 100644
--- a/xmlsecurity/source/helper/xmlsignaturehelper2.cxx
+++ b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx
@@ -184,14 +184,19 @@ uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno
     OSL_ASSERT(!rURI.isEmpty());
     uno::Reference < io::XInputStream > xInStream;
 
-    sal_Int32 nSepPos = rURI.indexOf( '/' );
+    OUString aURI(rURI);
+    // Ignore leading slash, don't attempt to open a storage with name "".
+    if (aURI.startsWith("/"))
+        aURI = aURI.copy(1);
+
+    sal_Int32 nSepPos = aURI.indexOf( '/' );
     if ( nSepPos == -1 )
     {
         // Cloning because of I can't keep all storage references open
         // MBA with think about a better API...
         const OUString sName = ::rtl::Uri::decode(
-            rURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment);
-        if (sName.isEmpty() && !rURI.isEmpty())
+            aURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment);
+        if (sName.isEmpty() && !aURI.isEmpty())
             throw uno::Exception("Could not decode URI for stream element.", nullptr);
 
         uno::Reference< io::XStream > xStream;
@@ -202,12 +207,17 @@ uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno
     }
     else
     {
+        // Ignore query part of the URI.
+        sal_Int32 nQueryPos = aURI.indexOf('?');
+        if (nQueryPos != -1)
+            aURI = aURI.copy(0, nQueryPos);
+
         const OUString aStoreName = ::rtl::Uri::decode(
-            rURI.copy( 0, nSepPos ), rtl_UriDecodeStrict, rtl_UriCharClassRelSegment);
-        if (aStoreName.isEmpty() && !rURI.isEmpty())
+            aURI.copy( 0, nSepPos ), rtl_UriDecodeStrict, rtl_UriCharClassRelSegment);
+        if (aStoreName.isEmpty() && !aURI.isEmpty())
             throw uno::Exception("Could not decode URI for stream element.", nullptr);
 
-        OUString aElement = rURI.copy( nSepPos+1 );
+        OUString aElement = aURI.copy( nSepPos+1 );
         uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ );
         xInStream = OpenInputStream( xSubStore, aElement );
     }
diff --git a/xmlsecurity/source/helper/xsecctl.hxx b/xmlsecurity/source/helper/xsecctl.hxx
index b48b8cd..769e6b2 100644
--- a/xmlsecurity/source/helper/xsecctl.hxx
+++ b/xmlsecurity/source/helper/xsecctl.hxx
@@ -96,6 +96,7 @@
 #define ALGO_C14N           "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
 #define ALGO_RSASHA1            "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
 #define ALGO_XMLDSIGSHA1        "http://www.w3.org/2000/09/xmldsig#sha1"
+#define ALGO_RELATIONSHIP "http://schemas.openxmlformats.org/package/2006/RelationshipTransform"
 
 #define CHAR_FRAGMENT           "#"
 #define CHAR_BLANK          " "


More information about the Libreoffice-commits mailing list