Signature-V4: Include content-length for signature calculation. (#2643)

This is to be compatible with clients which includes content-length for signature calculation
(and hence deviating from AWS Signature-v4 spec)
This commit is contained in:
Krishna Srinivas 2016-09-09 22:08:07 +05:30 committed by Harshavardhana
parent a4afb312d4
commit 400e9309f1
3 changed files with 56 additions and 2 deletions

View file

@ -342,8 +342,21 @@ func doesSignatureMatch(hashedPayload string, r *http.Request, validateRegion bo
return ErrContentSHA256Mismatch
}
header := req.Header
// Signature-V4 spec excludes Content-Length from signed headers list for signature calculation.
// But some clients deviate from this rule. Hence we consider Content-Length for signature
// calculation to be compatible with such clients.
for _, h := range signV4Values.SignedHeaders {
if h == "content-length" {
header = cloneHeader(req.Header)
header.Add("content-length", strconv.FormatInt(r.ContentLength, 10))
break
}
}
// Extract all the signed headers along with its values.
extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, req.Header)
extractedSignedHeaders, errCode := extractSignedHeaders(signV4Values.SignedHeaders, header)
if errCode != ErrNone {
return errCode
}

View file

@ -21,6 +21,7 @@ import (
"encoding/xml"
"errors"
"io"
"net/http"
"os"
"os/exec"
"strings"
@ -30,6 +31,18 @@ import (
"github.com/pkg/profile"
)
// make a copy of http.Header
func cloneHeader(h http.Header) http.Header {
h2 := make(http.Header, len(h))
for k, vv := range h {
vv2 := make([]string, len(vv))
copy(vv2, vv)
h2[k] = vv2
}
return h2
}
// xmlDecoder provide decoded value in xml.
func xmlDecoder(body io.Reader, v interface{}, size int64) error {
var lbody io.Reader

View file

@ -16,7 +16,35 @@
package cmd
import "testing"
import (
"net/http"
"reflect"
"testing"
)
// Tests http.Header clone.
func TestCloneHeader(t *testing.T) {
headers := []http.Header{
http.Header{
"Content-Type": {"text/html; charset=UTF-8"},
"Content-Length": {"0"},
},
http.Header{
"Content-Length": {"0", "1", "2"},
},
http.Header{
"Expires": {"-1"},
"Content-Length": {"0"},
"Content-Encoding": {"gzip"},
},
}
for i, header := range headers {
clonedHeader := cloneHeader(header)
if !reflect.DeepEqual(header, clonedHeader) {
t.Errorf("Test %d failed", i+1)
}
}
}
// Tests maximum object size.
func TestMaxObjectSize(t *testing.T) {