mirror of
https://github.com/curl/curl.git
synced 2025-02-23 15:10:03 +08:00
aws_sigv4: fix canon order for headers with same prefix
If a request containing two headers that have equivalent prefixes (ex. "x-amz-meta-test:test" and "x-amz-meta-test-two:test2") AWS expects the header with the shorter name to come first. The previous implementation used `strcmp` on the full header. Using the example, this would result in a comparison between the ':' and '-' chars and sort "x-amz-meta-test-two" before "x-amz-meta-test", which produces a different "StringToSign" than the one calculated by AWS. Test 1976 verifies Closes #14370
This commit is contained in:
parent
f3e07e5c55
commit
cf3e3d93d1
@ -129,6 +129,37 @@ static void trim_headers(struct curl_slist *head)
|
||||
/* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */
|
||||
#define DATE_FULL_HDR_LEN (DATE_HDR_KEY_LEN + TIMESTAMP_SIZE + 1)
|
||||
|
||||
/* alphabetically compare two headers by their name, expecting
|
||||
headers to use ':' at this point */
|
||||
static int compare_header_names(const char *a, const char *b)
|
||||
{
|
||||
const char *colon_a;
|
||||
const char *colon_b;
|
||||
size_t len_a;
|
||||
size_t len_b;
|
||||
size_t min_len;
|
||||
int cmp;
|
||||
|
||||
colon_a = strchr(a, ':');
|
||||
colon_b = strchr(b, ':');
|
||||
|
||||
DEBUGASSERT(colon_a);
|
||||
DEBUGASSERT(colon_b);
|
||||
|
||||
len_a = colon_a ? (size_t)(colon_a - a) : strlen(a);
|
||||
len_b = colon_b ? (size_t)(colon_b - b) : strlen(b);
|
||||
|
||||
min_len = (len_a < len_b) ? len_a : len_b;
|
||||
|
||||
cmp = strncmp(a, b, min_len);
|
||||
|
||||
/* return the shorter of the two if one is shorter */
|
||||
if(!cmp)
|
||||
return (int)(len_a - len_b);
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
/* timestamp should point to a buffer of at last TIMESTAMP_SIZE bytes */
|
||||
static CURLcode make_headers(struct Curl_easy *data,
|
||||
const char *hostname,
|
||||
@ -267,13 +298,13 @@ static CURLcode make_headers(struct Curl_easy *data,
|
||||
*date_header = NULL;
|
||||
}
|
||||
|
||||
/* alpha-sort in a case sensitive manner */
|
||||
/* alpha-sort by header name in a case sensitive manner */
|
||||
do {
|
||||
again = 0;
|
||||
for(l = head; l; l = l->next) {
|
||||
struct curl_slist *next = l->next;
|
||||
|
||||
if(next && strcmp(l->data, next->data) > 0) {
|
||||
if(next && compare_header_names(l->data, next->data) > 0) {
|
||||
char *tmp = l->data;
|
||||
|
||||
l->data = next->data;
|
||||
|
@ -233,7 +233,7 @@ test1916 test1917 test1918 test1919 \
|
||||
test1933 test1934 test1935 test1936 test1937 test1938 test1939 test1940 \
|
||||
test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \
|
||||
test1955 test1956 test1957 test1958 test1959 test1960 test1964 \
|
||||
test1970 test1971 test1972 test1973 test1974 test1975 \
|
||||
test1970 test1971 test1972 test1973 test1974 test1975 test1976 \
|
||||
\
|
||||
test2000 test2001 test2002 test2003 test2004 \
|
||||
\
|
||||
|
60
tests/data/test1976
Normal file
60
tests/data/test1976
Normal file
@ -0,0 +1,60 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
CURLOPT_AWS_SIGV4
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 200 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake
|
||||
Content-Length: 0
|
||||
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
SSL
|
||||
Debug
|
||||
crypto
|
||||
</features>
|
||||
<name>
|
||||
HTTP AWS_SIGV4 canonical request header sorting test
|
||||
</name>
|
||||
<command>
|
||||
-X PUT -H "X-Amz-Meta-Test-Two: test2" -H "x-amz-meta-test: test" --aws-sigv4 "aws:amz:us-east-1:s3" -u "xxx:yyy" http://%HOSTIP:%HTTPPORT/%TESTNUMBER
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
^Content-Length:.*
|
||||
^Accept:.*
|
||||
</strip>
|
||||
<strippart>
|
||||
# Strip the actual signature. We only care about header order in this test
|
||||
s/Signature=[a-f0-9]{64}/Signature=stripped/
|
||||
</strippart>
|
||||
<protocol crlf="yes">
|
||||
PUT /%TESTNUMBER HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Authorization: AWS4-HMAC-SHA256 Credential=xxx/19700101/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-meta-test;x-amz-meta-test-two, Signature=stripped
|
||||
X-Amz-Date: 19700101T000000Z
|
||||
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
X-Amz-Meta-Test-Two: test2
|
||||
x-amz-meta-test: test
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
Loading…
Reference in New Issue
Block a user