summaryrefslogtreecommitdiff
path: root/swift
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-04-01 13:39:46 +0000
committerGerrit Code Review <review@openstack.org>2014-04-01 13:39:46 +0000
commit89905636f0eac9604bda4a2ab16cf851ba1b8266 (patch)
treee4b5c91ed576196e937bbbde672b4d02ad31ec7e /swift
parent917cf9e221d1fe164e0652c9c102345f201a300e (diff)
parentcd149ae19f9235cf7bfc96ed2e06a4fd390a4006 (diff)
downloadswift-89905636f0eac9604bda4a2ab16cf851ba1b8266.tar.gz
Merge "Check object segment MD5s"
Diffstat (limited to 'swift')
-rw-r--r--swift/common/request_helpers.py16
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' %