-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Description
I did this
In lib/http_proxy.c, an incorrect comparison makes a header comparison fail.
This is the description from ZeroPath:
dynhds_add_custom parses header names by locating ':' and computing namelen as the number of characters before the colon (namelen excludes the colon). Later the code checks for Authorization: and Cookie: using hd_name_eq(name, namelen, STRCONST("Authorization:")) / STRCONST("Cookie:"). hd_name_eq first requires the two lengths to be equal before performing a case-insensitive compare. Because the constant includes the colon in its length but namelen excludes it, the length comparison fails and the intended suppression branch is skipped.
It can be confirmed with the following patch:
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 845ba2e8f..5ccd656bf 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -54,6 +54,19 @@ static bool hd_name_eq(const char *n1, size_t n1len,
return (n1len == n2len) ? curl_strnequal(n1, n2, n1len) : FALSE;
}
+/* DEBUG helper: show what we are comparing.
+ Only useful with -v since infof prints in verbose mode. */
+static void debug_hdrcmp(struct Curl_easy *data,
+ const char *name, size_t namelen,
+ const char *label,
+ const char *cstr, size_t clen)
+{
+ infof(data,
+ "DEBUG hdrcmp %-18s name='%.*s' len=%zu const='%s' len=%zu => %s",
+ label, (int)namelen, name, namelen, cstr, clen,
+ hd_name_eq(name, namelen, cstr, clen) ? "MATCH" : "NO MATCH");
+}
+
static CURLcode dynhds_add_custom(struct Curl_easy *data,
bool is_connect, int httpversion,
struct dynhds *hds)
@@ -143,6 +156,21 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data,
}
DEBUGASSERT(name && value);
+ /* Show comparisons so we can see why branches are or are not taken. */
+ if(data->set.verbose) {
+ debug_hdrcmp(data, name, namelen, "Host:",
+ STRCONST("Host:"));
+ debug_hdrcmp(data, name, namelen, "Content-Type:",
+ STRCONST("Content-Type:"));
+ debug_hdrcmp(data, name, namelen, "Content-Length:",
+ STRCONST("Content-Length:"));
+ debug_hdrcmp(data, name, namelen, "Transfer-Encoding:",
+ STRCONST("Transfer-Encoding:"));
+ debug_hdrcmp(data, name, namelen, "Authorization:",
+ STRCONST("Authorization:"));
+ debug_hdrcmp(data, name, namelen, "Cookie:",
+ STRCONST("Cookie:"));
+ }
if(data->state.aptr.host &&
/* a Host: header was sent already, do not pass on any custom Host:
header as that will produce *two* in the same request! */
...
$ ./src/curl -vkL --http1.1 --proxy http://127.0.0.1:8080 https://a.test:4443/ --resolve a.test:4443:127.0.0.1 --resolve b.test:4444:127.0.0.1 --cacert cert.pem --proxy-header 'Authorization: Bearer LEAK' --proxy-header 'Cookie: a=1'
* Added a.test:4443:127.0.0.1 to DNS cache
* Added b.test:4444:127.0.0.1 to DNS cache
* Trying 127.0.0.1:8080...
* CONNECT: no ALPN negotiated
* allocate connect buffer
* DEBUG hdrcmp Host: name='Authorization' len=13 const='Host:' len=5 => NO MATCH
* DEBUG hdrcmp Content-Type: name='Authorization' len=13 const='Content-Type:' len=13 => NO MATCH
* DEBUG hdrcmp Content-Length: name='Authorization' len=13 const='Content-Length:' len=15 => NO MATCH
* DEBUG hdrcmp Transfer-Encoding: name='Authorization' len=13 const='Transfer-Encoding:' len=18 => NO MATCH
* DEBUG hdrcmp Authorization: name='Authorization' len=13 const='Authorization:' len=14 => NO MATCH
* DEBUG hdrcmp Cookie: name='Authorization' len=13 const='Cookie:' len=7 => NO MATCH
* DEBUG hdrcmp Host: name='Cookie' len=6 const='Host:' len=5 => NO MATCH
* DEBUG hdrcmp Content-Type: name='Cookie' len=6 const='Content-Type:' len=13 => NO MATCH
* DEBUG hdrcmp Content-Length: name='Cookie' len=6 const='Content-Length:' len=15 => NO MATCH
* DEBUG hdrcmp Transfer-Encoding: name='Cookie' len=6 const='Transfer-Encoding:' len=18 => NO MATCH
* DEBUG hdrcmp Authorization: name='Cookie' len=6 const='Authorization:' len=14 => NO MATCH
* DEBUG hdrcmp Cookie: name='Cookie' len=6 const='Cookie:' len=7 => NO MATCH
Note the extra : in the latter part of the lines.
This bug was found with ZeroPath.
I expected the following
No response
curl/libcurl version
most recent
operating system
all