From 45d9cfa0c5da82109d490c20f1eb076addf47ce4 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Mon, 6 Feb 2017 13:09:09 -0800 Subject: [PATCH] signature-v4: stringToSign and signingKey should use Scope's date. (#3688) fixes #3676 --- cmd/signature-v4-parser.go | 10 ++++++++++ cmd/signature-v4.go | 20 +++++++------------- cmd/signature-v4_test.go | 11 ++--------- cmd/streaming-signature-v4.go | 4 ++-- cmd/test-utils_test.go | 5 +++-- cmd/web-handlers.go | 2 +- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/cmd/signature-v4-parser.go b/cmd/signature-v4-parser.go index 913099e47..475361fa4 100644 --- a/cmd/signature-v4-parser.go +++ b/cmd/signature-v4-parser.go @@ -34,6 +34,16 @@ type credentialHeader struct { } } +// Return scope string. +func (c credentialHeader) getScope() string { + return strings.Join([]string{ + c.scope.date.Format(yyyymmdd), + c.scope.region, + c.scope.service, + c.scope.request, + }, "/") +} + // parse credentialHeader string into its structured form. func parseCredentialHeader(credElement string) (credentialHeader, APIErrorCode) { creds := strings.Split(strings.TrimSpace(credElement), "=") diff --git a/cmd/signature-v4.go b/cmd/signature-v4.go index 174e7579d..f6a5ea2fb 100644 --- a/cmd/signature-v4.go +++ b/cmd/signature-v4.go @@ -124,9 +124,9 @@ func getScope(t time.Time, region string) string { } // getStringToSign a string based on selected query values. -func getStringToSign(canonicalRequest string, t time.Time, region string) string { +func getStringToSign(canonicalRequest string, t time.Time, scope string) string { stringToSign := signV4Algorithm + "\n" + t.Format(iso8601Format) + "\n" - stringToSign = stringToSign + getScope(t, region) + "\n" + stringToSign = stringToSign + scope + "\n" canonicalRequestBytes := sha256.Sum256([]byte(canonicalRequest)) stringToSign = stringToSign + hex.EncodeToString(canonicalRequestBytes[:]) return stringToSign @@ -182,14 +182,8 @@ func doesPolicySignatureV4Match(formValues map[string]string) APIErrorCode { return ErrInvalidRegion } - // Parse date string. - t, e := time.Parse(iso8601Format, formValues["X-Amz-Date"]) - if e != nil { - return ErrMalformedDate - } - // Get signing key. - signingKey := getSigningKey(cred.SecretKey, t, region) + signingKey := getSigningKey(cred.SecretKey, credHeader.scope.date, region) // Get signature. newSignature := getSignature(signingKey, formValues["Policy"]) @@ -311,10 +305,10 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s presignedCanonicalReq := getCanonicalRequest(extractedSignedHeaders, hashedPayload, encodedQuery, req.URL.Path, req.Method, req.Host) // Get string to sign from canonical request. - presignedStringToSign := getStringToSign(presignedCanonicalReq, t, region) + presignedStringToSign := getStringToSign(presignedCanonicalReq, t, pSignValues.Credential.getScope()) // Get hmac presigned signing key. - presignedSigningKey := getSigningKey(cred.SecretKey, t, region) + presignedSigningKey := getSigningKey(cred.SecretKey, pSignValues.Credential.scope.date, region) // Get new signature. newSignature := getSignature(presignedSigningKey, presignedStringToSign) @@ -408,10 +402,10 @@ func doesSignatureMatch(hashedPayload string, r *http.Request, region string) AP canonicalRequest := getCanonicalRequest(extractedSignedHeaders, hashedPayload, queryStr, req.URL.Path, req.Method, req.Host) // Get string to sign from canonical request. - stringToSign := getStringToSign(canonicalRequest, t, region) + stringToSign := getStringToSign(canonicalRequest, t, signV4Values.Credential.getScope()) // Get hmac signing key. - signingKey := getSigningKey(cred.SecretKey, t, region) + signingKey := getSigningKey(cred.SecretKey, signV4Values.Credential.scope.date, region) // Calculate signature. newSignature := getSignature(signingKey, stringToSign) diff --git a/cmd/signature-v4_test.go b/cmd/signature-v4_test.go index 4990f9941..12137d1e1 100644 --- a/cmd/signature-v4_test.go +++ b/cmd/signature-v4_test.go @@ -61,14 +61,7 @@ func TestDoesPolicySignatureMatch(t *testing.T) { }, expected: ErrInvalidRegion, }, - // (3) It should fail if the date is invalid (or missing, in this case). - { - form: map[string]string{ - "X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion), - }, - expected: ErrMalformedDate, - }, - // (4) It should fail with a bad signature. + // (3) It should fail with a bad signature. { form: map[string]string{ "X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion), @@ -78,7 +71,7 @@ func TestDoesPolicySignatureMatch(t *testing.T) { }, expected: ErrSignatureDoesNotMatch, }, - // (5) It should succeed if everything is correct. + // (4) It should succeed if everything is correct. { form: map[string]string{ "X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion), diff --git a/cmd/streaming-signature-v4.go b/cmd/streaming-signature-v4.go index d2bbc3d66..8e703bfb4 100644 --- a/cmd/streaming-signature-v4.go +++ b/cmd/streaming-signature-v4.go @@ -135,10 +135,10 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time, canonicalRequest := getCanonicalRequest(extractedSignedHeaders, payload, queryStr, req.URL.Path, req.Method, req.Host) // Get string to sign from canonical request. - stringToSign := getStringToSign(canonicalRequest, date, region) + stringToSign := getStringToSign(canonicalRequest, date, signV4Values.Credential.getScope()) // Get hmac signing key. - signingKey := getSigningKey(cred.SecretKey, date, region) + signingKey := getSigningKey(cred.SecretKey, signV4Values.Credential.scope.date, region) // Calculate signature. newSignature := getSignature(signingKey, stringToSign) diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 98c6bc15e..67219df0c 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -893,7 +893,8 @@ func preSignV4(req *http.Request, accessKeyID, secretAccessKey string, expires i region := serverConfig.GetRegion() date := time.Now().UTC() - credential := fmt.Sprintf("%s/%s", accessKeyID, getScope(date, region)) + scope := getScope(date, region) + credential := fmt.Sprintf("%s/%s", accessKeyID, scope) // Set URL query. query := req.URL.Query() @@ -909,7 +910,7 @@ func preSignV4(req *http.Request, accessKeyID, secretAccessKey string, expires i queryStr := strings.Replace(query.Encode(), "+", "%20", -1) canonicalRequest := getCanonicalRequest(extractedSignedHeaders, unsignedPayload, queryStr, req.URL.Path, req.Method, req.Host) - stringToSign := getStringToSign(canonicalRequest, date, region) + stringToSign := getStringToSign(canonicalRequest, date, scope) signingKey := getSigningKey(secretAccessKey, date, region) signature := getSignature(signingKey, stringToSign) diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 4943fa78c..d3f65a0e8 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -748,7 +748,7 @@ func presignedGet(host, bucket, object string, expiry int64) string { var extractedSignedHeaders http.Header canonicalRequest := getCanonicalRequest(extractedSignedHeaders, unsignedPayload, query, path, "GET", host) - stringToSign := getStringToSign(canonicalRequest, date, region) + stringToSign := getStringToSign(canonicalRequest, date, getScope(date, region)) signingKey := getSigningKey(secretKey, date, region) signature := getSignature(signingKey, stringToSign)