mirror of https://github.com/minio/minio.git
				
				
				
			Verify md5 content hash, closes #4285
This commit is contained in:
		
							parent
							
								
									bd67117756
								
							
						
					
					
						commit
						5c78415b31
					
				|  | @ -706,6 +706,8 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) { | |||
| 		apiErr = ErrNoSuchUpload | ||||
| 	case PartTooSmall: | ||||
| 		apiErr = ErrEntityTooSmall | ||||
| 	case SignatureDoesNotMatch: | ||||
| 		apiErr = ErrSignatureDoesNotMatch | ||||
| 	case SHA256Mismatch: | ||||
| 		apiErr = ErrContentSHA256Mismatch | ||||
| 	case ObjectTooLarge: | ||||
|  |  | |||
|  | @ -35,6 +35,8 @@ import ( | |||
| 
 | ||||
| 	"encoding/base64" | ||||
| 
 | ||||
| 	"bytes" | ||||
| 
 | ||||
| 	minio "github.com/minio/minio-go" | ||||
| 	"github.com/minio/minio-go/pkg/policy" | ||||
| ) | ||||
|  | @ -469,17 +471,18 @@ func (l *gcsGateway) PutObject(bucket string, key string, size int64, data io.Re | |||
| 		return ObjectInfo{}, gcsToObjectError(traceError(err), bucket) | ||||
| 	} | ||||
| 
 | ||||
| 	var sha256Writer hash.Hash | ||||
| 
 | ||||
| 	teeReader := data | ||||
| 
 | ||||
| 	var sha256Writer hash.Hash | ||||
| 	if sha256sum == "" { | ||||
| 	} else if _, err := hex.DecodeString(sha256sum); err != nil { | ||||
| 		return ObjectInfo{}, gcsToObjectError(traceError(err), bucket, key) | ||||
| 	} else { | ||||
| 		sha256Writer = sha256.New() | ||||
| 		teeReader = io.TeeReader(data, sha256Writer) | ||||
| 		teeReader = io.TeeReader(teeReader, sha256Writer) | ||||
| 	} | ||||
| 
 | ||||
| 	md5sum := metadata["md5Sum"] | ||||
| 	delete(metadata, "md5Sum") | ||||
| 
 | ||||
| 	object := l.client.Bucket(bucket).Object(key) | ||||
|  | @ -504,12 +507,18 @@ func (l *gcsGateway) PutObject(bucket string, key string, size int64, data io.Re | |||
| 	if err != nil { | ||||
| 		return ObjectInfo{}, gcsToObjectError(traceError(err), bucket, key) | ||||
| 	} | ||||
| 	if sha256sum != "" { | ||||
| 		newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)) | ||||
| 		if newSHA256sum != sha256sum { | ||||
| 			//l.Client.RemoveObject(bucket, object)
 | ||||
| 
 | ||||
| 	if sha256sum == "" { | ||||
| 	} else if newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)); newSHA256sum != sha256sum { | ||||
| 		object.Delete(l.ctx) | ||||
| 		return ObjectInfo{}, traceError(SHA256Mismatch{}) | ||||
| 	} | ||||
| 
 | ||||
| 	if md5sum == "" { | ||||
| 	} else if b, err := hex.DecodeString(md5sum); err != nil { | ||||
| 	} else if bytes.Compare(b, attrs.MD5) != 0 { | ||||
| 		object.Delete(l.ctx) | ||||
| 		return ObjectInfo{}, traceError(SignatureDoesNotMatch{}) | ||||
| 	} | ||||
| 
 | ||||
| 	return fromGCSObjectInfo(attrs), nil | ||||
|  |  | |||
|  | @ -238,8 +238,6 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re | |||
| 	// Make sure we hex encode md5sum here.
 | ||||
| 	metadata["etag"] = hex.EncodeToString(md5Bytes) | ||||
| 
 | ||||
| 	sha256sum := "" | ||||
| 
 | ||||
| 	// Lock the object.
 | ||||
| 	objectLock := globalNSMutex.NewNSLock(bucket, object) | ||||
| 	objectLock.Lock() | ||||
|  | @ -249,7 +247,7 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re | |||
| 	switch reqAuthType { | ||||
| 	case authTypeAnonymous: | ||||
| 		// Create anonymous object.
 | ||||
| 		objInfo, err = objectAPI.AnonPutObject(bucket, object, size, r.Body, metadata, sha256sum) | ||||
| 		objInfo, err = objectAPI.AnonPutObject(bucket, object, size, r.Body, metadata, "") | ||||
| 	case authTypeStreamingSigned: | ||||
| 		// Initialize stream signature verifier.
 | ||||
| 		reader, s3Error := newSignV4ChunkedReader(r) | ||||
|  | @ -258,7 +256,7 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re | |||
| 			writeErrorResponse(w, s3Error, r.URL) | ||||
| 			return | ||||
| 		} | ||||
| 		objInfo, err = objectAPI.PutObject(bucket, object, size, reader, metadata, sha256sum) | ||||
| 		objInfo, err = objectAPI.PutObject(bucket, object, size, reader, metadata, "") | ||||
| 	case authTypeSignedV2, authTypePresignedV2: | ||||
| 		s3Error := isReqAuthenticatedV2(r) | ||||
| 		if s3Error != ErrNone { | ||||
|  | @ -266,16 +264,20 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re | |||
| 			writeErrorResponse(w, s3Error, r.URL) | ||||
| 			return | ||||
| 		} | ||||
| 		objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum) | ||||
| 		objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, "") | ||||
| 	case authTypePresigned, authTypeSigned: | ||||
| 		if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone { | ||||
| 			errorIf(errSignatureMismatch, "%s", dumpRequest(r)) | ||||
| 			writeErrorResponse(w, s3Error, r.URL) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		sha256sum := getContentSha256Cksum(r) | ||||
| 
 | ||||
| 		if !skipContentSha256Cksum(r) { | ||||
| 			sha256sum = r.Header.Get("X-Amz-Content-Sha256") | ||||
| 		} | ||||
| 
 | ||||
| 		// Create object.
 | ||||
| 		objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum) | ||||
| 	default: | ||||
|  |  | |||
|  | @ -110,6 +110,13 @@ func (e SHA256Mismatch) Error() string { | |||
| 	return "sha256 computed does not match with what is expected" | ||||
| } | ||||
| 
 | ||||
| // SignatureDoesNotMatch - when content md5 does not match with what was sent from client.
 | ||||
| type SignatureDoesNotMatch struct{} | ||||
| 
 | ||||
| func (e SignatureDoesNotMatch) Error() string { | ||||
| 	return "The request signature we calculated does not match the signature you provided. Check your key and signing method." | ||||
| } | ||||
| 
 | ||||
| // StorageFull storage ran out of space.
 | ||||
| type StorageFull struct{} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue