diff --git a/cmd/signature-v4-utils.go b/cmd/signature-v4-utils.go index bb5c5887d..47834cd3d 100644 --- a/cmd/signature-v4-utils.go +++ b/cmd/signature-v4-utils.go @@ -107,7 +107,8 @@ func getURLEncodedName(name string) string { } // extractSignedHeaders extract signed headers from Authorization header -func extractSignedHeaders(signedHeaders []string, reqHeaders http.Header) (http.Header, APIErrorCode) { +func extractSignedHeaders(signedHeaders []string, r *http.Request) (http.Header, APIErrorCode) { + reqHeaders := r.Header // find whether "host" is part of list of signed headers. // if not return ErrUnsignedHeaders. "host" is mandatory. if !contains(signedHeaders, "host") { @@ -145,6 +146,10 @@ func extractSignedHeaders(signedHeaders []string, reqHeaders http.Header) (http. if header == "host" { continue } + if header == "transfer-encoding" { + extractedSignedHeaders[header] = r.TransferEncoding + continue + } // If not found continue, we will stop here. return nil, ErrUnsignedHeaders } diff --git a/cmd/signature-v4-utils_test.go b/cmd/signature-v4-utils_test.go index a844a63a9..830d040cd 100644 --- a/cmd/signature-v4-utils_test.go +++ b/cmd/signature-v4-utils_test.go @@ -132,7 +132,7 @@ func TestGetURLEncodedName(t *testing.T) { // TestExtractSignedHeaders - Tests validate extraction of signed headers using list of signed header keys. func TestExtractSignedHeaders(t *testing.T) { - signedHeaders := []string{"host", "x-amz-content-sha256", "x-amz-date"} + signedHeaders := []string{"host", "x-amz-content-sha256", "x-amz-date", "transfer-encoding"} // If the `expect` key exists in the signed headers then golang server would have stripped out the value, expecting the `expect` header set to `100-continue` in the result. signedHeaders = append(signedHeaders, "expect") @@ -140,14 +140,21 @@ func TestExtractSignedHeaders(t *testing.T) { expectedHost := "play.minio.io:9000" expectedContentSha256 := "1234abcd" expectedTime := UTCNow().Format(iso8601Format) + expectedTransferEncoding := "gzip" + + r, err := http.NewRequest("GET", "http://localhost", nil) + if err != nil { + t.Fatal("Unable to create http.Request :", err) + } + r.TransferEncoding = []string{expectedTransferEncoding} // Creating input http header. - inputHeader := make(http.Header) + inputHeader := r.Header inputHeader.Set(signedHeaders[0], expectedHost) inputHeader.Set(signedHeaders[1], expectedContentSha256) inputHeader.Set(signedHeaders[2], expectedTime) // calling the function being tested. - extractedSignedHeaders, errCode := extractSignedHeaders(signedHeaders, inputHeader) + extractedSignedHeaders, errCode := extractSignedHeaders(signedHeaders, r) if errCode != ErrNone { t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrNone, errCode) } @@ -160,6 +167,9 @@ func TestExtractSignedHeaders(t *testing.T) { extractedDate := extractedSignedHeaders[signedHeaders[2]] // extracted `expect` header. extractedExpect := extractedSignedHeaders["expect"][0] + + extractedTransferEncoding := extractedSignedHeaders["transfer-encoding"][0] + if expectedHost != extractedHost[0] { t.Errorf("host header mismatch: expected `%s`, got `%s`", expectedHost, extractedHost) } @@ -170,6 +180,9 @@ func TestExtractSignedHeaders(t *testing.T) { if expectedTime != extractedDate[0] { t.Errorf("x-amz-date header mismatch: expected `%s`, got `%s`", expectedTime, extractedDate) } + if extractedTransferEncoding != expectedTransferEncoding { + t.Errorf("transfer-encoding mismatch: expected %s, got %s", expectedTransferEncoding, extractedTransferEncoding) + } // Since the list of signed headers value contained `expect`, the default value of `100-continue` will be added to extracted signed headers. if extractedExpect != "100-continue" { @@ -179,7 +192,7 @@ func TestExtractSignedHeaders(t *testing.T) { // case where the headers doesn't contain the one of the signed header in the signed headers list. signedHeaders = append(signedHeaders, " X-Amz-Credential") // expected to fail with `ErrUnsignedHeaders`. - _, errCode = extractSignedHeaders(signedHeaders, inputHeader) + _, errCode = extractSignedHeaders(signedHeaders, r) if errCode != ErrUnsignedHeaders { t.Fatalf("Expected the APIErrorCode to %d, but got %d", ErrUnsignedHeaders, errCode) } @@ -187,7 +200,7 @@ func TestExtractSignedHeaders(t *testing.T) { // case where the list of signed headers doesn't contain the host field. signedHeaders = signedHeaders[1:] // expected to fail with `ErrUnsignedHeaders`. - _, errCode = extractSignedHeaders(signedHeaders, inputHeader) + _, errCode = extractSignedHeaders(signedHeaders, r) if errCode != ErrUnsignedHeaders { t.Fatalf("Expected the APIErrorCode to %d, but got %d", ErrUnsignedHeaders, errCode) } diff --git a/cmd/signature-v4.go b/cmd/signature-v4.go index 7abc98829..59acce0f6 100644 --- a/cmd/signature-v4.go +++ b/cmd/signature-v4.go @@ -235,7 +235,7 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s } // Extract all the signed headers along with its values. - extractedSignedHeaders, errCode := extractSignedHeaders(pSignValues.SignedHeaders, req.Header) + extractedSignedHeaders, errCode := extractSignedHeaders(pSignValues.SignedHeaders, r) if errCode != ErrNone { return errCode } @@ -360,7 +360,7 @@ func doesSignatureMatch(hashedPayload string, r *http.Request, region string) AP } // Extract all the signed headers along with its values. - extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, header) + extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, r) if errCode != ErrNone { return errCode } diff --git a/cmd/streaming-signature-v4.go b/cmd/streaming-signature-v4.go index 4fc4eca21..cbbf515c8 100644 --- a/cmd/streaming-signature-v4.go +++ b/cmd/streaming-signature-v4.go @@ -97,7 +97,7 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time, } // Extract all the signed headers along with its values. - extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, req.Header) + extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, r) if errCode != ErrNone { return "", time.Time{}, errCode }