]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http_aws_sigv4: handle no-value user header entries
authorJay Satiro <raysatiro@yahoo.com>
Sat, 12 Aug 2023 19:06:08 +0000 (15:06 -0400)
committerJay Satiro <raysatiro@yahoo.com>
Mon, 11 Sep 2023 19:24:05 +0000 (15:24 -0400)
- 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

lib/http_aws_sigv4.c
tests/data/test1955
tests/libtest/lib1955.c

index d934f17148a194a67253b341f02612f4aa52b8f4..f39d02ccedbee422626c0c1f2c4233f7647b3de3 100644 (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;
   }
 
index 342b7b703c1aaa877e4541b10c104aae0f75d341..27bb466c7590a23614926b3170b423ca593c4b4c 100644 (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\r
 Host: exam.ple.com:9000\r
-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\r
+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\r
 X-Xxx-Date: 19700101T000000Z\r
-test2: 1234\r
+test3: 1234\r
+test2:\r
 test_space: t  s  m       end    \r
 tesMixCase: MixCase\r
 \r
index d92582bd5e586e4d4364bd6fb4db45c12157016d..3328d7ef1ab0a9e5529ea0c9b56d8aba03505c6c 100644 (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);