Merge "s3api: Better-handle SHA mismatches during CompleteMultipartUpload"

This commit is contained in:
Zuul 2021-01-08 04:52:39 +00:00 committed by Gerrit Code Review
commit 1cffbe5b8f
2 changed files with 51 additions and 3 deletions

View File

@ -448,8 +448,8 @@ class SigV4Mixin(object):
'x-amz-content-sha256'
raise InvalidRequest(msg)
else:
hashed_payload = self.headers['X-Amz-Content-SHA256']
if hashed_payload != 'UNSIGNED-PAYLOAD':
hashed_payload = self.headers['X-Amz-Content-SHA256'].lower()
if hashed_payload != 'unsigned-payload':
if self.content_length == 0:
if hashed_payload != sha256().hexdigest():
raise BadDigest(
@ -853,7 +853,15 @@ class S3Request(swob.Request):
if te or ml:
# Limit the read similar to how SLO handles manifests
body = self.body_file.read(max_length)
try:
body = self.body_file.read(max_length)
except swob.HTTPException as err:
if err.status_int == HTTP_UNPROCESSABLE_ENTITY:
# Special case for HashingInput check
raise BadDigest(
'The X-Amz-Content-SHA56 you specified did not '
'match what we received.')
raise
else:
# No (or zero) Content-Length provided, and not chunked transfer;
# no body. Assume zero-length, and enforce a required body below.

View File

@ -15,6 +15,7 @@
import base64
import binascii
import hashlib
from mock import patch
import os
import time
@ -1059,6 +1060,45 @@ class TestS3ApiMultiUpload(S3ApiTestCase):
self.assertEqual('400 Bad Request', status)
self.assertEqual(self._get_error_code(body), 'BadDigest')
def test_object_multipart_upload_invalid_sha256(self):
bad_sha = hashlib.sha256(
XML.encode('ascii') + b'some junk').hexdigest()
authz_header = 'AWS4-HMAC-SHA256 ' + ', '.join([
'Credential=test:tester/%s/us-east-1/s3/aws4_request' %
self.get_v4_amz_date_header().split('T', 1)[0],
'SignedHeaders=host;x-amz-date',
'Signature=X',
])
req = Request.blank(
'/bucket/object?uploadId=X',
environ={'REQUEST_METHOD': 'POST'},
headers={'Authorization': authz_header,
'X-Amz-Date': self.get_v4_amz_date_header(),
'X-Amz-Content-SHA256': bad_sha, },
body=XML)
status, headers, body = self.call_s3api(req)
self.assertEqual('400 Bad Request', status)
self.assertEqual(self._get_error_code(body), 'BadDigest')
def test_object_multipart_upload_upper_sha256(self):
upper_sha = hashlib.sha256(
XML.encode('ascii')).hexdigest().upper()
authz_header = 'AWS4-HMAC-SHA256 ' + ', '.join([
'Credential=test:tester/%s/us-east-1/s3/aws4_request' %
self.get_v4_amz_date_header().split('T', 1)[0],
'SignedHeaders=host;x-amz-date',
'Signature=X',
])
req = Request.blank(
'/bucket/object?uploadId=X',
environ={'REQUEST_METHOD': 'POST'},
headers={'Authorization': authz_header,
'X-Amz-Date': self.get_v4_amz_date_header(),
'X-Amz-Content-SHA256': upper_sha, },
body=XML)
status, headers, body = self.call_s3api(req)
self.assertEqual('200 OK', status)
@patch('swift.common.middleware.s3api.controllers.multi_upload.time')
def test_object_multipart_upload_complete_with_heartbeat(self, mock_time):
self.swift.register(