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 9f59ca751f
)
This commit is contained in:
parent
e6dd7dabcd
commit
1dd97d1335
|
@ -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 '
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -23,6 +23,7 @@ import contextlib
|
|||
import datetime
|
||||
import functools
|
||||
import hashlib
|
||||
import hmac
|
||||
import inspect
|
||||
import os
|
||||
import pyclbr
|
||||
|
@ -1302,3 +1303,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
|
||||
|
|
Loading…
Reference in New Issue