mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-29 16:30:44 +01:00
s3: accept bare composite checksum on CompleteMultipartUpload (#12194)
* s3: accept bare composite checksum on CompleteMultipartUpload Clients such as minio-go send the composite object checksum without the "-<parts>" suffix. Compare against the base64 part of the computed composite value as well as the full form. * s3: test object checksum matching with and without part suffix
This commit is contained in:
1 parent
4ed9595a58
commit
ec43f4ca00
2 files changed
+35
-1
No files matched your search
@@ -625,7 +625,7 @@ func (s3a *S3ApiServer) prepareMultipartCompletionState(r *http.Request, input *
|
||||
glog.Errorf("completeMultipartUpload: %s checksum computation failed: %v", checksumType, checksumErr)
|
||||
return nil, nil, s3err.ErrInvalidPart
|
||||
}
|
||||
if objectChecksum := lookupHeaderOrQuery(r, query, checksumHeaderName); objectChecksum != "" && objectChecksum != checksumValue {
|
||||
if objectChecksum := lookupHeaderOrQuery(r, query, checksumHeaderName); objectChecksum != "" && !matchesObjectChecksum(objectChecksum, checksumValue) {
|
||||
return nil, nil, s3err.ErrBadDigest
|
||||
}
|
||||
}
|
||||
@@ -1858,6 +1858,18 @@ func decodePartChecksum(partNumber int, entries []*filer_pb.Entry, checksumHeade
|
||||
return raw, entry, nil
|
||||
}
|
||||
|
||||
// matchesObjectChecksum accepts the computed checksum verbatim or, for a
|
||||
// composite checksum, its bare base64 form without the "-N" part-count suffix.
|
||||
func matchesObjectChecksum(provided, computed string) bool {
|
||||
if provided == computed {
|
||||
return true
|
||||
}
|
||||
if i := strings.LastIndexByte(computed, '-'); i > 0 {
|
||||
return provided == computed[:i]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// computeCompositeChecksum computes a composite checksum from per-part checksums.
|
||||
// It concatenates the raw (decoded) per-part checksums, hashes the result with the
|
||||
// same algorithm, and returns the value as "base64-N" where N is the part count.
|
||||
|
||||
@@ -204,3 +204,25 @@ func TestCreateMultipartUploadResultChecksumHeaders(t *testing.T) {
|
||||
t.Fatalf("response %q carries checksum members in the XML body", encoded)
|
||||
}
|
||||
}
|
||||
|
||||
// A client may send the composite object checksum with or without the "-N"
|
||||
// part-count suffix (minio-go sends the bare form); both must match.
|
||||
func TestMatchesObjectChecksum(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
provided string
|
||||
computed string
|
||||
want bool
|
||||
}{
|
||||
{"hSEgHA==-1", "hSEgHA==-1", true},
|
||||
{"hSEgHA==", "hSEgHA==-1", true},
|
||||
{"hSEgHA==-2", "hSEgHA==-1", false},
|
||||
{"AAAAAA==", "hSEgHA==-1", false},
|
||||
{"fx4FQw==", "fx4FQw==", true},
|
||||
{"fx4FQw==-1", "fx4FQw==", false},
|
||||
{"", "hSEgHA==-1", false},
|
||||
} {
|
||||
if got := matchesObjectChecksum(tc.provided, tc.computed); got != tc.want {
|
||||
t.Errorf("matchesObjectChecksum(%q, %q) = %v, want %v", tc.provided, tc.computed, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user