Tagging 1.7.1 release.

git-svn-id: https://svn.apache.org/repos/asf/santuario/xml-security-cpp/tags/1.7.1@1493963 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 5bb30c6..8fc01ec 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,8 @@
+Changes since 1.7.0
+=====================================
+* Fixes for CVE-2013-2153, CVE-2013-2154, CVE-2013-2155, CVE-2013-2156
+* Reduced entity expansion limits when parsing
+
 Changes since 1.6.1
 =====================================
 * [SANTUARIO-314] - AES-GCM support
diff --git a/configure.ac b/configure.ac
index 2b42af7..674b04a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
 
 # Process this file with autoreconf
 AC_PREREQ(2.50)
-AC_INIT([[XML-Security-C]],[1.7.1],[santuario-dev@apache.org],[xml-security-c])
+AC_INIT([[XML-Security-C]],[1.7.1],[dev@santuario.apache.org],[xml-security-c])
 AC_CONFIG_SRCDIR(xsec)
 AC_CONFIG_AUX_DIR(build-aux)
 AC_CONFIG_MACRO_DIR(m4)
diff --git a/xsec/Makefile.am b/xsec/Makefile.am
index 7ce67f8..0396c5c 100644
--- a/xsec/Makefile.am
+++ b/xsec/Makefile.am
@@ -16,7 +16,7 @@
 
 AUTOMAKE_OPTIONS = foreign
 
-INCLUDES = -I..
+AM_CPPFLAGS = -I..
 
 noinst_PROGRAMS = ${samples}
 bin_PROGRAMS = ${tools}
diff --git a/xsec/canon/XSECC14n20010315.cpp b/xsec/canon/XSECC14n20010315.cpp
index aff141e..fb9f60a 100644
--- a/xsec/canon/XSECC14n20010315.cpp
+++ b/xsec/canon/XSECC14n20010315.cpp
@@ -240,6 +240,8 @@
 
 	}
 
+	ArrayJanitor<char> j_nsBuf(nsBuf);
+
 	int i, j;
 
 	i = 0;
@@ -247,21 +249,22 @@
 	while (xmlnsList[i] != '\0') {
 
 		while (xmlnsList[i] == ' ' ||
-			   xmlnsList[i] == '\0' ||
 			   xmlnsList[i] == '\t' ||
 			   xmlnsList[i] == '\r' ||
-			   xmlnsList[i] == '\n')
+			   xmlnsList[i] == '\n') {
 
 			   ++i;	// Skip white space
+		}
 
 		j = 0;
 		while (!(xmlnsList[i] == ' ' ||
 			   xmlnsList[i] == '\0' ||
 			   xmlnsList[i] == '\t' ||
 			   xmlnsList[i] == '\r' ||
-			   xmlnsList[i] == '\n'))
+			   xmlnsList[i] == '\n')) {
 
 			   nsBuf[j++] = xmlnsList[i++];	// Copy name
+		}
 
 		// Terminate the string
 		nsBuf[j] = '\0';
@@ -281,8 +284,6 @@
 
 	}
 
-	delete[] nsBuf;
-
 }
 
 
diff --git a/xsec/dsig/DSIGAlgorithmHandlerDefault.cpp b/xsec/dsig/DSIGAlgorithmHandlerDefault.cpp
index 14694ce..f938c3c 100644
--- a/xsec/dsig/DSIGAlgorithmHandlerDefault.cpp
+++ b/xsec/dsig/DSIGAlgorithmHandlerDefault.cpp
@@ -60,6 +60,15 @@
 	// Compare at most maxCompare bits (if maxCompare > 0)
 	// Note - whilst the other parameters are bytes, maxCompare is bits
 
+	// The div function below takes signed int, so make sure the value
+	// is safe to cast.
+	if ((int) maxCompare < 0) {
+
+		throw XSECException(XSECException::CryptoProviderError, 
+				"Comparison length was unsafe");
+
+	}
+
 	unsigned char outputStr[MAXB64BUFSIZE];
 	unsigned int outputLen = 0;
 	
