@ -28,6 +28,7 @@ import (
"strings"
"strings"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/hash"
"github.com/minio/minio/pkg/policy"
"github.com/minio/minio/pkg/policy"
)
)
@ -209,59 +210,45 @@ func reqSignatureV4Verify(r *http.Request, region string) (s3Error APIErrorCode)
// Verify if request has valid AWS Signature Version '4'.
// Verify if request has valid AWS Signature Version '4'.
func isReqAuthenticated ( r * http . Request , region string ) ( s3Error APIErrorCode ) {
func isReqAuthenticated ( r * http . Request , region string ) ( s3Error APIErrorCode ) {
if r == nil {
return ErrInternalError
}
if errCode := reqSignatureV4Verify ( r , region ) ; errCode != ErrNone {
if errCode := reqSignatureV4Verify ( r , region ) ; errCode != ErrNone {
return errCode
return errCode
}
}
payload , err := ioutil . ReadAll ( r . Body )
var (
if err != nil {
err error
logger . LogIf ( context . Background ( ) , err )
contentMD5 , contentSHA256 [ ] byte
return ErrInternalError
)
}
// Extract 'Content-Md5' if present.
if _ , ok := r . Header [ "Content-Md5" ] ; ok {
// Populate back the payload.
contentMD5 , err = base64 . StdEncoding . Strict ( ) . DecodeString ( r . Header . Get ( "Content-Md5" ) )
r . Body = ioutil . NopCloser ( bytes . NewReader ( payload ) )
if err != nil || len ( contentMD5 ) == 0 {
// Verify Content-Md5, if payload is set.
if clntMD5B64 , ok := r . Header [ "Content-Md5" ] ; ok {
if clntMD5B64 [ 0 ] == "" {
return ErrInvalidDigest
return ErrInvalidDigest
}
}
md5Sum , err := base64 . StdEncoding . Strict ( ) . DecodeString ( clntMD5B64 [ 0 ] )
if err != nil {
return ErrInvalidDigest
}
if ! bytes . Equal ( md5Sum , getMD5Sum ( payload ) ) {
return ErrBadDigest
}
}
}
if skipContentSha256Cksum ( r ) {
// Extract either 'X-Amz-Content-Sha256' header or 'X-Amz-Content-Sha256' query parameter (if V4 presigned)
return ErrNone
// Do not verify 'X-Amz-Content-Sha256' if skipSHA256.
}
if skipSHA256 := skipContentSha256Cksum ( r ) ; ! skipSHA256 && isRequestPresignedSignatureV4 ( r ) {
if sha256Sum , ok := r . URL . Query ( ) [ "X-Amz-Content-Sha256" ] ; ok && len ( sha256Sum ) > 0 {
// Verify that X-Amz-Content-Sha256 Header == sha256(payload)
contentSHA256 , err = hex . DecodeString ( sha256Sum [ 0 ] )
// If X-Amz-Content-Sha256 header is not sent then we don't calculate/verify sha256(payload)
if err != nil {
sumHex , ok := r . Header [ "X-Amz-Content-Sha256" ]
return ErrContentSHA256Mismatch
if isRequestPresignedSignatureV4 ( r ) {
}
sumHex , ok = r . URL . Query ( ) [ "X-Amz-Content-Sha256" ]
}
if ok {
if sumHex [ 0 ] == "" {
return ErrContentSHA256Mismatch
}
sum , err := hex . DecodeString ( sumHex [ 0 ] )
if err != nil {
return ErrContentSHA256Mismatch
}
}
if ! bytes . Equal ( sum , getSHA256Sum ( payload ) ) {
} else if _ , ok := r . Header [ "X-Amz-Content-Sha256" ] ; ! skipSHA256 && ok {
contentSHA256 , err = hex . DecodeString ( r . Header . Get ( "X-Amz-Content-Sha256" ) )
if err != nil || len ( contentSHA256 ) == 0 {
return ErrContentSHA256Mismatch
return ErrContentSHA256Mismatch
}
}
}
}
// Verify 'Content-Md5' and/or 'X-Amz-Content-Sha256' if present.
// The verification happens implicit during reading.
reader , err := hash . NewReader ( r . Body , - 1 , hex . EncodeToString ( contentMD5 ) , hex . EncodeToString ( contentSHA256 ) )
if err != nil {
return toAPIErrorCode ( err )
}
r . Body = ioutil . NopCloser ( reader )
return ErrNone
return ErrNone
}
}