From afd77c029cbd0713ca11474d833b5e7ae5174071 Mon Sep 17 00:00:00 2001 From: itsHenry <2671230065@qq.com> Date: Sun, 7 Jul 2024 04:16:26 +0000 Subject: [PATCH] feat: support query-based requests --- signature/signature-v4-utils.go | 2 +- signature/signature-v4.go | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/signature/signature-v4-utils.go b/signature/signature-v4-utils.go index 92a0a685..6ed15f48 100644 --- a/signature/signature-v4-utils.go +++ b/signature/signature-v4-utils.go @@ -12,7 +12,7 @@ var ( // extractSignedHeaders extract signed headers from Authorization header func extractSignedHeaders(signedHeaders []string, r *http.Request) (http.Header, ErrorCode) { reqHeaders := r.Header - reqQueries := r.Form + reqQueries := r.URL.Query() // find whether "host" is part of list of signed headers. // if not return ErrUnsignedHeaders. "host" is mandatory. if !contains(signedHeaders, "host") { diff --git a/signature/signature-v4.go b/signature/signature-v4.go index 7f34eafd..5a2131bd 100644 --- a/signature/signature-v4.go +++ b/signature/signature-v4.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "crypto/subtle" "encoding/hex" + "fmt" "net/http" "sort" "strings" @@ -25,6 +26,11 @@ const ( headerDate = "Date" amzContentSha256 = "X-Amz-Content-Sha256" amzDate = "X-Amz-Date" + amzAlgorithm = "X-Amz-Algorithm" + amzCredential = "X-Amz-Credential" + amzSignedHeaders = "X-Amz-SignedHeaders" + amzSignature = "X-Amz-Signature" + amzexpires = "X-Amz-Expires" ) // getCanonicalHeaders generate a list of request headers with their values @@ -134,9 +140,17 @@ func V4SignVerify(r *http.Request) ErrorCode { // Copy request. req := *r hashedPayload := getContentSha256Cksum(r) + queryf := req.URL.Query() // Save authorization header. v4Auth := req.Header.Get(headerAuth) + if v4Auth == "" { + // try query based + v4Auth = fmt.Sprintf("%s Credential=%s,SignedHeaders=%s, Signature=%s", queryf.Get(amzAlgorithm), queryf.Get(amzCredential), queryf.Get(amzSignedHeaders), queryf.Get(amzSignature)) + if v4Auth == "" { + return errMissingCredTag + } + } // Parse signature version '4' header. signV4Values, Err := ParseSignV4(v4Auth) @@ -159,7 +173,9 @@ func V4SignVerify(r *http.Request) ErrorCode { var date string if date = req.Header.Get(amzDate); date == "" { if date = r.Header.Get(headerDate); date == "" { - return errMissingDateHeader + if date = queryf.Get(amzDate); date == "" { + return errMissingDateHeader + } } } @@ -170,10 +186,11 @@ func V4SignVerify(r *http.Request) ErrorCode { } // Query string. - queryStr := req.URL.RawQuery + queryf.Del(amzSignature) + rawquery := queryf.Encode() // Get canonical request. - canonicalRequest := getCanonicalRequest(extractedSignedHeaders, hashedPayload, queryStr, req.URL.Path, req.Method) + canonicalRequest := getCanonicalRequest(extractedSignedHeaders, hashedPayload, rawquery, req.URL.Path, req.Method) // Get string to sign from canonical request. stringToSign := getStringToSign(canonicalRequest, t, signV4Values.Credential.getScope()) @@ -186,7 +203,14 @@ func V4SignVerify(r *http.Request) ErrorCode { // Verify if signature match. if !compareSignatureV4(newSignature, signV4Values.Signature) { - return errSignatureDoesNotMatch + //try unsigned payload + hashedPayload = "UNSIGNED-PAYLOAD" + canonicalRequest = getCanonicalRequest(extractedSignedHeaders, hashedPayload, rawquery, req.URL.Path, req.Method) + stringToSign = getStringToSign(canonicalRequest, t, signV4Values.Credential.getScope()) + newSignature = getSignature(signingKey, stringToSign) + if !compareSignatureV4(newSignature, signV4Values.Signature) { + return errSignatureDoesNotMatch + } } // Return Error none.