Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Trim extra spaces in signed header values for creating canonical #1065

Merged
merged 1 commit into from Jan 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion functional_tests.go
Expand Up @@ -653,7 +653,8 @@ func testPutObjectWithMetadata() {
customContentType := "custom/contenttype"

args["metadata"] = map[string][]string{
"Content-Type": {customContentType},
"Content-Type": {customContentType},
"X-Amz-Meta-CustomKey": {"extra spaces in value"},
}

n, err := c.PutObject(bucketName, objectName, reader, int64(bufSize), minio.PutObjectOptions{
Expand Down
2 changes: 1 addition & 1 deletion pkg/s3signer/request-signature-v4.go
Expand Up @@ -151,7 +151,7 @@ func getCanonicalHeaders(req http.Request, ignoredHeaders map[string]bool) strin
if idx > 0 {
buf.WriteByte(',')
}
buf.WriteString(v)
buf.WriteString(signV4TrimAll(v))
}
buf.WriteByte('\n')
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/s3signer/utils.go
Expand Up @@ -21,6 +21,7 @@ import (
"crypto/hmac"
"crypto/sha256"
"net/http"
"strings"
)

// unsignedPayload - value to be set to X-Amz-Content-Sha256 header when
Expand All @@ -47,3 +48,11 @@ func getHostAddr(req *http.Request) string {
}
return req.URL.Host
}

// Trim leading and trailing spaces and replace sequential spaces with one space, following Trimall()
// in http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
func signV4TrimAll(input string) string {
// Compress adjacent spaces (a space is determined by
// unicode.IsSpace() internally here) to one space and return
return strings.Join(strings.Fields(input), " ")
}
29 changes: 29 additions & 0 deletions pkg/s3signer/utils_test.go
Expand Up @@ -84,3 +84,32 @@ func TestEncodeURL2Path(t *testing.T) {
}

}

// TestSignV4TrimAll - tests the logic of TrimAll() function
func TestSignV4TrimAll(t *testing.T) {
testCases := []struct {
// Input.
inputStr string
// Expected result.
result string
}{
{"本語", "本語"},
{" abc ", "abc"},
{" a b ", "a b"},
{"a b ", "a b"},
{"a b", "a b"},
{"a b", "a b"},
{" a b c ", "a b c"},
{"a \t b c ", "a b c"},
{"\"a \t b c ", "\"a b c"},
{" \t\n\u000b\r\fa \t\n\u000b\r\f b \t\n\u000b\r\f c \t\n\u000b\r\f", "a b c"},
}

// Tests generated values from url encoded name.
for i, testCase := range testCases {
result := signV4TrimAll(testCase.inputStr)
if testCase.result != result {
t.Errorf("Test %d: Expected signV4TrimAll result to be \"%s\", but found it to be \"%s\" instead", i+1, testCase.result, result)
}
}
}