s3api: Block ETag header from CompleteMultipartUpload requests
Change-Id: I7df13e670f702a2956a9c8057fcb971f4bfb7319 Closes-Bug: 1810397
This commit is contained in:
parent
32bf43990c
commit
c51db382cb
@ -73,7 +73,7 @@ from six.moves.urllib.parse import quote, urlparse
|
|||||||
from swift.common.middleware.s3api.controllers.base import Controller, \
|
from swift.common.middleware.s3api.controllers.base import Controller, \
|
||||||
bucket_operation, object_operation, check_container_existence
|
bucket_operation, object_operation, check_container_existence
|
||||||
from swift.common.middleware.s3api.s3response import InvalidArgument, \
|
from swift.common.middleware.s3api.s3response import InvalidArgument, \
|
||||||
ErrorResponse, MalformedXML, \
|
ErrorResponse, MalformedXML, BadDigest, \
|
||||||
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
|
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
|
||||||
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
|
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
|
||||||
NoSuchBucket, BucketAlreadyOwnedByYou
|
NoSuchBucket, BucketAlreadyOwnedByYou
|
||||||
@ -571,6 +571,15 @@ class UploadController(Controller):
|
|||||||
xml = req.xml(MAX_COMPLETE_UPLOAD_BODY_SIZE)
|
xml = req.xml(MAX_COMPLETE_UPLOAD_BODY_SIZE)
|
||||||
if not xml:
|
if not xml:
|
||||||
raise InvalidRequest(msg='You must specify at least one part')
|
raise InvalidRequest(msg='You must specify at least one part')
|
||||||
|
if 'content-md5' in req.headers:
|
||||||
|
# If an MD5 was provided, we need to verify it.
|
||||||
|
# Note that S3Request already took care of translating to ETag
|
||||||
|
if req.headers['etag'] != md5(xml).hexdigest():
|
||||||
|
raise BadDigest(content_md5=req.headers['content-md5'])
|
||||||
|
# We're only interested in the body here, in the
|
||||||
|
# multipart-upload controller -- *don't* let it get
|
||||||
|
# plumbed down to the object-server
|
||||||
|
del req.headers['etag']
|
||||||
|
|
||||||
complete_elem = fromstring(
|
complete_elem = fromstring(
|
||||||
xml, 'CompleteMultipartUpload', self.logger)
|
xml, 'CompleteMultipartUpload', self.logger)
|
||||||
|
@ -114,6 +114,9 @@ class FakeSwift(object):
|
|||||||
if method == 'PUT' and obj:
|
if method == 'PUT' and obj:
|
||||||
input = env['wsgi.input'].read()
|
input = env['wsgi.input'].read()
|
||||||
etag = md5(input).hexdigest()
|
etag = md5(input).hexdigest()
|
||||||
|
if env.get('HTTP_ETAG', etag) != etag:
|
||||||
|
raise Exception('Client sent a bad ETag! Got %r, but '
|
||||||
|
'md5(body) = %r' % (env['HTTP_ETAG'], etag))
|
||||||
headers.setdefault('Etag', etag)
|
headers.setdefault('Etag', etag)
|
||||||
headers.setdefault('Content-Length', len(input))
|
headers.setdefault('Content-Length', len(input))
|
||||||
|
|
||||||
|
@ -667,10 +667,12 @@ class TestS3ApiMultiUpload(S3ApiTestCase):
|
|||||||
self.assertEqual(self._get_error_code(body), 'NoSuchBucket')
|
self.assertEqual(self._get_error_code(body), 'NoSuchBucket')
|
||||||
|
|
||||||
def test_object_multipart_upload_complete(self):
|
def test_object_multipart_upload_complete(self):
|
||||||
|
content_md5 = base64.b64encode(hashlib.md5(xml).digest())
|
||||||
req = Request.blank('/bucket/object?uploadId=X',
|
req = Request.blank('/bucket/object?uploadId=X',
|
||||||
environ={'REQUEST_METHOD': 'POST'},
|
environ={'REQUEST_METHOD': 'POST'},
|
||||||
headers={'Authorization': 'AWS test:tester:hmac',
|
headers={'Authorization': 'AWS test:tester:hmac',
|
||||||
'Date': self.get_date_header(), },
|
'Date': self.get_date_header(),
|
||||||
|
'Content-MD5': content_md5, },
|
||||||
body=xml)
|
body=xml)
|
||||||
status, headers, body = self.call_s3api(req)
|
status, headers, body = self.call_s3api(req)
|
||||||
elem = fromstring(body, 'CompleteMultipartUploadResult')
|
elem = fromstring(body, 'CompleteMultipartUploadResult')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user