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();