mirror of
https://github.com/minio/minio.git
synced 2025-04-20 02:27:50 -04:00
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
|
apiErr = ErrNoSuchUpload
|
||||||
case PartTooSmall:
|
case PartTooSmall:
|
||||||
apiErr = ErrEntityTooSmall
|
apiErr = ErrEntityTooSmall
|
||||||
|
case SignatureDoesNotMatch:
|
||||||
|
apiErr = ErrSignatureDoesNotMatch
|
||||||
case SHA256Mismatch:
|
case SHA256Mismatch:
|
||||||
apiErr = ErrContentSHA256Mismatch
|
apiErr = ErrContentSHA256Mismatch
|
||||||
case ObjectTooLarge:
|
case ObjectTooLarge:
|
||||||
|
@ -35,6 +35,8 @@ import (
|
|||||||
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
|
||||||
|
"bytes"
|
||||||
|
|
||||||
minio "github.com/minio/minio-go"
|
minio "github.com/minio/minio-go"
|
||||||
"github.com/minio/minio-go/pkg/policy"
|
"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)
|
return ObjectInfo{}, gcsToObjectError(traceError(err), bucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sha256Writer hash.Hash
|
|
||||||
|
|
||||||
teeReader := data
|
teeReader := data
|
||||||
|
|
||||||
|
var sha256Writer hash.Hash
|
||||||
if sha256sum == "" {
|
if sha256sum == "" {
|
||||||
} else if _, err := hex.DecodeString(sha256sum); err != nil {
|
} else if _, err := hex.DecodeString(sha256sum); err != nil {
|
||||||
return ObjectInfo{}, gcsToObjectError(traceError(err), bucket, key)
|
return ObjectInfo{}, gcsToObjectError(traceError(err), bucket, key)
|
||||||
} else {
|
} else {
|
||||||
sha256Writer = sha256.New()
|
sha256Writer = sha256.New()
|
||||||
teeReader = io.TeeReader(data, sha256Writer)
|
teeReader = io.TeeReader(teeReader, sha256Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
md5sum := metadata["md5Sum"]
|
||||||
delete(metadata, "md5Sum")
|
delete(metadata, "md5Sum")
|
||||||
|
|
||||||
object := l.client.Bucket(bucket).Object(key)
|
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 {
|
if err != nil {
|
||||||
return ObjectInfo{}, gcsToObjectError(traceError(err), bucket, key)
|
return ObjectInfo{}, gcsToObjectError(traceError(err), bucket, key)
|
||||||
}
|
}
|
||||||
if sha256sum != "" {
|
|
||||||
newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil))
|
if sha256sum == "" {
|
||||||
if newSHA256sum != sha256sum {
|
} else if newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)); newSHA256sum != sha256sum {
|
||||||
//l.Client.RemoveObject(bucket, object)
|
object.Delete(l.ctx)
|
||||||
return ObjectInfo{}, traceError(SHA256Mismatch{})
|
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
|
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.
|
// Make sure we hex encode md5sum here.
|
||||||
metadata["etag"] = hex.EncodeToString(md5Bytes)
|
metadata["etag"] = hex.EncodeToString(md5Bytes)
|
||||||
|
|
||||||
sha256sum := ""
|
|
||||||
|
|
||||||
// Lock the object.
|
// Lock the object.
|
||||||
objectLock := globalNSMutex.NewNSLock(bucket, object)
|
objectLock := globalNSMutex.NewNSLock(bucket, object)
|
||||||
objectLock.Lock()
|
objectLock.Lock()
|
||||||
@ -249,7 +247,7 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
switch reqAuthType {
|
switch reqAuthType {
|
||||||
case authTypeAnonymous:
|
case authTypeAnonymous:
|
||||||
// Create anonymous object.
|
// 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:
|
case authTypeStreamingSigned:
|
||||||
// Initialize stream signature verifier.
|
// Initialize stream signature verifier.
|
||||||
reader, s3Error := newSignV4ChunkedReader(r)
|
reader, s3Error := newSignV4ChunkedReader(r)
|
||||||
@ -258,7 +256,7 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
objInfo, err = objectAPI.PutObject(bucket, object, size, reader, metadata, sha256sum)
|
objInfo, err = objectAPI.PutObject(bucket, object, size, reader, metadata, "")
|
||||||
case authTypeSignedV2, authTypePresignedV2:
|
case authTypeSignedV2, authTypePresignedV2:
|
||||||
s3Error := isReqAuthenticatedV2(r)
|
s3Error := isReqAuthenticatedV2(r)
|
||||||
if s3Error != ErrNone {
|
if s3Error != ErrNone {
|
||||||
@ -266,16 +264,20 @@ func (api gatewayAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
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:
|
case authTypePresigned, authTypeSigned:
|
||||||
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
if s3Error := reqSignatureV4Verify(r, serverConfig.GetRegion()); s3Error != ErrNone {
|
||||||
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
errorIf(errSignatureMismatch, "%s", dumpRequest(r))
|
||||||
writeErrorResponse(w, s3Error, r.URL)
|
writeErrorResponse(w, s3Error, r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sha256sum := getContentSha256Cksum(r)
|
||||||
|
|
||||||
if !skipContentSha256Cksum(r) {
|
if !skipContentSha256Cksum(r) {
|
||||||
sha256sum = r.Header.Get("X-Amz-Content-Sha256")
|
sha256sum = r.Header.Get("X-Amz-Content-Sha256")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create object.
|
// Create object.
|
||||||
objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum)
|
objInfo, err = objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum)
|
||||||
default:
|
default:
|
||||||
|
@ -110,6 +110,13 @@ func (e SHA256Mismatch) Error() string {
|
|||||||
return "sha256 computed does not match with what is expected"
|
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.
|
// StorageFull storage ran out of space.
|
||||||
type StorageFull struct{}
|
type StorageFull struct{}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user