fix `X-Amz-Credential` parsing for V4 policy signature (#6451)

This commit fixes an AWS S3 incompatibility issue.
The AccessKeyID may contain one or more `/` which caused
the server to interpret parts of the AccessKeyID as
other `X-Amz-Credential` parameters (like date, region, ...)

This commit fixes this by allowing 5 or more
`X-Amz-Credential` parameter strings and only interpreting
the last 5.

Fixes #6443
master
Andreas Auernhammer 6 years ago committed by kannappanr
parent 985fd7d4e7
commit 267a0a3dfa
  1. 20
      cmd/signature-v4-parser.go
  2. 19
      cmd/signature-v4-parser_test.go

@ -56,23 +56,25 @@ func parseCredentialHeader(credElement string, region string) (ch credentialHead
return ch, ErrMissingCredTag return ch, ErrMissingCredTag
} }
credElements := strings.Split(strings.TrimSpace(creds[1]), "/") credElements := strings.Split(strings.TrimSpace(creds[1]), "/")
if len(credElements) != 5 { if len(credElements) < 5 {
return ch, ErrCredMalformed return ch, ErrCredMalformed
} }
if !auth.IsAccessKeyValid(credElements[0]) { accessKey := strings.Join(credElements[:len(credElements)-4], "/") // The access key may contain one or more `/`
if !auth.IsAccessKeyValid(accessKey) {
return ch, ErrInvalidAccessKeyID return ch, ErrInvalidAccessKeyID
} }
// Save access key id. // Save access key id.
cred := credentialHeader{ cred := credentialHeader{
accessKey: credElements[0], accessKey: accessKey,
} }
credElements = credElements[len(credElements)-4:]
var e error var e error
cred.scope.date, e = time.Parse(yyyymmdd, credElements[1]) cred.scope.date, e = time.Parse(yyyymmdd, credElements[0])
if e != nil { if e != nil {
return ch, ErrMalformedCredentialDate return ch, ErrMalformedCredentialDate
} }
cred.scope.region = credElements[2] cred.scope.region = credElements[1]
// Verify if region is valid. // Verify if region is valid.
sRegion := cred.scope.region sRegion := cred.scope.region
// Region is set to be empty, we use whatever was sent by the // Region is set to be empty, we use whatever was sent by the
@ -87,14 +89,14 @@ func parseCredentialHeader(credElement string, region string) (ch credentialHead
return ch, ErrAuthorizationHeaderMalformed return ch, ErrAuthorizationHeaderMalformed
} }
if credElements[3] != "s3" { if credElements[2] != "s3" {
return ch, ErrInvalidService return ch, ErrInvalidService
} }
cred.scope.service = credElements[3] cred.scope.service = credElements[2]
if credElements[4] != "aws4_request" { if credElements[3] != "aws4_request" {
return ch, ErrInvalidRequestVersion return ch, ErrInvalidRequestVersion
} }
cred.scope.request = credElements[4] cred.scope.request = credElements[3]
return cred, ErrNone return cred, ErrNone
} }

@ -197,6 +197,25 @@ func TestParseCredentialHeader(t *testing.T) {
"aws4_request"), "aws4_request"),
expectedErrCode: ErrNone, expectedErrCode: ErrNone,
}, },
// Test Case - 10.
// Test case with right inputs -> AccessKey contains `/`. See minio/#6443
// "aws4_request" is the valid request version.
{
inputCredentialStr: generateCredentialStr(
"LOCALKEY/DEV/1",
sampleTimeStr,
"us-west-1",
"s3",
"aws4_request"),
expectedCredentials: generateCredentials(
t,
"LOCALKEY/DEV/1",
sampleTimeStr,
"us-west-1",
"s3",
"aws4_request"),
expectedErrCode: ErrNone,
},
} }
for i, testCase := range testCases { for i, testCase := range testCases {

Loading…
Cancel
Save