mirror of
https://github.com/minio/minio.git
synced 2024-12-25 22:55:54 -05:00
sign: StreamingSign should use region from client. (#4577)
This is a fix to make streaming signature to behave the same as regular signature and presigned signature. Fixes https://github.com/minio/minio-go/issues/718
This commit is contained in:
parent
9d3d64df2d
commit
cec8b238f3
@ -41,13 +41,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// getChunkSignature - get chunk signature.
|
// getChunkSignature - get chunk signature.
|
||||||
func getChunkSignature(seedSignature string, date time.Time, hashedChunk string) string {
|
func getChunkSignature(seedSignature string, region string, date time.Time, hashedChunk string) string {
|
||||||
// Access credentials.
|
// Access credentials.
|
||||||
cred := serverConfig.GetCredential()
|
cred := serverConfig.GetCredential()
|
||||||
|
|
||||||
// Server region.
|
|
||||||
region := serverConfig.GetRegion()
|
|
||||||
|
|
||||||
// Calculate string to sign.
|
// Calculate string to sign.
|
||||||
stringToSign := signV4ChunkedAlgorithm + "\n" +
|
stringToSign := signV4ChunkedAlgorithm + "\n" +
|
||||||
date.Format(iso8601Format) + "\n" +
|
date.Format(iso8601Format) + "\n" +
|
||||||
@ -69,12 +66,12 @@ func getChunkSignature(seedSignature string, date time.Time, hashedChunk string)
|
|||||||
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
|
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
|
||||||
// returns signature, error otherwise if the signature mismatches or any other
|
// returns signature, error otherwise if the signature mismatches or any other
|
||||||
// error while parsing and validating.
|
// error while parsing and validating.
|
||||||
func calculateSeedSignature(r *http.Request) (signature string, date time.Time, errCode APIErrorCode) {
|
func calculateSeedSignature(r *http.Request) (signature string, region string, date time.Time, errCode APIErrorCode) {
|
||||||
// Access credentials.
|
// Access credentials.
|
||||||
cred := serverConfig.GetCredential()
|
cred := serverConfig.GetCredential()
|
||||||
|
|
||||||
// Server region.
|
// Configured region.
|
||||||
region := serverConfig.GetRegion()
|
confRegion := serverConfig.GetRegion()
|
||||||
|
|
||||||
// Copy request.
|
// Copy request.
|
||||||
req := *r
|
req := *r
|
||||||
@ -85,7 +82,7 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time,
|
|||||||
// Parse signature version '4' header.
|
// Parse signature version '4' header.
|
||||||
signV4Values, errCode := parseSignV4(v4Auth)
|
signV4Values, errCode := parseSignV4(v4Auth)
|
||||||
if errCode != ErrNone {
|
if errCode != ErrNone {
|
||||||
return "", time.Time{}, errCode
|
return "", "", time.Time{}, errCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Payload streaming.
|
// Payload streaming.
|
||||||
@ -93,32 +90,32 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time,
|
|||||||
|
|
||||||
// Payload for STREAMING signature should be 'STREAMING-AWS4-HMAC-SHA256-PAYLOAD'
|
// Payload for STREAMING signature should be 'STREAMING-AWS4-HMAC-SHA256-PAYLOAD'
|
||||||
if payload != req.Header.Get("X-Amz-Content-Sha256") {
|
if payload != req.Header.Get("X-Amz-Content-Sha256") {
|
||||||
return "", time.Time{}, ErrContentSHA256Mismatch
|
return "", "", time.Time{}, ErrContentSHA256Mismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract all the signed headers along with its values.
|
// Extract all the signed headers along with its values.
|
||||||
extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, r)
|
extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, r)
|
||||||
if errCode != ErrNone {
|
if errCode != ErrNone {
|
||||||
return "", time.Time{}, errCode
|
return "", "", time.Time{}, errCode
|
||||||
}
|
}
|
||||||
// Verify if the access key id matches.
|
// Verify if the access key id matches.
|
||||||
if signV4Values.Credential.accessKey != cred.AccessKey {
|
if signV4Values.Credential.accessKey != cred.AccessKey {
|
||||||
return "", time.Time{}, ErrInvalidAccessKeyID
|
return "", "", time.Time{}, ErrInvalidAccessKeyID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify if region is valid.
|
// Verify if region is valid.
|
||||||
sRegion := signV4Values.Credential.scope.region
|
region = signV4Values.Credential.scope.region
|
||||||
// Should validate region, only if region is set. Some operations
|
// Should validate region, only if region is set. Some operations
|
||||||
// do not need region validated for example GetBucketLocation.
|
// do not need region validated for example GetBucketLocation.
|
||||||
if !isValidRegion(sRegion, region) {
|
if !isValidRegion(region, confRegion) {
|
||||||
return "", time.Time{}, ErrInvalidRegion
|
return "", "", time.Time{}, ErrInvalidRegion
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract date, if not present throw error.
|
// Extract date, if not present throw error.
|
||||||
var dateStr string
|
var dateStr string
|
||||||
if dateStr = req.Header.Get(http.CanonicalHeaderKey("x-amz-date")); dateStr == "" {
|
if dateStr = req.Header.Get(http.CanonicalHeaderKey("x-amz-date")); dateStr == "" {
|
||||||
if dateStr = r.Header.Get("Date"); dateStr == "" {
|
if dateStr = r.Header.Get("Date"); dateStr == "" {
|
||||||
return "", time.Time{}, ErrMissingDateHeader
|
return "", "", time.Time{}, ErrMissingDateHeader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Parse date header.
|
// Parse date header.
|
||||||
@ -126,7 +123,7 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time,
|
|||||||
date, err = time.Parse(iso8601Format, dateStr)
|
date, err = time.Parse(iso8601Format, dateStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "Unable to parse date", dateStr)
|
errorIf(err, "Unable to parse date", dateStr)
|
||||||
return "", time.Time{}, ErrMalformedDate
|
return "", "", time.Time{}, ErrMalformedDate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query string.
|
// Query string.
|
||||||
@ -146,11 +143,11 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time,
|
|||||||
|
|
||||||
// Verify if signature match.
|
// Verify if signature match.
|
||||||
if newSignature != signV4Values.Signature {
|
if newSignature != signV4Values.Signature {
|
||||||
return "", time.Time{}, ErrSignatureDoesNotMatch
|
return "", "", time.Time{}, ErrSignatureDoesNotMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return caculated signature.
|
// Return caculated signature.
|
||||||
return newSignature, date, ErrNone
|
return newSignature, region, date, ErrNone
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxLineLength = 4 * humanize.KiByte // assumed <= bufio.defaultBufSize 4KiB
|
const maxLineLength = 4 * humanize.KiByte // assumed <= bufio.defaultBufSize 4KiB
|
||||||
@ -168,7 +165,7 @@ var errMalformedEncoding = errors.New("malformed chunked encoding")
|
|||||||
// NewChunkedReader is not needed by normal applications. The http package
|
// NewChunkedReader is not needed by normal applications. The http package
|
||||||
// automatically decodes chunking when reading response bodies.
|
// automatically decodes chunking when reading response bodies.
|
||||||
func newSignV4ChunkedReader(req *http.Request) (io.Reader, APIErrorCode) {
|
func newSignV4ChunkedReader(req *http.Request) (io.Reader, APIErrorCode) {
|
||||||
seedSignature, seedDate, errCode := calculateSeedSignature(req)
|
seedSignature, region, seedDate, errCode := calculateSeedSignature(req)
|
||||||
if errCode != ErrNone {
|
if errCode != ErrNone {
|
||||||
return nil, errCode
|
return nil, errCode
|
||||||
}
|
}
|
||||||
@ -176,6 +173,7 @@ func newSignV4ChunkedReader(req *http.Request) (io.Reader, APIErrorCode) {
|
|||||||
reader: bufio.NewReader(req.Body),
|
reader: bufio.NewReader(req.Body),
|
||||||
seedSignature: seedSignature,
|
seedSignature: seedSignature,
|
||||||
seedDate: seedDate,
|
seedDate: seedDate,
|
||||||
|
region: region,
|
||||||
chunkSHA256Writer: sha256.New(),
|
chunkSHA256Writer: sha256.New(),
|
||||||
state: readChunkHeader,
|
state: readChunkHeader,
|
||||||
}, ErrNone
|
}, ErrNone
|
||||||
@ -187,6 +185,7 @@ type s3ChunkedReader struct {
|
|||||||
reader *bufio.Reader
|
reader *bufio.Reader
|
||||||
seedSignature string
|
seedSignature string
|
||||||
seedDate time.Time
|
seedDate time.Time
|
||||||
|
region string
|
||||||
state chunkState
|
state chunkState
|
||||||
lastChunk bool
|
lastChunk bool
|
||||||
chunkSignature string
|
chunkSignature string
|
||||||
@ -304,7 +303,7 @@ func (cr *s3ChunkedReader) Read(buf []byte) (n int, err error) {
|
|||||||
// Calculate the hashed chunk.
|
// Calculate the hashed chunk.
|
||||||
hashedChunk := hex.EncodeToString(cr.chunkSHA256Writer.Sum(nil))
|
hashedChunk := hex.EncodeToString(cr.chunkSHA256Writer.Sum(nil))
|
||||||
// Calculate the chunk signature.
|
// Calculate the chunk signature.
|
||||||
newSignature := getChunkSignature(cr.seedSignature, cr.seedDate, hashedChunk)
|
newSignature := getChunkSignature(cr.seedSignature, cr.region, cr.seedDate, hashedChunk)
|
||||||
if cr.chunkSignature != newSignature {
|
if cr.chunkSignature != newSignature {
|
||||||
// Chunk signature doesn't match we return signature does not match.
|
// Chunk signature doesn't match we return signature does not match.
|
||||||
cr.err = errSignatureMismatch
|
cr.err = errSignatureMismatch
|
||||||
|
Loading…
Reference in New Issue
Block a user