summaryrefslogtreecommitdiffstats
path: root/nova/utils.py
diff options
context:
space:
mode:
authorDan Prince <dprince@redhat.com>2013-02-01 17:04:27 -0500
committerDan Prince <dprince@redhat.com>2013-02-19 09:12:01 -0500
commit59933249054bf71ec963585198583fe78050c9d6 (patch)
treeebc4eb8b5f6cef1b3452a47985acaa480e40efc8 /nova/utils.py
parent1b9b66ba210c1dd886a95d79e5621e13fb64aa3a (diff)
downloadnova-59933249054bf71ec963585198583fe78050c9d6.tar.gz
nova-59933249054bf71ec963585198583fe78050c9d6.tar.xz
nova-59933249054bf71ec963585198583fe78050c9d6.zip
Add a safe_minidom_parse_string function.
Adds a new utils.safe_minidom_parse_string function and updates external API facing Nova modules to use it. This ensures we have safe defaults on our incoming API XML parsing. Internally safe_minidom_parse_string uses a ProtectedExpatParser class to disable DTDs and entities from being parsed when using minidom. Fixes LP Bug #1100282. Change-Id: Ib90d6379320ff1d007f8a661f7ddaa286ba6918e
Diffstat (limited to 'nova/utils.py')
-rw-r--r--nova/utils.py44
1 files changed, 44 insertions, 0 deletions
diff --git a/nova/utils.py b/nova/utils.py
index 126e3c7e4..ac658cd5e 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -36,6 +36,10 @@ import struct
import sys
import tempfile
import time
+from xml.dom import minidom
+from xml.parsers import expat
+from xml import sax
+from xml.sax import expatreader
from xml.sax import saxutils
from eventlet import event
@@ -652,6 +656,46 @@ class DynamicLoopingCall(LoopingCallBase):
return self.done
+class ProtectedExpatParser(expatreader.ExpatParser):
+ """An expat parser which disables DTD's and entities by default."""
+
+ def __init__(self, forbid_dtd=True, forbid_entities=True,
+ *args, **kwargs):
+ # Python 2.x old style class
+ expatreader.ExpatParser.__init__(self, *args, **kwargs)
+ self.forbid_dtd = forbid_dtd
+ self.forbid_entities = forbid_entities
+
+ def start_doctype_decl(self, name, sysid, pubid, has_internal_subset):
+ raise ValueError("Inline DTD forbidden")
+
+ def entity_decl(self, entityName, is_parameter_entity, value, base,
+ systemId, publicId, notationName):
+ raise ValueError("<!ENTITY> forbidden")
+
+ def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):
+ # expat 1.2
+ raise ValueError("<!ENTITY> forbidden")
+
+ def reset(self):
+ expatreader.ExpatParser.reset(self)
+ if self.forbid_dtd:
+ self._parser.StartDoctypeDeclHandler = self.start_doctype_decl
+ if self.forbid_entities:
+ self._parser.EntityDeclHandler = self.entity_decl
+ self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl
+
+
+def safe_minidom_parse_string(xml_string):
+ """Parse an XML string using minidom safely.
+
+ """
+ try:
+ return minidom.parseString(xml_string, parser=ProtectedExpatParser())
+ except sax.SAXParseException as se:
+ raise expat.ExpatError()
+
+
def xhtml_escape(value):
"""Escapes a string so it is valid within XML or XHTML.