prometheanfire    14/07/17 07:06:48

  Added:                nova-2014.1.1-CVE-2014-3517.patch
  Log:
  fix for nova 2014.1.1 CVE-2014-3517, we good yo
  
  (Portage version: 2.2.8-r1/cvs/Linux x86_64, signed Manifest commit with key 
0x2471eb3e40ac5ac3)

Revision  Changes    Path
1.1                  sys-cluster/nova/files/nova-2014.1.1-CVE-2014-3517.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-cluster/nova/files/nova-2014.1.1-CVE-2014-3517.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-cluster/nova/files/nova-2014.1.1-CVE-2014-3517.patch?rev=1.1&content-type=text/plain

Index: nova-2014.1.1-CVE-2014-3517.patch
===================================================================
>From 3dd2cb0452b63d5de04606d79bbbf41a4e50a42a Mon Sep 17 00:00:00 2001
From: Grant Murphy <[email protected]>
Date: Tue, 8 Jul 2014 03:35:40 +0000
Subject: [PATCH 1/1] Avoid possible timing attack in metadata api

Introduce a constant time comparison function to
nova utils for comparing authentication tokens.
Original code taken from:

https://github.com/openstack/python-keystoneclient/blob/master/keystoneclient/middleware/memcache_crypt.py#L86

Change-Id: I7374f2edc6f03c7da59cf73ae91a87147e53d0de
Closes-bug: #1325128
---
 nova/api/metadata/handler.py |  3 ++-
 nova/tests/test_utils.py     |  7 +++++++
 nova/utils.py                | 27 +++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/nova/api/metadata/handler.py b/nova/api/metadata/handler.py
index a14db67..be866ef 100644
--- a/nova/api/metadata/handler.py
+++ b/nova/api/metadata/handler.py
@@ -30,6 +30,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
@@ -169,7 +170,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 59d08fd..c2969a6 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -979,3 +979,10 @@ class VersionTestCase(test.NoDBTestCase):
 
     def test_convert_version_to_tuple(self):
         self.assertEqual(utils.convert_version_to_tuple('6.7.0'), (6, 7, 0))
+
+
+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 0c3ee94..7dfa0cc 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -21,6 +21,7 @@ import contextlib
 import datetime
 import functools
 import hashlib
+import hmac
 import inspect
 import multiprocessing
 import os
@@ -1170,3 +1171,29 @@ def cpu_count():
         return multiprocessing.cpu_count()
     except NotImplementedError:
         return 1
+
+
+# NOTE(gm) Constant time comparison taken from keystone. This is a
+# candidate for inclusion in oslo.
+#
+# Original code: master/keystoneclient/middleware/memcache_crypt.py#L86
+if sys.version_info >= (3, 3):
+    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
+        if six.PY3 and isinstance(first, bytes) and isinstance(second, bytes):
+            for x, y in zip(first, second):
+                result |= x ^ y
+        else:
+            for x, y in zip(first, second):
+                result |= ord(x) ^ ord(y)
+        return result == 0
-- 
1.9.3





Reply via email to