From 2f0ef2e9831c82c0038d0d85d434272291e0c502 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 11 Jun 2020 12:50:33 +0100 Subject: [PATCH] s3: fix v2 auth for multipart server side copy Before this change the v2 signer sorted the headers for signing as joined key:value pairs. However this put these two headers in the wrong order. x-amz-copy-source-range: x-amz-copy-source: This changes sorts on the keys before joining the values producing the correct sort order. x-amz-copy-source: x-amz-copy-source-range: This commit also adds some missing query parameters for signing that I spotted in the s3cmd source. --- backend/s3/v2sign.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/backend/s3/v2sign.go b/backend/s3/v2sign.go index d6e638431..8c69c7d1d 100644 --- a/backend/s3/v2sign.go +++ b/backend/s3/v2sign.go @@ -36,6 +36,11 @@ var s3ParamsToSign = map[string]struct{}{ "response-cache-control": {}, "response-content-disposition": {}, "response-content-encoding": {}, + "lifecycle": {}, + "website": {}, + "delete": {}, + "cors": {}, + "restore": {}, } // Warn once about empty endpoint @@ -73,7 +78,7 @@ func v2sign(opt *Options, req *http.Request) { // Look through headers of interest var md5 string var contentType string - var headersToSign []string + var headersToSign [][2]string // slice of key, value pairs for k, v := range req.Header { k = strings.ToLower(k) switch k { @@ -84,15 +89,26 @@ func v2sign(opt *Options, req *http.Request) { default: if strings.HasPrefix(k, "x-amz-") { vall := strings.Join(v, ",") - headersToSign = append(headersToSign, k+":"+vall) + headersToSign = append(headersToSign, [2]string{k, vall}) } } } // Make headers of interest into canonical string var joinedHeadersToSign string if len(headersToSign) > 0 { - sort.StringSlice(headersToSign).Sort() - joinedHeadersToSign = strings.Join(headersToSign, "\n") + "\n" + // sort by keys + sort.Slice(headersToSign, func(i, j int) bool { + return headersToSign[i][0] < headersToSign[j][0] + }) + // join into key:value\n + var out strings.Builder + for _, kv := range headersToSign { + out.WriteString(kv[0]) + out.WriteRune(':') + out.WriteString(kv[1]) + out.WriteRune('\n') + } + joinedHeadersToSign = out.String() } // Look for query parameters which need to be added to the signature