http_aws_sigv4: handle no-value user header entries

- Handle user headers in format 'name:' and 'name;' with no value.

The former is used when the user wants to remove an internal libcurl
header and the latter is used when the user actually wants to send a
no-value header in the format 'name:' (note the semi-colon is converted
by libcurl to a colon).

Prior to this change the AWS header import code did not special case
either of those and the generated AWS SignedHeaders would be incorrect.

Reported-by: apparentorder@users.noreply.github.com

Ref: https://curl.se/docs/manpage.html#-H

Fixes https://github.com/curl/curl/issues/11664
Closes https://github.com/curl/curl/pull/11668
This commit is contained in:
Jay Satiro 2023-08-12 15:06:08 -04:00
parent 14108c1b80
commit b5c65f8b7b
3 changed files with 51 additions and 5 deletions

View File

@ -199,10 +199,41 @@ static CURLcode make_headers(struct Curl_easy *data,
head = tmp_head;
}
/* copy user headers to our header list. the logic is based on how http.c
handles user headers.
user headers in format 'name:' with no value are used to signal that an
internal header of that name should be removed. those user headers are not
added to this list.
user headers in format 'name;' with no value are used to signal that a
header of that name with no value should be sent. those user headers are
added to this list but in the format that they will be sent, ie the
semi-colon is changed to a colon for format 'name:'.
user headers with a value of whitespace only, or without a colon or
semi-colon, are not added to this list.
*/
for(l = data->set.headers; l; l = l->next) {
tmp_head = curl_slist_append(head, l->data);
if(!tmp_head)
char *dupdata, *ptr;
char *sep = strchr(l->data, ':');
if(!sep)
sep = strchr(l->data, ';');
if(!sep || (*sep == ':' && !*(sep + 1)))
continue;
for(ptr = sep + 1; ISSPACE(*ptr); ++ptr)
;
if(!*ptr && ptr != sep + 1) /* a value of whitespace only */
continue;
dupdata = strdup(l->data);
if(!dupdata)
goto fail;
dupdata[sep - l->data] = ':';
tmp_head = Curl_slist_append_nodup(head, dupdata);
if(!tmp_head) {
free(dupdata);
goto fail;
}
head = tmp_head;
}

View File

@ -64,9 +64,10 @@ http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPP
<protocol>
GET /aws_sigv4/testapi/test HTTP/1.1
Host: exam.ple.com:9000
Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;tesmixcase;test0;test1;test2;test_space;x-xxx-date, Signature=779a8ff876528aece8bf03b1296702af0644a4745aa5feabb6ebb1a7bb0d907e
Authorization: XXX4-HMAC-SHA256 Credential=xxx/19700101/ple/exam/xxx4_request, SignedHeaders=content-type;host;tesmixcase;test2;test3;test_space;x-xxx-date, Signature=dd39202e9fb7b836ebf2abb83b114cae11ff3b6a169f0c64b290a774a873db9d
X-Xxx-Date: 19700101T000000Z
test2: 1234
test3: 1234
test2:
test_space: t s m end
tesMixCase: MixCase

View File

@ -49,7 +49,7 @@ int test(char *URL)
test_setopt(curl, CURLOPT_USERPWD, "xxx");
test_setopt(curl, CURLOPT_HEADER, 0L);
test_setopt(curl, CURLOPT_URL, URL);
list = curl_slist_append(list, "test2: 1234");
list = curl_slist_append(list, "test3: 1234");
if(!list)
goto test_cleanup;
if(libtest_arg2) {
@ -57,8 +57,22 @@ int test(char *URL)
}
test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
curl_slist_append(list, "Content-Type: application/json");
/* 'name;' user headers with no value are used to send an empty header in the
format 'name:' (note the semi-colon becomes a colon). this entry should
show in SignedHeaders without an additional semi-colon, as any other
header would. eg 'foo;test2;test3' and not 'foo;test2;;test3'. */
curl_slist_append(list, "test2;");
/* 'name:' user headers with no value are used to signal an internal header
of that name should be removed and are not sent as a header. this entry
should not show in SignedHeaders. */
curl_slist_append(list, "test1:");
/* 'name' user headers with no separator or value are invalid and ignored.
this entry should not show in SignedHeaders. */
curl_slist_append(list, "test0");
curl_slist_append(list, "test_space: t\ts m\t end ");
curl_slist_append(list, "tesMixCase: MixCase");
test_setopt(curl, CURLOPT_HTTPHEADER, list);