@@ -126,7 +135,7 @@
 
 	char mask = 0x01;
 	if (maxCompare != 0) {
-	    for (j = 0 ; j < (unsigned int) d.rem; ++i) {
+	    for (j = 0 ; j < (unsigned int) d.rem; ++j) {
 
 		    if ((raw[i] & mask) != (outputStr[i] & mask))
 			    return false;
@@ -516,7 +525,7 @@
 		// Signature already created, so just translate to base 64 and enter string
 
         // FIX: CVE-2009-0217
-        if (outputLength > 0 && (outputLength < 80 || outputLength < hashLen / 2)) {
+        if (outputLength > 0 && (outputLength > hashLen || outputLength < 80 || outputLength < hashLen / 2)) {
             throw XSECException(XSECException::AlgorithmMapperError,
                 "HMACOutputLength set to unsafe value.");
         }
@@ -641,7 +650,7 @@
 		// Already done - just compare calculated value with read value
 
         // FIX: CVE-2009-0217
-        if (outputLength > 0 && (outputLength < 80 || outputLength < hashLen / 2)) {
+        if (outputLength > 0 && (outputLength > hashLen || outputLength < 80 || outputLength < hashLen / 2)) {
             throw XSECException(XSECException::AlgorithmMapperError,
                 "HMACOutputLength set to unsafe value.");
         }
diff --git a/xsec/dsig/DSIGReference.cpp b/xsec/dsig/DSIGReference.cpp
index b40b26d..71f6926 100644
--- a/xsec/dsig/DSIGReference.cpp
+++ b/xsec/dsig/DSIGReference.cpp
@@ -516,17 +516,15 @@
 		}
 
 		else if (URI[9] == XERCES_CPP_NAMESPACE_QUALIFIER chOpenParen &&
-			     URI[10] == XERCES_CPP_NAMESPACE_QUALIFIER chLatin_i &&
-				 URI[11] == XERCES_CPP_NAMESPACE_QUALIFIER chLatin_d &&
-				 URI[12] == XERCES_CPP_NAMESPACE_QUALIFIER chOpenParen &&
-				 URI[13] == XERCES_CPP_NAMESPACE_QUALIFIER chSingleQuote) {
+				URI[10] == XERCES_CPP_NAMESPACE_QUALIFIER chLatin_i &&
+				URI[11] == XERCES_CPP_NAMESPACE_QUALIFIER chLatin_d &&
+				URI[12] == XERCES_CPP_NAMESPACE_QUALIFIER chOpenParen &&
+				URI[13] == XERCES_CPP_NAMESPACE_QUALIFIER chSingleQuote) {
 
 			xsecsize_t len = XMLString::stringLen(&URI[14]);
 
-			XMLCh tmp[512];
-
-			if (len > 511)
-				len = 511;
+			XMLCh* tmp = new XMLCh[len + 1];
+			ArrayJanitor<XMLCh> j_tmp(tmp);
 
 			xsecsize_t j = 14, i = 0;
 
@@ -630,9 +628,14 @@
 	// Now check for Transforms
 	tmpElt = mp_referenceNode->getFirstChild();
 
-	while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE))
+	while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE)) {
+		if (tmpElt->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+				"EntityReference nodes in <Reference> are unsupported.");
+		}
 		// Skip text and comments
 		tmpElt = tmpElt->getNextSibling();
+	}
 
 	if (tmpElt == 0) {
 
@@ -651,13 +654,19 @@
 
 		// Find next node
 		tmpElt = tmpElt->getNextSibling();
-		while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE))
+		while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE)) {
+			if (tmpElt->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+					"EntityReference nodes in <Reference> are unsupported.");
+			}
 			tmpElt = tmpElt->getNextSibling();
+		}
 
 
 	} /* if tmpElt node type = transforms */
-	else
+	else {
 		mp_transformList = NULL;
+	}
 
 
 	if (tmpElt == NULL || !strEquals(getDSIGLocalName(tmpElt), "DigestMethod")) {
@@ -692,8 +701,14 @@
 
 	tmpElt = tmpElt->getNextSibling();
 
-	while (tmpElt != 0 && !(strEquals(getDSIGLocalName(tmpElt), "DigestValue")))
+	while (tmpElt != 0 &&
+		(tmpElt->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getDSIGLocalName(tmpElt), "DigestValue"))) {
+		if (tmpElt->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+				"EntityReference nodes in <Reference> are unsupported.");
+		}
 		tmpElt = tmpElt->getNextSibling();
