check if metadata headers/url values are equal with signed headers (#17737)

This commit is contained in:
ruspaul013 2023-07-27 21:44:56 +03:00 committed by GitHub
parent 14ebd82dbd
commit 535f97ba61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 2 deletions

View File

@ -260,3 +260,28 @@ func signV4TrimAll(input string) string {
// unicode.IsSpace() internally here) to one space and return
return strings.Join(strings.Fields(input), " ")
}
// checkMetaHeaders will check if the metadata from header/url is the same with the one from signed headers
func checkMetaHeaders(signedHeadersMap http.Header, r *http.Request) APIErrorCode {
// check values from http header
for k, val := range r.Header {
if stringsHasPrefixFold(k, "X-Amz-Meta-") {
if signedHeadersMap.Get(k) == val[0] {
continue
}
return ErrUnsignedHeaders
}
}
// check values from url, if no http header
for k, val := range r.Form {
if stringsHasPrefixFold(k, "x-amz-meta-") {
if signedHeadersMap.Get(http.CanonicalHeaderKey(k)) == val[0] {
continue
}
return ErrUnsignedHeaders
}
}
return ErrNone
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 MinIO, Inc.
// Copyright (c) 2015-2023 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
@ -339,3 +339,72 @@ func TestGetContentSha256Cksum(t *testing.T) {
}
}
}
// Test TestCheckMetaHeaders tests the logic of checkMetaHeaders() function
func TestCheckMetaHeaders(t *testing.T) {
signedHeadersMap := map[string][]string{
"X-Amz-Meta-Test": {"test"},
"X-Amz-Meta-Extension": {"png"},
"X-Amz-Meta-Name": {"imagepng"},
}
expectedMetaTest := "test"
expectedMetaExtension := "png"
expectedMetaName := "imagepng"
r, err := http.NewRequest(http.MethodPut, "http://play.min.io:9000", nil)
if err != nil {
t.Fatal("Unable to create http.Request :", err)
}
// Creating input http header.
inputHeader := r.Header
inputHeader.Set("X-Amz-Meta-Test", expectedMetaTest)
inputHeader.Set("X-Amz-Meta-Extension", expectedMetaExtension)
inputHeader.Set("X-Amz-Meta-Name", expectedMetaName)
// calling the function being tested.
errCode := checkMetaHeaders(signedHeadersMap, r)
if errCode != ErrNone {
t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrNone, errCode)
}
// Add new metadata in inputHeader
inputHeader.Set("X-Amz-Meta-Clone", "fail")
// calling the function being tested.
errCode = checkMetaHeaders(signedHeadersMap, r)
if errCode != ErrUnsignedHeaders {
t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrUnsignedHeaders, errCode)
}
// Delete extra metadata from header to don't affect other test
inputHeader.Del("X-Amz-Meta-Clone")
// calling the function being tested.
errCode = checkMetaHeaders(signedHeadersMap, r)
if errCode != ErrNone {
t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrNone, errCode)
}
// Creating input url values
r, err = http.NewRequest(http.MethodPut, "http://play.min.io:9000?x-amz-meta-test=test&x-amz-meta-extension=png&x-amz-meta-name=imagepng", nil)
if err != nil {
t.Fatal("Unable to create http.Request :", err)
}
r.ParseForm()
// calling the function being tested.
errCode = checkMetaHeaders(signedHeadersMap, r)
if errCode != ErrNone {
t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrNone, errCode)
}
// Add extra metadata in url values
r, err = http.NewRequest(http.MethodPut, "http://play.min.io:9000?x-amz-meta-test=test&x-amz-meta-extension=png&x-amz-meta-name=imagepng&x-amz-meta-clone=fail", nil)
if err != nil {
t.Fatal("Unable to create http.Request :", err)
}
r.ParseForm()
// calling the function being tested.
errCode = checkMetaHeaders(signedHeadersMap, r)
if errCode != ErrUnsignedHeaders {
t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrUnsignedHeaders, errCode)
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 MinIO, Inc.
// Copyright (c) 2015-2023 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
@ -229,6 +229,12 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
return errCode
}
// Check if the metadata headers are equal with signedheaders
errMetaCode := checkMetaHeaders(extractedSignedHeaders, r)
if errMetaCode != ErrNone {
return errMetaCode
}
// If the host which signed the request is slightly ahead in time (by less than globalMaxSkewTime) the
// request should still be allowed.
if pSignValues.Date.After(UTCNow().Add(globalMaxSkewTime)) {