Skip to content

Commit b9b0ab6

Browse files
jayptitSeb
authored andcommitted
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: [email protected] Ref: https://curl.se/docs/manpage.html#-H Fixes curl#11664 Closes curl#11668
1 parent 4c8eecf commit b9b0ab6

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

lib/http_aws_sigv4.c

+33-2
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,41 @@ static CURLcode make_headers(struct Curl_easy *data,
199199
head = tmp_head;
200200
}
201201

202+
/* copy user headers to our header list. the logic is based on how http.c
203+
handles user headers.
204+
205+
user headers in format 'name:' with no value are used to signal that an
206+
internal header of that name should be removed. those user headers are not
207+
added to this list.
208+
209+
user headers in format 'name;' with no value are used to signal that a
210+
header of that name with no value should be sent. those user headers are
211+
added to this list but in the format that they will be sent, ie the
212+
semi-colon is changed to a colon for format 'name:'.
213+
214+
user headers with a value of whitespace only, or without a colon or
215+
semi-colon, are not added to this list.
216+
*/
202217
for(l = data->set.headers; l; l = l->next) {
203-
tmp_head = curl_slist_append(head, l->data);
204-
if(!tmp_head)
218+
char *dupdata, *ptr;
219+
char *sep = strchr(l->data, ':');
220+
if(!sep)
221+
sep = strchr(l->data, ';');
222+
if(!sep || (*sep == ':' && !*(sep + 1)))
223+
continue;
224+
for(ptr = sep + 1; ISSPACE(*ptr); ++ptr)
225+
;
226+
if(!*ptr && ptr != sep + 1) /* a value of whitespace only */
227+
continue;
228+
dupdata = strdup(l->data);
229+
if(!dupdata)
205230
goto fail;
231+
dupdata[sep - l->data] = ':';
232+
tmp_head = Curl_slist_append_nodup(head, dupdata);
233+
if(!tmp_head) {
234+
free(dupdata);
235+
goto fail;
236+
}
206237
head = tmp_head;
207238
}
208239

tests/data/test1955

+3-2
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ http://exam.ple.com:9000/aws_sigv4/testapi/test exam.ple.com:9000:%HOSTIP:%HTTPP
6464
<protocol>
6565
GET /aws_sigv4/testapi/test HTTP/1.1
6666
Host: exam.ple.com:9000
67-
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
67+
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
6868
X-Xxx-Date: 19700101T000000Z
69-
test2: 1234
69+
test3: 1234
70+
test2:
7071
test_space: t s m end
7172
tesMixCase: MixCase
7273

tests/libtest/lib1955.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,30 @@ int test(char *URL)
4949
test_setopt(curl, CURLOPT_USERPWD, "xxx");
5050
test_setopt(curl, CURLOPT_HEADER, 0L);
5151
test_setopt(curl, CURLOPT_URL, URL);
52-
list = curl_slist_append(list, "test2: 1234");
52+
list = curl_slist_append(list, "test3: 1234");
5353
if(!list)
5454
goto test_cleanup;
5555
if(libtest_arg2) {
5656
connect_to = curl_slist_append(connect_to, libtest_arg2);
5757
}
5858
test_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
5959
curl_slist_append(list, "Content-Type: application/json");
60+
61+
/* 'name;' user headers with no value are used to send an empty header in the
62+
format 'name:' (note the semi-colon becomes a colon). this entry should
63+
show in SignedHeaders without an additional semi-colon, as any other
64+
header would. eg 'foo;test2;test3' and not 'foo;test2;;test3'. */
65+
curl_slist_append(list, "test2;");
66+
67+
/* 'name:' user headers with no value are used to signal an internal header
68+
of that name should be removed and are not sent as a header. this entry
69+
should not show in SignedHeaders. */
6070
curl_slist_append(list, "test1:");
71+
72+
/* 'name' user headers with no separator or value are invalid and ignored.
73+
this entry should not show in SignedHeaders. */
6174
curl_slist_append(list, "test0");
75+
6276
curl_slist_append(list, "test_space: t\ts m\t end ");
6377
curl_slist_append(list, "tesMixCase: MixCase");
6478
test_setopt(curl, CURLOPT_HTTPHEADER, list);

0 commit comments

Comments
 (0)