+	}
 
 	if (tmpElt == 0) {
 
@@ -731,8 +746,13 @@
 
 			// Find Manifest child
 			manifestNode = manifestNode->getFirstChild();
-			while (manifestNode != 0 && manifestNode->getNodeType() != DOMNode::ELEMENT_NODE)
+			while (manifestNode != 0 && manifestNode->getNodeType() != DOMNode::ELEMENT_NODE) {
+				if (manifestNode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+					throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+						"EntityReference nodes in <Reference> are unsupported.");
+				}
 				manifestNode = manifestNode->getNextSibling();
+			}
 
 			if (manifestNode == 0 || !strEquals(getDSIGLocalName(manifestNode), "Manifest"))
 				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
@@ -743,8 +763,14 @@
 		// Now have the manifest node, find the first reference and load!
 		referenceNode = manifestNode->getFirstChild();
 
-		while (referenceNode != 0 && !strEquals(getDSIGLocalName(referenceNode), "Reference"))
+		while (referenceNode != 0 &&
+			(referenceNode->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getDSIGLocalName(referenceNode), "Reference"))) {
+			if (referenceNode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+					"EntityReference nodes in <Reference> are unsupported.");
+			}
 			referenceNode = referenceNode->getNextSibling();
+		}
 
 		if (referenceNode == 0)
 			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
@@ -797,8 +823,13 @@
 		// Find next element Node
 		tmpRef = tmpRef->getNextSibling();
 
-		while (tmpRef != 0 && tmpRef->getNodeType() != DOMNode::ELEMENT_NODE)
+		while (tmpRef != 0 && tmpRef->getNodeType() != DOMNode::ELEMENT_NODE) {
+			if (tmpRef->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+				throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+					"EntityReference nodes in <Reference> are unsupported.");
+			}
 			tmpRef = tmpRef->getNextSibling();
+		}
 
 	}
 
diff --git a/xsec/dsig/DSIGSignedInfo.cpp b/xsec/dsig/DSIGSignedInfo.cpp
index b2d95c6..7514b85 100644
--- a/xsec/dsig/DSIGSignedInfo.cpp
+++ b/xsec/dsig/DSIGSignedInfo.cpp
@@ -299,9 +299,14 @@
 
 	// Check for CanonicalizationMethod
 
-	while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE))
+	while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE)) {
+		if (tmpSI->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+				"EntityReference nodes in <SignedInfo> are unsupported.");
+		}
 		// Skip text and comments
 		tmpSI = tmpSI->getNextSibling();
+	}
 
 	if (tmpSI == 0 || !strEquals(getDSIGLocalName(tmpSI), "CanonicalizationMethod")) {
 
@@ -362,17 +367,23 @@
 
 	}
 
-	else
+	else {
 
 		throw XSECException(XSECException::UnknownCanonicalization);
+	}
 
 	// Now load the SignatureMethod
 
 	tmpSI = tmpSI->getNextSibling();
 
-	while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE))
+	while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE)) {
+		if (tmpSI->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+				"EntityReference nodes in <SignedInfo> are unsupported.");
+		}
 		// Skip text and comments
 		tmpSI = tmpSI->getNextSibling();
