diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-04-01 13:39:46 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-04-01 13:39:46 +0000 |
commit | 89905636f0eac9604bda4a2ab16cf851ba1b8266 (patch) | |
tree | e4b5c91ed576196e937bbbde672b4d02ad31ec7e /swift | |
parent | 917cf9e221d1fe164e0652c9c102345f201a300e (diff) | |
parent | cd149ae19f9235cf7bfc96ed2e06a4fd390a4006 (diff) | |
download | swift-89905636f0eac9604bda4a2ab16cf851ba1b8266.tar.gz |
Merge "Check object segment MD5s"
Diffstat (limited to 'swift')
-rw-r--r-- | swift/common/request_helpers.py | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/swift/common/request_helpers.py b/swift/common/request_helpers.py index a6f0c985e..98a239e69 100644 --- a/swift/common/request_helpers.py +++ b/swift/common/request_helpers.py @@ -20,6 +20,7 @@ Why not swift.common.utils, you ask? Because this way we can import things from swob in here without creating circular imports. """ +import hashlib import sys import time from contextlib import contextmanager @@ -281,8 +282,11 @@ class SegmentedIterable(object): 'ERROR: While processing manifest %s, ' 'max LO GET time of %ds exceeded' % (self.name, self.max_get_time)) + # Make sure that the segment is a plain old object, not some + # flavor of large object, so that we can check its MD5. + path = seg_path + '?multipart-manifest=get' seg_req = make_subrequest( - self.req.environ, path=seg_path, method='GET', + self.req.environ, path=path, method='GET', headers={'x-auth-token': self.req.headers.get( 'x-auth-token')}, agent=('%(orig)s ' + self.ua_suffix), @@ -322,7 +326,9 @@ class SegmentedIterable(object): 's_etag': seg_etag, 's_size': seg_size}) + seg_hash = hashlib.md5() for chunk in seg_resp.app_iter: + seg_hash.update(chunk) have_yielded_data = True if bytes_left is None: yield chunk @@ -340,6 +346,14 @@ class SegmentedIterable(object): 'left': bytes_left}) close_if_possible(seg_resp.app_iter) + if seg_resp.etag and seg_hash.hexdigest() != seg_resp.etag \ + and first_byte is None and last_byte is None: + raise SegmentError( + "Bad MD5 checksum in %(name)s for %(seg)s: headers had" + " %(etag)s, but object MD5 was actually %(actual)s" % + {'seg': seg_req.path, 'etag': seg_resp.etag, + 'name': self.name, 'actual': seg_hash.hexdigest()}) + if bytes_left: raise SegmentError( 'Not enough bytes for %s; closing connection' % |