summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Thode <prometheanfire@gentoo.org>2013-02-20 05:42:51 +0000
committerMatthew Thode <prometheanfire@gentoo.org>2013-02-20 05:42:51 +0000
commitdbebcc017db485f62afe2c42aa08e697ed850886 (patch)
treec01bbe384f5bf30655ae4ff6d2599957546c4f6e /sys-cluster/nova
parentreadding boto-2.1.1 as sys-cluster/nova requires it (diff)
downloadgentoo-2-dbebcc017db485f62afe2c42aa08e697ed850886.tar.gz
gentoo-2-dbebcc017db485f62afe2c42aa08e697ed850886.tar.bz2
gentoo-2-dbebcc017db485f62afe2c42aa08e697ed850886.zip
updating nova and addressing CVE-2013-1664 from bug 458330
(Portage version: 2.1.11.50/cvs/Linux x86_64, signed Manifest commit with key 0x2471eb3e40ac5ac3)
Diffstat (limited to 'sys-cluster/nova')
-rw-r--r--sys-cluster/nova/ChangeLog10
-rw-r--r--sys-cluster/nova/files/nova-folsom-CVE-2013-1664.patch396
-rw-r--r--sys-cluster/nova/nova-2012.2.2-r1.ebuild (renamed from sys-cluster/nova/nova-2012.2.2.ebuild)6
-rw-r--r--sys-cluster/nova/nova-2012.2.3.ebuild65
4 files changed, 475 insertions, 2 deletions
diff --git a/sys-cluster/nova/ChangeLog b/sys-cluster/nova/ChangeLog
index 5e0c6eccb200..7e48114363ce 100644
--- a/sys-cluster/nova/ChangeLog
+++ b/sys-cluster/nova/ChangeLog
@@ -1,6 +1,14 @@
# ChangeLog for sys-cluster/nova
# Copyright 1999-2013 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/ChangeLog,v 1.1 2013/01/26 09:18:28 prometheanfire Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/ChangeLog,v 1.2 2013/02/20 05:42:51 prometheanfire Exp $
+
+*nova-2012.2.3 (20 Feb 2013)
+*nova-2012.2.2-r1 (20 Feb 2013)
+
+ 20 Feb 2013; Matthew Thode <prometheanfire@gentoo.org> -nova-2012.2.2.ebuild,
+ +nova-2012.2.2-r1.ebuild, +nova-2012.2.3.ebuild,
+ +files/nova-folsom-CVE-2013-1664.patch:
+ updating nova and addressing CVE-2013-1664 from bug 458330
*nova-2012.2.2 (26 Jan 2013)
diff --git a/sys-cluster/nova/files/nova-folsom-CVE-2013-1664.patch b/sys-cluster/nova/files/nova-folsom-CVE-2013-1664.patch
new file mode 100644
index 000000000000..9da049326d7a
--- /dev/null
+++ b/sys-cluster/nova/files/nova-folsom-CVE-2013-1664.patch
@@ -0,0 +1,396 @@
+From: Dan Prince <dprince@redhat.com>
+Date: Sat, 2 Feb 2013 16:34:25 +0000 (-0500)
+Subject: Add a safe_minidom_parse_string function.
+X-Git-Url: https://review.openstack.org/gitweb?p=openstack%2Fnova.git;a=commitdiff_plain;h=2ae74f8222058e475350458ca0c820adb910582c
+
+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 for Folsom.
+
+Change-Id: I6a4051b5e66f3ce5a330b2589c42e6e9e5b9268e
+---
+
+diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
+index ccc70cd..7fe3a50 100644
+--- a/nova/api/openstack/common.py
++++ b/nova/api/openstack/common.py
+@@ -21,7 +21,6 @@ import re
+ import urlparse
+
+ import webob
+-from xml.dom import minidom
+
+ from nova.api.openstack import wsgi
+ from nova.api.openstack import xmlutil
+@@ -32,6 +31,7 @@ from nova import exception
+ from nova import flags
+ from nova.openstack.common import log as logging
+ from nova import quota
++from nova import utils
+
+
+ LOG = logging.getLogger(__name__)
+@@ -341,7 +341,7 @@ def raise_http_conflict_for_instance_invalid_state(exc, action):
+
+ class MetadataDeserializer(wsgi.MetadataXMLDeserializer):
+ def deserialize(self, text):
+- dom = minidom.parseString(text)
++ dom = utils.safe_minidom_parse_string(text)
+ metadata_node = self.find_first_child_named(dom, "metadata")
+ metadata = self.extract_metadata(metadata_node)
+ return {'body': {'metadata': metadata}}
+@@ -349,7 +349,7 @@ class MetadataDeserializer(wsgi.MetadataXMLDeserializer):
+
+ class MetaItemDeserializer(wsgi.MetadataXMLDeserializer):
+ def deserialize(self, text):
+- dom = minidom.parseString(text)
++ dom = utils.safe_minidom_parse_string(text)
+ metadata_item = self.extract_metadata(dom)
+ return {'body': {'meta': metadata_item}}
+
+@@ -367,7 +367,7 @@ class MetadataXMLDeserializer(wsgi.XMLDeserializer):
+ return metadata
+
+ def _extract_metadata_container(self, datastring):
+- dom = minidom.parseString(datastring)
++ dom = utils.safe_minidom_parse_string(datastring)
+ metadata_node = self.find_first_child_named(dom, "metadata")
+ metadata = self.extract_metadata(metadata_node)
+ return {'body': {'metadata': metadata}}
+@@ -379,7 +379,7 @@ class MetadataXMLDeserializer(wsgi.XMLDeserializer):
+ return self._extract_metadata_container(datastring)
+
+ def update(self, datastring):
+- dom = minidom.parseString(datastring)
++ dom = utils.safe_minidom_parse_string(datastring)
+ metadata_item = self.extract_metadata(dom)
+ return {'body': {'meta': metadata_item}}
+
+diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py
+index 95a80f3..fa3c961 100644
+--- a/nova/api/openstack/compute/contrib/hosts.py
++++ b/nova/api/openstack/compute/contrib/hosts.py
+@@ -16,7 +16,6 @@
+ """The hosts admin extension."""
+
+ import webob.exc
+-from xml.dom import minidom
+ from xml.parsers import expat
+
+ from nova.api.openstack import extensions
+@@ -27,6 +26,7 @@ from nova import db
+ from nova import exception
+ from nova import flags
+ from nova.openstack.common import log as logging
++from nova import utils
+
+
+ LOG = logging.getLogger(__name__)
+@@ -80,7 +80,7 @@ class HostShowTemplate(xmlutil.TemplateBuilder):
+ class HostDeserializer(wsgi.XMLDeserializer):
+ def default(self, string):
+ try:
+- node = minidom.parseString(string)
++ node = utils.safe_minidom_parse_string(string)
+ except expat.ExpatError:
+ msg = _("cannot understand XML")
+ raise exception.MalformedRequestBody(reason=msg)
+diff --git a/nova/api/openstack/compute/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py
+index e5b1797..4a6be1e 100644
+--- a/nova/api/openstack/compute/contrib/security_groups.py
++++ b/nova/api/openstack/compute/contrib/security_groups.py
+@@ -16,8 +16,6 @@
+
+ """The security groups extension."""
+
+-from xml.dom import minidom
+-
+ import webob
+ from webob import exc
+
+@@ -30,6 +28,7 @@ from nova import db
+ from nova import exception
+ from nova import flags
+ from nova.openstack.common import log as logging
++from nova import utils
+
+
+ LOG = logging.getLogger(__name__)
+@@ -110,7 +109,7 @@ class SecurityGroupXMLDeserializer(wsgi.MetadataXMLDeserializer):
+ """
+ def default(self, string):
+ """Deserialize an xml-formatted security group create request"""
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ security_group = {}
+ sg_node = self.find_first_child_named(dom,
+ 'security_group')
+@@ -131,7 +130,7 @@ class SecurityGroupRulesXMLDeserializer(wsgi.MetadataXMLDeserializer):
+
+ def default(self, string):
+ """Deserialize an xml-formatted security group create request"""
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ security_group_rule = self._extract_security_group_rule(dom)
+ return {'body': {'security_group_rule': security_group_rule}}
+
+diff --git a/nova/api/openstack/compute/contrib/volumes.py b/nova/api/openstack/compute/contrib/volumes.py
+index 9940e30..9f1fa62 100644
+--- a/nova/api/openstack/compute/contrib/volumes.py
++++ b/nova/api/openstack/compute/contrib/volumes.py
+@@ -17,7 +17,6 @@
+
+ import webob
+ from webob import exc
+-from xml.dom import minidom
+
+ from nova.api.openstack import common
+ from nova.api.openstack import extensions
+@@ -155,7 +154,7 @@ class CreateDeserializer(CommonDeserializer):
+
+ def default(self, string):
+ """Deserialize an xml-formatted volume create request."""
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ volume = self._extract_volume(dom)
+ return {'body': {'volume': volume}}
+
+diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
+index 3a14b4f..a093266 100644
+--- a/nova/api/openstack/compute/servers.py
++++ b/nova/api/openstack/compute/servers.py
+@@ -21,7 +21,6 @@ import socket
+
+ import webob
+ from webob import exc
+-from xml.dom import minidom
+
+ from nova.api.openstack import common
+ from nova.api.openstack.compute import ips
+@@ -297,7 +296,7 @@ class ActionDeserializer(CommonDeserializer):
+ """
+
+ def default(self, string):
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ action_node = dom.childNodes[0]
+ action_name = action_node.tagName
+
+@@ -404,7 +403,7 @@ class CreateDeserializer(CommonDeserializer):
+
+ def default(self, string):
+ """Deserialize an xml-formatted server create request."""
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ server = self._extract_server(dom)
+ return {'body': {'server': server}}
+
+diff --git a/nova/api/openstack/volume/contrib/volume_actions.py b/nova/api/openstack/volume/contrib/volume_actions.py
+index 8a453bf..7e47065 100644
+--- a/nova/api/openstack/volume/contrib/volume_actions.py
++++ b/nova/api/openstack/volume/contrib/volume_actions.py
+@@ -13,7 +13,6 @@
+ # under the License.
+
+ import webob
+-from xml.dom import minidom
+
+ from nova.api.openstack import extensions
+ from nova.api.openstack import wsgi
+@@ -22,6 +21,7 @@ from nova import exception
+ from nova import flags
+ from nova.openstack.common import log as logging
+ from nova.openstack.common.rpc import common as rpc_common
++from nova import utils
+ from nova import volume
+
+
+@@ -54,7 +54,7 @@ class VolumeToImageSerializer(xmlutil.TemplateBuilder):
+ class VolumeToImageDeserializer(wsgi.XMLDeserializer):
+ """Deserializer to handle xml-formatted requests"""
+ def default(self, string):
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ action_node = dom.childNodes[0]
+ action_name = action_node.tagName
+
+diff --git a/nova/api/openstack/volume/volumes.py b/nova/api/openstack/volume/volumes.py
+index 6cc4af8..ef33f92 100644
+--- a/nova/api/openstack/volume/volumes.py
++++ b/nova/api/openstack/volume/volumes.py
+@@ -17,7 +17,6 @@
+
+ import webob
+ from webob import exc
+-from xml.dom import minidom
+
+ from nova.api.openstack import common
+ from nova.api.openstack import wsgi
+@@ -191,7 +190,7 @@ class CreateDeserializer(CommonDeserializer):
+
+ def default(self, string):
+ """Deserialize an xml-formatted volume create request."""
+- dom = minidom.parseString(string)
++ dom = utils.safe_minidom_parse_string(string)
+ volume = self._extract_volume(dom)
+ return {'body': {'volume': volume}}
+
+diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
+index 1ff7745..6ab4f63 100644
+--- a/nova/api/openstack/wsgi.py
++++ b/nova/api/openstack/wsgi.py
+@@ -27,6 +27,7 @@ import webob
+ from nova import exception
+ from nova.openstack.common import jsonutils
+ from nova.openstack.common import log as logging
++from nova import utils
+ from nova import wsgi
+
+
+@@ -217,7 +218,7 @@ class XMLDeserializer(TextDeserializer):
+ plurals = set(self.metadata.get('plurals', {}))
+
+ try:
+- node = minidom.parseString(datastring).childNodes[0]
++ node = utils.safe_minidom_parse_string(datastring).childNodes[0]
+ return {node.nodeName: self._from_xml_node(node, plurals)}
+ except expat.ExpatError:
+ msg = _("cannot understand XML")
+@@ -268,11 +269,11 @@ class XMLDeserializer(TextDeserializer):
+
+ def extract_text(self, node):
+ """Get the text field contained by the given node"""
+- if len(node.childNodes) == 1:
+- child = node.childNodes[0]
++ ret_val = ""
++ for child in node.childNodes:
+ if child.nodeType == child.TEXT_NODE:
+- return child.nodeValue
+- return ""
++ ret_val += child.nodeValue
++ return ret_val
+
+ def extract_elements(self, node):
+ """Get only Element type childs from node"""
+@@ -631,7 +632,7 @@ def action_peek_json(body):
+ def action_peek_xml(body):
+ """Determine action to invoke."""
+
+- dom = minidom.parseString(body)
++ dom = utils.safe_minidom_parse_string(body)
+ action_node = dom.childNodes[0]
+
+ return action_node.tagName
+diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
+index adc62d8..46e4f14 100644
+--- a/nova/tests/test_utils.py
++++ b/nova/tests/test_utils.py
+@@ -457,6 +457,39 @@ class GenericUtilsTestCase(test.TestCase):
+ result = utils.service_is_up(service)
+ self.assertFalse(result)
+
++ def test_safe_parse_xml(self):
++
++ normal_body = ("""
++ <?xml version="1.0" ?><foo>
++ <bar>
++ <v1>hey</v1>
++ <v2>there</v2>
++ </bar>
++ </foo>""").strip()
++
++ def killer_body():
++ return (("""<!DOCTYPE x [
++ <!ENTITY a "%(a)s">
++ <!ENTITY b "%(b)s">
++ <!ENTITY c "%(c)s">]>
++ <foo>
++ <bar>
++ <v1>%(d)s</v1>
++ </bar>
++ </foo>""") % {
++ 'a': 'A' * 10,
++ 'b': '&a;' * 10,
++ 'c': '&b;' * 10,
++ 'd': '&c;' * 9999,
++ }).strip()
++
++ dom = utils.safe_minidom_parse_string(normal_body)
++ self.assertEqual(normal_body, str(dom.toxml()))
++
++ self.assertRaises(ValueError,
++ utils.safe_minidom_parse_string,
++ killer_body())
++
+ def test_xhtml_escape(self):
+ self.assertEqual('&quot;foo&quot;', utils.xhtml_escape('"foo"'))
+ self.assertEqual('&apos;foo&apos;', utils.xhtml_escape("'foo'"))
+diff --git a/nova/utils.py b/nova/utils.py
+index 5722cf5..4a605cb 100644
+--- a/nova/utils.py
++++ b/nova/utils.py
+@@ -39,6 +39,10 @@ import tempfile
+ import time
+ import uuid
+ import weakref
++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
+@@ -567,6 +571,46 @@ class LoopingCall(object):
+ return self.done.wait()
+
+
++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.
diff --git a/sys-cluster/nova/nova-2012.2.2.ebuild b/sys-cluster/nova/nova-2012.2.2-r1.ebuild
index dd20969839c7..36f854797c5b 100644
--- a/sys-cluster/nova/nova-2012.2.2.ebuild
+++ b/sys-cluster/nova/nova-2012.2.2-r1.ebuild
@@ -1,6 +1,6 @@
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2012.2.2.ebuild,v 1.1 2013/01/26 09:18:28 prometheanfire Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2012.2.2-r1.ebuild,v 1.1 2013/02/20 05:42:51 prometheanfire Exp $
EAPI=5
PYTHON_COMPAT=( python2_5 python2_6 python2_7 )
@@ -43,6 +43,10 @@ RDEPEND="=dev-python/amqplib-0.6.1
<dev-python/python-glanceclient-2
>=dev-python/python-quantumclient-2.1"
+src_prepare() {
+ epatch "${FILESDIR}/nova-folsom-3-CVE-2013-1664.patch"
+}
+
python_install() {
distutils-r1_python_install
keepdir /etc/nova
diff --git a/sys-cluster/nova/nova-2012.2.3.ebuild b/sys-cluster/nova/nova-2012.2.3.ebuild
new file mode 100644
index 000000000000..4d1820832eeb
--- /dev/null
+++ b/sys-cluster/nova/nova-2012.2.3.ebuild
@@ -0,0 +1,65 @@
+# Copyright 1999-2013 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/nova-2012.2.3.ebuild,v 1.1 2013/02/20 05:42:51 prometheanfire Exp $
+
+EAPI=5
+PYTHON_COMPAT=( python2_5 python2_6 python2_7 )
+
+inherit distutils-r1 eutils
+
+DESCRIPTION="Nova is a cloud computing fabric controller (main part of an
+IaaS system). It is written in Python."
+HOMEPAGE="https://launchpad.net/nova"
+SRC_URI="http://launchpad.net/${PN}/folsom/${PV}/+download/${P}.tar.gz"
+
+LICENSE="Apache-2.0"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]"
+
+RDEPEND="=dev-python/amqplib-0.6.1
+ >=dev-python/anyjson-0.2.4
+ >=dev-python/sqlalchemy-0.7.8
+ <=dev-python/sqlalchemy-0.7.9
+ =dev-python/boto-2.1.1
+ >=dev-python/eventlet-0.9.17
+ =dev-python/kombu-1.0.4
+ =dev-python/routes-1.12.3
+ =dev-python/webob-1.0.8
+ >=dev-python/greenlet-0.3.1
+ =dev-python/pastedeploy-1.5.0
+ dev-python/paste
+ >=dev-python/sqlalchemy-migrate-0.7.2
+ dev-python/netaddr
+ =dev-python/suds-0.4
+ dev-python/paramiko
+ >=dev-python/Babel-0.9.6
+ >=dev-python/iso8601-0.1.4
+ dev-python/httplib2
+ >=dev-python/setuptools-git-0.4
+ >=dev-python/python-glanceclient-0.5.0
+ <dev-python/python-glanceclient-2
+ >=dev-python/python-quantumclient-2.1"
+
+src_prepare() {
+ epatch "${FILESDIR}/nova-folsom-3-CVE-2013-1664.patch"
+}
+
+python_install() {
+ distutils-r1_python_install
+ keepdir /etc/nova
+ insinto /etc/nova
+
+ newins "etc/nova/nova.conf.sample" "nova.conf"
+ newins "etc/nova/api-paste.ini" "api-paste.ini"
+ newins "etc/nova/logging_sample.conf" "logging_sample.conf"
+ newins "etc/nova/policy.json" "policy.json"
+ newins "etc/nova/rootwrap.conf" "rootwrap.conf"
+ insinto /etc/nova/rootwrap.d
+ doins "etc/nova/rootwrap.d/api-metadata.filters"
+ doins "etc/nova/rootwrap.d/compute.filters"
+ doins "etc/nova/rootwrap.d/network.filters"
+ doins "etc/nova/rootwrap.d/volume.filters"
+}