+	}
 
 	if (tmpSI == 0 || !strEquals(getDSIGLocalName(tmpSI), "SignatureMethod")) {
 
@@ -406,10 +417,14 @@
 	 * longer know at this point if this is an HMAC, we need to check. */
 
 	DOMNode *tmpSOV = tmpSI->getFirstChild();
-	while (tmpSOV != NULL && 
-		tmpSOV->getNodeType() != DOMNode::ELEMENT_NODE && 
-		!strEquals(getDSIGLocalName(tmpSOV), "HMACOutputLength"))
+	while (tmpSOV != NULL &&
+		(tmpSOV->getNodeType() != DOMNode::ELEMENT_NODE || !strEquals(getDSIGLocalName(tmpSOV), "HMACOutputLength"))) {
+		if (tmpSOV->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+				"EntityReference nodes in <SignedInfo> are unsupported.");
+		}
 		tmpSOV = tmpSOV->getNextSibling();
+	}
 
 	if (tmpSOV != NULL) {
 
@@ -433,9 +448,14 @@
 
 	// Run through the rest of the elements until done
 
-	while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE))
+	while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE)) {
+		if (tmpSI->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
+			throw XSECException(XSECException::ExpectedDSIGChildNotFound,
+				"EntityReference nodes in <SignedInfo> are unsupported.");
+		}
 		// Skip text and comments
 		tmpSI = tmpSI->getNextSibling();
+	}
 
 	if (tmpSI != NULL) {
 
diff --git a/xsec/framework/XSECDefs.hpp b/xsec/framework/XSECDefs.hpp
index 8bcece5..f45339e 100644
--- a/xsec/framework/XSECDefs.hpp
+++ b/xsec/framework/XSECDefs.hpp
@@ -69,6 +69,9 @@
     typedef unsigned int xsecsize_t;
 #endif
 
+// Pending API change, compile in a limit for Xerces SecurityManager entity expansion
+#define XSEC_ENTITY_EXPANSION_LIMIT 1000
+
 
 // --------------------------------------------------------------------------------
 //           Namespace Handling
diff --git a/xsec/transformers/TXFMParser.cpp b/xsec/transformers/TXFMParser.cpp
index 76d3ea3..f81eb5d 100644
--- a/xsec/transformers/TXFMParser.cpp
+++ b/xsec/transformers/TXFMParser.cpp
@@ -114,8 +114,11 @@
 	XercesDOMParser parser;
 
 	parser.setDoNamespaces(true);
-	parser.setCreateEntityReferenceNodes(true);
-	parser.setDoSchema(true);
+	parser.setLoadExternalDTD(false);
+
+	SecurityManager securityManager;
+	securityManager.setEntityExpansionLimit(XSEC_ENTITY_EXPANSION_LIMIT);
+	parser.setSecurityManager(&securityManager);
 
 	parser.parse(is);
     xsecsize_t errorCount = parser.getErrorCount();
diff --git a/xsec/transformers/TXFMXSL.cpp b/xsec/transformers/TXFMXSL.cpp
index 31fc7ff..65df488 100644
--- a/xsec/transformers/TXFMXSL.cpp
+++ b/xsec/transformers/TXFMXSL.cpp
@@ -187,8 +187,12 @@
 
 	parser->setDoNamespaces(true);
 	parser->setCreateEntityReferenceNodes(true);
+	parser->setLoadExternalDTD(false);
 	parser->setDoSchema(true);
 
+	SecurityManager securityManager;
+	parser->setSecurityManager(&securityManager);
+
 	// Create an input source
 
 	MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) txoh.buffer.rawBuffer(), txoh.offset, "XSECMem");
diff --git a/xsec/utils/XSECSOAPRequestorSimple.cpp b/xsec/utils/XSECSOAPRequestorSimple.cpp
index 32bb1de..ba18ebf 100644
--- a/xsec/utils/XSECSOAPRequestorSimple.cpp
+++ b/xsec/utils/XSECSOAPRequestorSimple.cpp
@@ -218,31 +218,31 @@
 
 DOMDocument * XSECSOAPRequestorSimple::parseAndUnwrap(const char * buf, unsigned int len) {
 
-	XercesDOMParser * parser = new XercesDOMParser;
-	Janitor<XercesDOMParser> j_parser(parser);
+	XercesDOMParser parser;
+	parser.setDoNamespaces(true);
+	parser.setLoadExternalDTD(false);
 
-	parser->setDoNamespaces(true);
-	parser->setCreateEntityReferenceNodes(true);
-	parser->setDoSchema(true);
+	SecurityManager securityManager;
+	securityManager.setEntityExpansionLimit(XSEC_ENTITY_EXPANSION_LIMIT);
+	parser.setSecurityManager(&securityManager);
 
 	// Create an input source
 
-	MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) buf, len, "XSECMem");
-	Janitor<MemBufInputSource> j_memIS(memIS);
+	MemBufInputSource memIS((const XMLByte*) buf, len, "XSECMem");
 
