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 <vmik...@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 <vmik...@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 <vmik...@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 " " _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits