components/openstack/nova/patches/07-CVE-2014-3517.patch
branchs11u2-sru
changeset 3326 030508e3f1bd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/nova/patches/07-CVE-2014-3517.patch	Tue Sep 23 17:12:33 2014 -0700
@@ -0,0 +1,91 @@
+This upstream patch addresses CVE-2014-3517 and is tracked under
+Launchpad bug 1325128. It is addressed in the Juno trunk, Icehouse
+2014.1.2, and Havana 2013.2.4. It has been modified to apply cleanly
+into our current Havana implementation
+
+commit 1dd97d1335f6ec028d0e4440250f80802a2f1d18
+Author: Grant Murphy <[email protected]>
+Date:   Tue Jul 8 03:35:40 2014 +0000
+
+    Avoid possible timing attack in metadata api
+    
+    Introduce a constant time comparison function to
+    nova utils for comparing authentication tokens.
+    
+    Conflicts:
+    	nova/tests/test_utils.py
+    	nova/utils.py
+    
+    Closes-bug: #1325128
+    Change-Id: I7374f2edc6f03c7da59cf73ae91a87147e53d0de
+    (cherry picked from commit 9f59ca751f1a392ef24d8ab73a7bf5ce9655017e)
+
+diff --git a/nova/api/metadata/handler.py b/nova/api/metadata/handler.py
+index 50387ab..74bb4f7 100644
+--- a/nova/api/metadata/handler.py
++++ b/nova/api/metadata/handler.py
+@@ -31,6 +31,7 @@ from nova import exception
+ from nova.openstack.common.gettextutils import _
+ from nova.openstack.common import log as logging
+ from nova.openstack.common import memorycache
++from nova import utils
+ from nova import wsgi
+ 
+ CACHE_EXPIRATION = 15  # in seconds
+@@ -172,7 +173,7 @@ class MetadataRequestHandler(wsgi.Application):
+             instance_id,
+             hashlib.sha256).hexdigest()
+ 
+-        if expected_signature != signature:
++        if not utils.constant_time_compare(expected_signature, signature):
+             if instance_id:
+                 LOG.warn(_('X-Instance-ID-Signature: %(signature)s does not '
+                            'match the expected value: %(expected_signature)s '
+diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
+index b38ea50..820fe09 100644
+--- a/nova/tests/test_utils.py
++++ b/nova/tests/test_utils.py
+@@ -1083,3 +1083,10 @@ class GetImageFromSystemMetadataTestCase(test.NoDBTestCase):
+ 
+         # Verify that the foo1 key has not been inherited
+         self.assertTrue("foo1" not in image)
++
++
++class ConstantTimeCompareTestCase(test.NoDBTestCase):
++    def test_constant_time_compare(self):
++        self.assertTrue(utils.constant_time_compare("abcd1234", "abcd1234"))
++        self.assertFalse(utils.constant_time_compare("abcd1234", "a"))
++        self.assertFalse(utils.constant_time_compare("abcd1234", "ABCD234"))
+diff --git a/nova/utils.py b/nova/utils.py
+index 4757f3a..5f10a8a 100755
+--- nova-2013.2.3/nova/utils.py.~2~	2014-09-02 13:57:46.030039835 -0700
++++ nova-2013.2.3/nova/utils.py	2014-09-02 13:57:49.391998275 -0700
+@@ -23,6 +23,7 @@ import contextlib
+ import datetime
+ import functools
+ import hashlib
++import hmac
+ import inspect
+ import os
+ import pyclbr
+@@ -1288,3 +1289,20 @@ def get_boolean(value):
+         return value
+     else:
+         return strutils.bool_from_string(value)
++
++if hasattr(hmac, 'compare_digest'):
++    constant_time_compare = hmac.compare_digest
++else:
++    def constant_time_compare(first, second):
++        """Returns True if both string inputs are equal, otherwise False.
++
++        This function should take a constant amount of time regardless of
++        how many characters in the strings match.
++
++        """
++        if len(first) != len(second):
++            return False
++        result = 0
++        for x, y in zip(first, second):
++            result |= ord(x) ^ ord(y)
++        return result == 0