-	parser->parse(*memIS);
-    xsecsize_t errorCount = parser->getErrorCount();
+	parser.parse(memIS);
+	xsecsize_t errorCount = parser.getErrorCount();
     if (errorCount > 0)
 		throw XSECException(XSECException::HTTPURIInputStreamError,
 							"Error parsing response message");
 
 	if (m_envelopeType == ENVELOPE_NONE) {
 
-		return parser->adoptDocument();
+		return parser.adoptDocument();
 
 	}
 
-    DOMDocument * responseDoc = parser->getDocument();
+	DOMDocument * responseDoc = parser.getDocument();
 
 	// Must be a SOAP message of some kind - so lets remove the wrapper.
 	// First create a new document for the Response message
diff --git a/xsec/xenc/impl/XENCCipherImpl.cpp b/xsec/xenc/impl/XENCCipherImpl.cpp
index 8dde6aa..4fba68d 100644
--- a/xsec/xenc/impl/XENCCipherImpl.cpp
+++ b/xsec/xenc/impl/XENCCipherImpl.cpp
@@ -270,8 +270,9 @@
     sb.sbXMLChAppendCh(chCloseAngle);
 
     char* prefix = transcodeToUTF8(sb.rawXMLChBuffer());
-
     sbt = prefix;
+    XSEC_RELEASE_XMLCH(prefix);
+
     const char * crcb = content.rawCharBuffer();
     int offset = 0;
     if (crcb[0] == '<' && crcb[1] == '?') {
@@ -286,9 +287,6 @@
 
     sbt.sbStrcatIn(&crcb[offset]);
 
-    // Now transform the content to UTF-8
-    //sb.sbXMLChCat8(content.rawCharBuffer());
-
     // Terminate the string
     sb.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty);
     sb.sbXMLChAppendCh(chOpenAngle);
@@ -300,37 +298,24 @@
     sbt.sbStrcatIn(trailer);
     XSEC_RELEASE_XMLCH(trailer);
 
-    // Now we need to parse the document
-    XercesDOMParser* parser = NULL;
-    MemBufInputSource* memIS = NULL;
-    try {
-        parser = new XercesDOMParser;
+    // Create an input source
+    xsecsize_t bytes = XMLString::stringLen(sbt.rawCharBuffer());
+    MemBufInputSource memIS((const XMLByte*) sbt.rawBuffer(), bytes, "XSECMem");
 
-        parser->setDoNamespaces(true);
-        parser->setCreateEntityReferenceNodes(true);
-        parser->setDoSchema(false);
+    XercesDOMParser parser;
+    parser.setDoNamespaces(true);
+    parser.setLoadExternalDTD(false);
 
-        // Create an input source
-        xsecsize_t bytes = XMLString::stringLen(sbt.rawCharBuffer());
-        memIS = new MemBufInputSource((const XMLByte*) sbt.rawBuffer(), bytes, "XSECMem");
-    }
-    catch (...) {
-        delete memIS;
-        delete parser;
-        XSEC_RELEASE_XMLCH(prefix);
-        throw;
-    }
+    SecurityManager securityManager;
+    securityManager.setEntityExpansionLimit(XSEC_ENTITY_EXPANSION_LIMIT);
+    parser.setSecurityManager(&securityManager);
 
-    XSEC_RELEASE_XMLCH(prefix);
-    Janitor<XercesDOMParser> j_parser(parser);
-    Janitor<MemBufInputSource> j_memIS(memIS);
-
-    parser->parse(*memIS);
-    xsecsize_t errorCount = parser->getErrorCount();
+    parser.parse(memIS);
+    xsecsize_t errorCount = parser.getErrorCount();
     if (errorCount > 0)
         throw XSECException(XSECException::CipherError, "Errors occured during de-serialisation of decrypted element content");
 
-    DOMDocument * doc = parser->getDocument();
+    DOMDocument * doc = parser.getDocument();
 
     // Create a DocumentFragment to hold the children of the parsed doc element
     DOMDocument *ctxDocument = ctx->getOwnerDocument();