Skip to content

Commit

Permalink
fix: allow spaces in Authorization string
Browse files Browse the repository at this point in the history
This change removes all spaces after the algorithm to have
standard parsing for the following key/value pairs. This fixes
some clients that were using a slightly different format than
the example AWS request strings.
  • Loading branch information
benmcclelland committed Jan 17, 2024
1 parent 17bdc58 commit b5894dd
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 4 deletions.
22 changes: 18 additions & 4 deletions s3api/utils/auth-reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"os"
"strings"
"time"
"unicode"

"github.com/aws/aws-sdk-go-v2/aws"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
Expand Down Expand Up @@ -173,18 +174,20 @@ func ParseAuthorization(authorization string) (AuthData, error) {
// authorization must start with:
// Authorization: <ALGORITHM>
// followed by key=value pairs separated by ","
authParts := strings.Fields(authorization)
authParts := strings.SplitN(authorization, " ", 2)
for i, el := range authParts {
authParts[i] = strings.TrimSpace(el)
if strings.Contains(el, " ") {
authParts[i] = removeSpace(el)
}
}

if len(authParts) < 3 {
if len(authParts) < 2 {
return a, s3err.GetAPIError(s3err.ErrMissingFields)
}

algo := authParts[0]

kvData := strings.Join(authParts[1:], "")
kvData := authParts[1]
kvPairs := strings.Split(kvData, ",")
// we are expecting at least Credential, SignedHeaders, and Signature
// key value pairs here
Expand Down Expand Up @@ -244,6 +247,17 @@ func ParseAuthorization(authorization string) (AuthData, error) {
}, nil
}

func removeSpace(str string) string {
var b strings.Builder
b.Grow(len(str))
for _, ch := range str {
if !unicode.IsSpace(ch) {
b.WriteRune(ch)
}
}
return b.String()
}

var (
specialValues = map[string]bool{
"UNSIGNED-PAYLOAD": true,
Expand Down
40 changes: 40 additions & 0 deletions s3api/utils/auth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package utils

import (
"testing"
)

func TestAuthParse(t *testing.T) {
vectors := []struct {
name string // name of test string
authstr string // Authorization string
algo string
sig string
}{{
name: "restic",
authstr: "AWS4-HMAC-SHA256 Credential=user/20240116/us-east-1/s3/aws4_request,SignedHeaders=content-md5;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length,Signature=d5199fc7f3aa35dd3d400427be2ae4c98bfad390785280cbb9eea015b51e12ac",
algo: "AWS4-HMAC-SHA256",
sig: "d5199fc7f3aa35dd3d400427be2ae4c98bfad390785280cbb9eea015b51e12ac",
},
{
name: "aws eaxample",
authstr: "AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, SignedHeaders=host;range;x-amz-date, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024",
algo: "AWS4-HMAC-SHA256",
sig: "fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024",
}}

for _, v := range vectors {
t.Run(v.name, func(t *testing.T) {
data, err := ParseAuthorization(v.authstr)
if err != nil {
t.Fatal(err)
}
if data.Algorithm != v.algo {
t.Errorf("algo got %v, expected %v", data.Algorithm, v.algo)
}
if data.Signature != v.sig {
t.Errorf("signature got %v, expected %v", data.Signature, v.sig)
}
})
}
}

0 comments on commit b5894dd

Please sign in to comment.