s3api: Use constant-time string comparisons in check_signature
Change-Id: Ibe514a7ab22d475517b1efc50de676f47d741a4c
This commit is contained in:
parent
1cee51d526
commit
6142ce88cc
@ -25,7 +25,8 @@ import six
|
|||||||
from six.moves.urllib.parse import quote, unquote, parse_qsl
|
from six.moves.urllib.parse import quote, unquote, parse_qsl
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from swift.common.utils import split_path, json, close_if_possible, md5
|
from swift.common.utils import split_path, json, close_if_possible, md5, \
|
||||||
|
streq_const_time
|
||||||
from swift.common.registry import get_swift_info
|
from swift.common.registry import get_swift_info
|
||||||
from swift.common import swob
|
from swift.common import swob
|
||||||
from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \
|
from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \
|
||||||
@ -160,7 +161,7 @@ class SigV4Mixin(object):
|
|||||||
derived_secret, scope_piece.encode('utf8'), sha256).digest()
|
derived_secret, scope_piece.encode('utf8'), sha256).digest()
|
||||||
valid_signature = hmac.new(
|
valid_signature = hmac.new(
|
||||||
derived_secret, self.string_to_sign, sha256).hexdigest()
|
derived_secret, self.string_to_sign, sha256).hexdigest()
|
||||||
return user_signature == valid_signature
|
return streq_const_time(user_signature, valid_signature)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _is_query_auth(self):
|
def _is_query_auth(self):
|
||||||
@ -559,7 +560,7 @@ class S3Request(swob.Request):
|
|||||||
secret, self.string_to_sign, sha1).digest()).strip()
|
secret, self.string_to_sign, sha1).digest()).strip()
|
||||||
if not six.PY2:
|
if not six.PY2:
|
||||||
valid_signature = valid_signature.decode('ascii')
|
valid_signature = valid_signature.decode('ascii')
|
||||||
return user_signature == valid_signature
|
return streq_const_time(user_signature, valid_signature)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def timestamp(self):
|
def timestamp(self):
|
||||||
|
@ -834,6 +834,11 @@ class TestRequest(S3ApiTestCase):
|
|||||||
self.assertEqual(expected_sts, sigv2_req._string_to_sign())
|
self.assertEqual(expected_sts, sigv2_req._string_to_sign())
|
||||||
self.assertTrue(sigv2_req.check_signature(secret))
|
self.assertTrue(sigv2_req.check_signature(secret))
|
||||||
|
|
||||||
|
with patch('swift.common.middleware.s3api.s3request.streq_const_time',
|
||||||
|
return_value=True) as mock_eq:
|
||||||
|
self.assertTrue(sigv2_req.check_signature(secret))
|
||||||
|
mock_eq.assert_called_once()
|
||||||
|
|
||||||
def test_check_signature_sigv2(self):
|
def test_check_signature_sigv2(self):
|
||||||
self._test_check_signature_sigv2(
|
self._test_check_signature_sigv2(
|
||||||
'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY')
|
'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY')
|
||||||
@ -874,6 +879,12 @@ class TestRequest(S3ApiTestCase):
|
|||||||
self.assertFalse(sigv4_req.check_signature(
|
self.assertFalse(sigv4_req.check_signature(
|
||||||
u'\u30c9\u30e9\u30b4\u30f3'))
|
u'\u30c9\u30e9\u30b4\u30f3'))
|
||||||
|
|
||||||
|
with patch('swift.common.middleware.s3api.s3request.streq_const_time',
|
||||||
|
return_value=False) as mock_eq:
|
||||||
|
self.assertFalse(sigv4_req.check_signature(
|
||||||
|
u'\u30c9\u30e9\u30b4\u30f3'))
|
||||||
|
mock_eq.assert_called_once()
|
||||||
|
|
||||||
@patch.object(S3Request, '_validate_dates', lambda *a: None)
|
@patch.object(S3Request, '_validate_dates', lambda *a: None)
|
||||||
def test_check_signature_sigv4_unsigned_payload(self):
|
def test_check_signature_sigv4_unsigned_payload(self):
|
||||||
environ = {
|
environ = {
|
||||||
|
Loading…
Reference in New Issue
Block a user