Blame SOURCES/0037-curl-7.61.1-CVE-2022-27776.patch

34bc20
From 24ff6b126726201cf778038c332b3b921c7f5b2f Mon Sep 17 00:00:00 2001
34bc20
From: Katsuhiko YOSHIDA <claddvd@gmail.com>
34bc20
Date: Sun, 30 Dec 2018 09:44:30 +0900
34bc20
Subject: [PATCH 1/6] cookies: skip custom cookies when redirecting cross-site
34bc20
34bc20
Closes #3417
34bc20
34bc20
Upstream-commit: 1f30dc886d1a4a6e81599a9f5f5e9f60d97801d4
34bc20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
34bc20
---
34bc20
 docs/libcurl/opts/CURLOPT_HTTPHEADER.3 |  4 ++
34bc20
 lib/http.c                             |  3 +-
34bc20
 tests/data/Makefile.inc                |  2 +-
34bc20
 tests/data/test330                     | 90 ++++++++++++++++++++++++++
34bc20
 4 files changed, 97 insertions(+), 2 deletions(-)
34bc20
 create mode 100644 tests/data/test330
34bc20
34bc20
diff --git a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
34bc20
index f5826e1..4af69f4 100644
34bc20
--- a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
34bc20
+++ b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
34bc20
@@ -88,6 +88,10 @@ those servers will get all the contents of your custom headers too.
34bc20
 Starting in 7.58.0, libcurl will specifically prevent "Authorization:" headers
34bc20
 from being sent to other hosts than the first used one, unless specifically
34bc20
 permitted with the \fICURLOPT_UNRESTRICTED_AUTH(3)\fP option.
34bc20
+
34bc20
+Starting in 7.64.0, libcurl will specifically prevent "Cookie:" headers
34bc20
+from being sent to other hosts than the first used one, unless specifically
34bc20
+permitted with the \fICURLOPT_UNRESTRICTED_AUTH(3)\fP option.
34bc20
 .SH DEFAULT
34bc20
 NULL
34bc20
 .SH PROTOCOLS
34bc20
diff --git a/lib/http.c b/lib/http.c
34bc20
index bf19077..0b5e476 100644
34bc20
--- a/lib/http.c
34bc20
+++ b/lib/http.c
34bc20
@@ -1774,7 +1774,8 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
34bc20
                   checkprefix("Transfer-Encoding:", headers->data))
34bc20
             /* HTTP/2 doesn't support chunked requests */
34bc20
             ;
34bc20
-          else if(checkprefix("Authorization:", headers->data) &&
34bc20
+          else if((checkprefix("Authorization:", headers->data) ||
34bc20
+                   checkprefix("Cookie:", headers->data)) &&
34bc20
                   /* be careful of sending this potentially sensitive header to
34bc20
                      other hosts */
34bc20
                   (data->state.this_is_a_follow &&
34bc20
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
34bc20
index e0f1ef4..77e85fd 100644
34bc20
--- a/tests/data/Makefile.inc
34bc20
+++ b/tests/data/Makefile.inc
34bc20
@@ -56,7 +56,7 @@ test289 test290 test291 test292 test293 test294 test295 test296 test297 \
34bc20
 test298 test299 test300 test301 test302 test303 test304 test305 test306 \
34bc20
 test307 test308 test309 test310 test311 test312 test313 test314 test315 \
34bc20
 test316 test317 test318 test319 test320 test321 test322 test323 test324 \
34bc20
-test325 test326 \
34bc20
+test325 test326 test330 \
34bc20
 \
34bc20
 test340 \
34bc20
 \
34bc20
diff --git a/tests/data/test330 b/tests/data/test330
34bc20
new file mode 100644
34bc20
index 0000000..74607d5
34bc20
--- /dev/null
34bc20
+++ b/tests/data/test330
34bc20
@@ -0,0 +1,90 @@
34bc20
+<testcase>
34bc20
+<info>
34bc20
+<keywords>
34bc20
+HTTP
34bc20
+followlocation
34bc20
+cookies
34bc20
+</keywords>
34bc20
+</info>
34bc20
+#
34bc20
+# Server-side
34bc20
+<reply>
34bc20
+<data>
34bc20
+HTTP/1.1 302 OK
34bc20
+Date: Thu, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake swsclose
34bc20
+Content-Type: text/html
34bc20
+Funny-head: yesyes
34bc20
+Location: http://goto.second.host.now/3170002
34bc20
+Content-Length: 8
34bc20
+Connection: close
34bc20
+
34bc20
+contents
34bc20
+</data>
34bc20
+<data2>
34bc20
+HTTP/1.1 200 OK
34bc20
+Date: Thu, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake swsclose
34bc20
+Content-Type: text/html
34bc20
+Funny-head: yesyes
34bc20
+Content-Length: 9
34bc20
+
34bc20
+contents
34bc20
+</data2>
34bc20
+
34bc20
+<datacheck>
34bc20
+HTTP/1.1 302 OK
34bc20
+Date: Thu, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake swsclose
34bc20
+Content-Type: text/html
34bc20
+Funny-head: yesyes
34bc20
+Location: http://goto.second.host.now/3170002
34bc20
+Content-Length: 8
34bc20
+Connection: close
34bc20
+
34bc20
+HTTP/1.1 200 OK
34bc20
+Date: Thu, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake swsclose
34bc20
+Content-Type: text/html
34bc20
+Funny-head: yesyes
34bc20
+Content-Length: 9
34bc20
+
34bc20
+contents
34bc20
+</datacheck>
34bc20
+</reply>
34bc20
+
34bc20
+#
34bc20
+# Client-side
34bc20
+<client>
34bc20
+<server>
34bc20
+http
34bc20
+</server>
34bc20
+ <name>
34bc20
+HTTP with custom Cookie: and redirect to new host
34bc20
+ </name>
34bc20
+ <command>
34bc20
+http://first.host.it.is/we/want/that/page/317 -x %HOSTIP:%HTTPPORT -H "Cookie: test=yes" --location
34bc20
+</command>
34bc20
+</client>
34bc20
+
34bc20
+#
34bc20
+# Verify data after the test has been "shot"
34bc20
+<verify>
34bc20
+<strip>
34bc20
+^User-Agent:.*
34bc20
+</strip>
34bc20
+<protocol>
34bc20
+GET http://first.host.it.is/we/want/that/page/317 HTTP/1.1
34bc20
+Host: first.host.it.is
34bc20
+Accept: */*
34bc20
+Proxy-Connection: Keep-Alive
34bc20
+Cookie: test=yes
34bc20
+
34bc20
+GET http://goto.second.host.now/3170002 HTTP/1.1
34bc20
+Host: goto.second.host.now
34bc20
+Accept: */*
34bc20
+Proxy-Connection: Keep-Alive
34bc20
+
34bc20
+</protocol>
34bc20
+</verify>
34bc20
+</testcase>
34bc20
-- 
34bc20
2.34.1
34bc20
34bc20
34bc20
From a3f3855c8bf3a39ef0d86ef04087c200bca765f1 Mon Sep 17 00:00:00 2001
34bc20
From: Daniel Stenberg <daniel@haxx.se>
34bc20
Date: Thu, 19 Dec 2019 16:45:53 +0100
34bc20
Subject: [PATCH 2/6] sws: search for "Testno:" header uncondtionally if no
34bc20
 testno
34bc20
34bc20
Even if the initial request line wasn't found. With the fix to 1455, the
34bc20
test number is now detected correctly.
34bc20
34bc20
(Problem found when running tests in random order.)
34bc20
34bc20
Closes #4744
34bc20
34bc20
Upstream-commit: 25b69c482f45c7acd817920bd8fdf68887be51a2
34bc20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
34bc20
---
34bc20
 tests/data/test1455 |  3 ++-
34bc20
 tests/server/sws.c  | 40 +++++++++++++++++++++++-----------------
34bc20
 2 files changed, 25 insertions(+), 18 deletions(-)
34bc20
34bc20
diff --git a/tests/data/test1455 b/tests/data/test1455
34bc20
index 0b77dc4..25f742e 100644
34bc20
--- a/tests/data/test1455
34bc20
+++ b/tests/data/test1455
34bc20
@@ -35,7 +35,7 @@ http
34bc20
 HTTP GET when PROXY Protocol enabled
34bc20
 </name>
34bc20
 <command>
34bc20
-http://%HOSTIP:%HTTPPORT/1455 --haproxy-protocol
34bc20
+http://%HOSTIP:%HTTPPORT/1455 --haproxy-protocol -H "Testno: 1455"
34bc20
 </command>
34bc20
 </client>
34bc20
 
34bc20
@@ -53,6 +53,7 @@ proxy-line
34bc20
 GET /1455 HTTP/1.1
34bc20
 Host: %HOSTIP:%HTTPPORT
34bc20
 Accept: */*
34bc20
+Testno: 1455
34bc20
 
34bc20
 </protocol>
34bc20
 </verify>
34bc20
diff --git a/tests/server/sws.c b/tests/server/sws.c
34bc20
index fbe7761..4ece830 100644
34bc20
--- a/tests/server/sws.c
34bc20
+++ b/tests/server/sws.c
34bc20
@@ -367,6 +367,8 @@ static int parse_servercmd(struct httprequest *req)
34bc20
 
34bc20
   filename = test2file(req->testno);
34bc20
   req->close = FALSE;
34bc20
+  req->connmon = FALSE;
34bc20
+
34bc20
   stream = fopen(filename, "rb");
34bc20
   if(!stream) {
34bc20
     error = errno;
34bc20
@@ -391,8 +393,6 @@ static int parse_servercmd(struct httprequest *req)
34bc20
       return 1; /* done */
34bc20
     }
34bc20
 
34bc20
-    req->connmon = FALSE;
34bc20
-
34bc20
     cmd = orgcmd;
34bc20
     while(cmd && cmdsize) {
34bc20
       char *check;
34bc20
@@ -548,12 +548,11 @@ static int ProcessRequest(struct httprequest *req)
34bc20
         snprintf(logbuf, sizeof(logbuf), "Requested test number %ld part %ld",
34bc20
                  req->testno, req->partno);
34bc20
         logmsg("%s", logbuf);
34bc20
-
34bc20
-        /* find and parse <servercmd> for this test */
34bc20
-        parse_servercmd(req);
34bc20
       }
34bc20
-      else
34bc20
+      else {
34bc20
+        logmsg("No test number");
34bc20
         req->testno = DOCNUMBER_NOTHING;
34bc20
+      }
34bc20
 
34bc20
     }
34bc20
 
34bc20
@@ -613,14 +612,6 @@ static int ProcessRequest(struct httprequest *req)
34bc20
       }
34bc20
     }
34bc20
 
34bc20
-    if(req->testno == DOCNUMBER_NOTHING) {
34bc20
-      /* check for a Testno: header with the test case number */
34bc20
-      char *testno = strstr(line, "\nTestno: ");
34bc20
-      if(testno) {
34bc20
-        req->testno = strtol(&testno[9], NULL, 10);
34bc20
-        logmsg("Found test number %d in Testno: header!", req->testno);
34bc20
-      }
34bc20
-    }
34bc20
     if(req->testno == DOCNUMBER_NOTHING) {
34bc20
       /* Still no test case number. Try to get the the number off the last dot
34bc20
          instead, IE we consider the TLD to be the test number. Test 123 can
34bc20
@@ -661,8 +652,8 @@ static int ProcessRequest(struct httprequest *req)
34bc20
     }
34bc20
   }
34bc20
   else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) {
34bc20
-    logmsg("** Unusual request. Starts with %02x %02x %02x",
34bc20
-           line[0], line[1], line[2]);
34bc20
+    logmsg("** Unusual request. Starts with %02x %02x %02x (%c%c%c)",
34bc20
+           line[0], line[1], line[2], line[0], line[1], line[2]);
34bc20
   }
34bc20
 
34bc20
   if(!end) {
34bc20
@@ -670,7 +661,22 @@ static int ProcessRequest(struct httprequest *req)
34bc20
     logmsg("request not complete yet");
34bc20
     return 0; /* not complete yet */
34bc20
   }
34bc20
-  logmsg("- request found to be complete");
34bc20
+  logmsg("- request found to be complete (%d)", req->testno);
34bc20
+
34bc20
+  if(req->testno == DOCNUMBER_NOTHING) {
34bc20
+    /* check for a Testno: header with the test case number */
34bc20
+    char *testno = strstr(line, "\nTestno: ");
34bc20
+    if(testno) {
34bc20
+      req->testno = strtol(&testno[9], NULL, 10);
34bc20
+      logmsg("Found test number %d in Testno: header!", req->testno);
34bc20
+    }
34bc20
+    else {
34bc20
+      logmsg("No Testno: header");
34bc20
+    }
34bc20
+  }
34bc20
+
34bc20
+  /* find and parse <servercmd> for this test */
34bc20
+  parse_servercmd(req);
34bc20
 
34bc20
   if(use_gopher) {
34bc20
     /* when using gopher we cannot check the request until the entire
34bc20
-- 
34bc20
2.34.1
34bc20
34bc20
34bc20
From 3772ea764c05a1cf37b96c091ae266138e8a2867 Mon Sep 17 00:00:00 2001
34bc20
From: Daniel Stenberg <daniel@haxx.se>
34bc20
Date: Thu, 16 Apr 2020 14:16:22 +0200
34bc20
Subject: [PATCH 3/6] runtests: always put test number in servercmd file
34bc20
34bc20
Upstream-commit: d1a2816b4128faa8ebc50ce93285c7364652856e
34bc20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
34bc20
---
34bc20
 tests/runtests.pl | 10 +++-------
34bc20
 1 file changed, 3 insertions(+), 7 deletions(-)
34bc20
34bc20
diff --git a/tests/runtests.pl b/tests/runtests.pl
34bc20
index a0fd991..8d8ed81 100755
34bc20
--- a/tests/runtests.pl
34bc20
+++ b/tests/runtests.pl
34bc20
@@ -3878,10 +3878,9 @@ sub singletest {
34bc20
     unlink($SERVER2IN);
34bc20
     unlink($PROXYIN);
34bc20
 
34bc20
-    if(@ftpservercmd) {
34bc20
-        # write the instructions to file
34bc20
-        writearray($FTPDCMD, \@ftpservercmd);
34bc20
-    }
34bc20
+    push @ftpservercmd, "Testnum $testnum\n";
34bc20
+    # write the instructions to file
34bc20
+    writearray($FTPDCMD, \@ftpservercmd);
34bc20
 
34bc20
     # get the command line options to use
34bc20
     my @blaha;
34bc20
@@ -4222,9 +4221,6 @@ sub singletest {
34bc20
         }
34bc20
     }
34bc20
 
34bc20
-    # remove the test server commands file after each test
34bc20
-    unlink($FTPDCMD) if(-f $FTPDCMD);
34bc20
-
34bc20
     # run the postcheck command
34bc20
     my @postcheck= getpart("client", "postcheck");
34bc20
     if(@postcheck) {
34bc20
-- 
34bc20
2.34.1
34bc20
34bc20
34bc20
From ac04f6feaa19c636aa09a1b50643d70a77be4465 Mon Sep 17 00:00:00 2001
34bc20
From: Daniel Stenberg <daniel@haxx.se>
34bc20
Date: Thu, 14 May 2020 17:45:40 +0200
34bc20
Subject: [PATCH 4/6] sws: as last resort, get test number from server cmd file
34bc20
34bc20
If it can't be found in the request. Also support --cmdfile to set it to
34bc20
a custom file name.
34bc20
34bc20
runtests.pl always writes this file with the test number in it since a
34bc20
while back.
34bc20
34bc20
Upstream-commit: a3b0699d5c110270f09ac51b5b465ca8753b35a9
34bc20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
34bc20
---
34bc20
 tests/server/sws.c | 68 ++++++++++++++++++++++++++++++++++------------
34bc20
 1 file changed, 51 insertions(+), 17 deletions(-)
34bc20
34bc20
diff --git a/tests/server/sws.c b/tests/server/sws.c
34bc20
index 4ece830..2696872 100644
34bc20
--- a/tests/server/sws.c
34bc20
+++ b/tests/server/sws.c
34bc20
@@ -155,6 +155,10 @@ const char *serverlogfile = DEFAULT_LOGFILE;
34bc20
 #define REQUEST_PROXY_DUMP  "log/proxy.input"
34bc20
 #define RESPONSE_PROXY_DUMP "log/proxy.response"
34bc20
 
34bc20
+/* file in which additional instructions may be found */
34bc20
+#define DEFAULT_CMDFILE "log/ftpserver.cmd"
34bc20
+const char *cmdfile = DEFAULT_CMDFILE;
34bc20
+
34bc20
 /* very-big-path support */
34bc20
 #define MAXDOCNAMELEN 140000
34bc20
 #define MAXDOCNAMELEN_TXT "139999"
34bc20
@@ -358,6 +362,24 @@ static bool socket_domain_is_ip(void)
34bc20
   }
34bc20
 }
34bc20
 
34bc20
+/* parse the file on disk that might have a test number for us */
34bc20
+static int parse_cmdfile(struct httprequest *req)
34bc20
+{
34bc20
+  int testnum = DOCNUMBER_NOTHING;
34bc20
+  char buf[256];
34bc20
+  FILE *f = fopen(cmdfile, FOPEN_READTEXT);
34bc20
+  if(f) {
34bc20
+    while(fgets(buf, sizeof(buf), f)) {
34bc20
+      if(1 == sscanf(buf, "Testnum %d", &testnum)) {
34bc20
+        logmsg("[%s] cmdfile says testnum %d", cmdfile, testnum);
34bc20
+        req->testno = testnum;
34bc20
+      }
34bc20
+    }
34bc20
+    fclose(f);
34bc20
+  }
34bc20
+  return 0;
34bc20
+}
34bc20
+
34bc20
 /* based on the testno, parse the correct server commands */
34bc20
 static int parse_servercmd(struct httprequest *req)
34bc20
 {
34bc20
@@ -622,34 +644,41 @@ static int ProcessRequest(struct httprequest *req)
34bc20
 
34bc20
       /* get the number after it */
34bc20
       if(ptr) {
34bc20
+        long num;
34bc20
         ptr++; /* skip the dot */
34bc20
 
34bc20
-        req->testno = strtol(ptr, &ptr, 10);
34bc20
+        num = strtol(ptr, &ptr, 10);
34bc20
 
34bc20
-        if(req->testno > 10000) {
34bc20
-          req->partno = req->testno % 10000;
34bc20
-          req->testno /= 10000;
34bc20
+        if(num) {
34bc20
+          req->testno = num;
34bc20
+          if(req->testno > 10000) {
34bc20
+            req->partno = req->testno % 10000;
34bc20
+            req->testno /= 10000;
34bc20
 
34bc20
-          logmsg("found test %d in requested host name", req->testno);
34bc20
+            logmsg("found test %d in requested host name", req->testno);
34bc20
 
34bc20
+          }
34bc20
+          else
34bc20
+            req->partno = 0;
34bc20
         }
34bc20
-        else
34bc20
-          req->partno = 0;
34bc20
 
34bc20
-        snprintf(logbuf, sizeof(logbuf),
34bc20
-                 "Requested test number %ld part %ld (from host name)",
34bc20
+        if(req->testno != DOCNUMBER_NOTHING) {
34bc20
+          logmsg("Requested test number %ld part %ld (from host name)",
34bc20
                  req->testno, req->partno);
34bc20
-        logmsg("%s", logbuf);
34bc20
-
34bc20
+        }
34bc20
       }
34bc20
+    }
34bc20
 
34bc20
-      if(!req->testno) {
34bc20
-        logmsg("Did not find test number in PATH");
34bc20
-        req->testno = DOCNUMBER_404;
34bc20
-      }
34bc20
-      else
34bc20
-        parse_servercmd(req);
34bc20
+    if(req->testno == DOCNUMBER_NOTHING)
34bc20
+      /* might get the test number */
34bc20
+      parse_cmdfile(req);
34bc20
+
34bc20
+    if(req->testno == DOCNUMBER_NOTHING) {
34bc20
+      logmsg("Did not find test number in PATH");
34bc20
+      req->testno = DOCNUMBER_404;
34bc20
     }
34bc20
+    else
34bc20
+      parse_servercmd(req);
34bc20
   }
34bc20
   else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) {
34bc20
     logmsg("** Unusual request. Starts with %02x %02x %02x (%c%c%c)",
34bc20
@@ -2038,6 +2067,11 @@ int main(int argc, char *argv[])
34bc20
       if(argc>arg)
34bc20
         serverlogfile = argv[arg++];
34bc20
     }
34bc20
+    else if(!strcmp("--cmdfile", argv[arg])) {
34bc20
+      arg++;
34bc20
+      if(argc>arg)
34bc20
+        cmdfile = argv[arg++];
34bc20
+    }
34bc20
     else if(!strcmp("--gopher", argv[arg])) {
34bc20
       arg++;
34bc20
       use_gopher = TRUE;
34bc20
-- 
34bc20
2.34.1
34bc20
34bc20
34bc20
From 9fa56a1e3ae7feff14668d8abd892fa028a9f32e Mon Sep 17 00:00:00 2001
34bc20
From: Daniel Stenberg <daniel@haxx.se>
34bc20
Date: Mon, 25 Apr 2022 13:05:40 +0200
34bc20
Subject: [PATCH 5/6] http: avoid auth/cookie on redirects same host diff port
34bc20
34bc20
CVE-2022-27776
34bc20
34bc20
Reported-by: Harry Sintonen
34bc20
Bug: https://curl.se/docs/CVE-2022-27776.html
34bc20
Closes #8749
34bc20
34bc20
Upstream-commit: 6e659993952aa5f90f48864be84a1bbb047fc258
34bc20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
34bc20
---
34bc20
 lib/http.c    | 33 +++++++++++++++++++++------------
34bc20
 lib/urldata.h | 16 +++++++++-------
34bc20
 2 files changed, 30 insertions(+), 19 deletions(-)
34bc20
34bc20
diff --git a/lib/http.c b/lib/http.c
34bc20
index 0b5e476..39fc7aa 100644
34bc20
--- a/lib/http.c
34bc20
+++ b/lib/http.c
34bc20
@@ -688,6 +688,21 @@ output_auth_headers(struct connectdata *conn,
34bc20
   return CURLE_OK;
34bc20
 }
34bc20
 
34bc20
+/*
34bc20
+ * allow_auth_to_host() tells if autentication, cookies or other "sensitive
34bc20
+ * data" can (still) be sent to this host.
34bc20
+ */
34bc20
+static bool allow_auth_to_host(struct connectdata *conn)
34bc20
+{
34bc20
+  struct Curl_easy *data = conn->data;
34bc20
+  return (!data->state.this_is_a_follow ||
34bc20
+          data->set.allow_auth_to_other_hosts ||
34bc20
+          (data->state.first_host &&
34bc20
+           strcasecompare(data->state.first_host, conn->host.name) &&
34bc20
+           (data->state.first_remote_port == conn->remote_port) &&
34bc20
+           (data->state.first_remote_protocol == conn->handler->protocol)));
34bc20
+}
34bc20
+
34bc20
 /**
34bc20
  * Curl_http_output_auth() setups the authentication headers for the
34bc20
  * host/proxy and the correct authentication
34bc20
@@ -756,15 +771,11 @@ Curl_http_output_auth(struct connectdata *conn,
34bc20
        with it */
34bc20
     authproxy->done = TRUE;
34bc20
 
34bc20
-  /* To prevent the user+password to get sent to other than the original
34bc20
-     host due to a location-follow, we do some weirdo checks here */
34bc20
-  if(!data->state.this_is_a_follow ||
34bc20
-     conn->bits.netrc ||
34bc20
-     !data->state.first_host ||
34bc20
-     data->set.allow_auth_to_other_hosts ||
34bc20
-     strcasecompare(data->state.first_host, conn->host.name)) {
34bc20
+  /* To prevent the user+password to get sent to other than the original host
34bc20
+     due to a location-follow */
34bc20
+  if(allow_auth_to_host(conn)
34bc20
+     || conn->bits.netrc)
34bc20
     result = output_auth_headers(conn, authhost, request, path, FALSE);
34bc20
-  }
34bc20
   else
34bc20
     authhost->done = TRUE;
34bc20
 
34bc20
@@ -1778,10 +1789,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
34bc20
                    checkprefix("Cookie:", headers->data)) &&
34bc20
                   /* be careful of sending this potentially sensitive header to
34bc20
                      other hosts */
34bc20
-                  (data->state.this_is_a_follow &&
34bc20
-                   data->state.first_host &&
34bc20
-                   !data->set.allow_auth_to_other_hosts &&
34bc20
-                   !strcasecompare(data->state.first_host, conn->host.name)))
34bc20
+                  !allow_auth_to_host(conn))
34bc20
             ;
34bc20
           else {
34bc20
             result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
34bc20
@@ -1937,6 +1945,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
34bc20
       return CURLE_OUT_OF_MEMORY;
34bc20
 
34bc20
     data->state.first_remote_port = conn->remote_port;
34bc20
+    data->state.first_remote_protocol = conn->handler->protocol;
34bc20
   }
34bc20
   http->writebytecount = http->readbytecount = 0;
34bc20
 
34bc20
diff --git a/lib/urldata.h b/lib/urldata.h
34bc20
index d3b971c..4bb0a84 100644
34bc20
--- a/lib/urldata.h
34bc20
+++ b/lib/urldata.h
34bc20
@@ -1231,13 +1231,15 @@ struct UrlState {
34bc20
                                 bytes / second */
34bc20
   bool this_is_a_follow; /* this is a followed Location: request */
34bc20
   bool refused_stream; /* this was refused, try again */
34bc20
-  char *first_host; /* host name of the first (not followed) request.
34bc20
-                       if set, this should be the host name that we will
34bc20
-                       sent authorization to, no else. Used to make Location:
34bc20
-                       following not keep sending user+password... This is
34bc20
-                       strdup() data.
34bc20
-                    */
34bc20
-  int first_remote_port; /* remote port of the first (not followed) request */
34bc20
+
34bc20
+  /* host name, port number and protocol of the first (not followed) request.
34bc20
+     if set, this should be the host name that we will sent authorization to,
34bc20
+     no else. Used to make Location: following not keep sending user+password.
34bc20
+     This is strdup()ed data. */
34bc20
+  char *first_host;
34bc20
+  int first_remote_port;
34bc20
+  unsigned int first_remote_protocol;
34bc20
+
34bc20
   struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
34bc20
   long sessionage;                  /* number of the most recent session */
34bc20
   unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
34bc20
-- 
34bc20
2.34.1
34bc20
34bc20
34bc20
From a8bb1e37e22788abaca37c59cf447d690fdcdfa4 Mon Sep 17 00:00:00 2001
34bc20
From: Daniel Stenberg <daniel@haxx.se>
34bc20
Date: Mon, 25 Apr 2022 13:05:47 +0200
34bc20
Subject: [PATCH 6/6] test898: verify the fix for CVE-2022-27776
34bc20
34bc20
Do not pass on Authorization headers on redirects to another port
34bc20
34bc20
Upstream-commit: afe752e0504ab60bf63787ede0b992cbe1065f78
34bc20
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
34bc20
---
34bc20
 tests/data/Makefile.inc |  2 +-
34bc20
 tests/data/test898      | 91 +++++++++++++++++++++++++++++++++++++++++
34bc20
 2 files changed, 92 insertions(+), 1 deletion(-)
34bc20
 create mode 100644 tests/data/test898
34bc20
34bc20
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
34bc20
index 77e85fd..58c9e31 100644
34bc20
--- a/tests/data/Makefile.inc
34bc20
+++ b/tests/data/Makefile.inc
34bc20
@@ -99,7 +99,7 @@ test850 test851 test852 test853 test854 test855 test856 test857 test858 \
34bc20
 test859 test860 test861 test862 test863 test864 test865 test866 test867 \
34bc20
 test868 test869 test870 test871 test872 test873 test874 test875 test876 \
34bc20
 test877 test878 test879 test880 test881 test882 test883 test884 test885 \
34bc20
-test886 test887 test888 test889 test890 test891 \
34bc20
+test886 test887 test888 test889 test890 test891 test898 \
34bc20
 \
34bc20
 test900 test901 test902 test903 test904 test905 test906 test907 test908 \
34bc20
 test909 test910 test911 test912 test913 test914 test915 test916 test917 \
34bc20
diff --git a/tests/data/test898 b/tests/data/test898
34bc20
new file mode 100644
34bc20
index 0000000..e295c26
34bc20
--- /dev/null
34bc20
+++ b/tests/data/test898
34bc20
@@ -0,0 +1,91 @@
34bc20
+<testcase>
34bc20
+<info>
34bc20
+<keywords>
34bc20
+HTTP
34bc20
+--location
34bc20
+Authorization
34bc20
+Cookie
34bc20
+</keywords>
34bc20
+</info>
34bc20
+
34bc20
+#
34bc20
+# Server-side
34bc20
+<reply>
34bc20
+<data>
34bc20
+HTTP/1.1 301 redirect
34bc20
+Date: Tue, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake
34bc20
+Content-Length: 0
34bc20
+Connection: close
34bc20
+Content-Type: text/html
34bc20
+Location: http://firsthost.com:9999/a/path/8980002
34bc20
+
34bc20
+</data>
34bc20
+<data2>
34bc20
+HTTP/1.1 200 OK
34bc20
+Date: Tue, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake
34bc20
+Content-Length: 4
34bc20
+Connection: close
34bc20
+Content-Type: text/html
34bc20
+
34bc20
+hey
34bc20
+</data2>
34bc20
+
34bc20
+<datacheck>
34bc20
+HTTP/1.1 301 redirect
34bc20
+Date: Tue, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake
34bc20
+Content-Length: 0
34bc20
+Connection: close
34bc20
+Content-Type: text/html
34bc20
+Location: http://firsthost.com:9999/a/path/8980002
34bc20
+
34bc20
+HTTP/1.1 200 OK
34bc20
+Date: Tue, 09 Nov 2010 14:49:00 GMT
34bc20
+Server: test-server/fake
34bc20
+Content-Length: 4
34bc20
+Connection: close
34bc20
+Content-Type: text/html
34bc20
+
34bc20
+hey
34bc20
+</datacheck>
34bc20
+
34bc20
+</reply>
34bc20
+
34bc20
+#
34bc20
+# Client-side
34bc20
+<client>
34bc20
+<server>
34bc20
+http
34bc20
+</server>
34bc20
+ <name>
34bc20
+HTTP with custom auth and cookies redirected to HTTP on a diff port
34bc20
+ </name>
34bc20
+ <command>
34bc20
+-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -H "Authorization: Basic am9lOnNlY3JldA==" -H "Cookie: userpwd=am9lOnNlY3JldA=="
34bc20
+</command>
34bc20
+</client>
34bc20
+
34bc20
+#
34bc20
+# Verify data after the test has been "shot"
34bc20
+<verify>
34bc20
+<strip>
34bc20
+^User-Agent:.*
34bc20
+</strip>
34bc20
+<protocol>
34bc20
+GET http://firsthost.com/ HTTP/1.1
34bc20
+Host: firsthost.com
34bc20
+Accept: */*
34bc20
+Proxy-Connection: Keep-Alive
34bc20
+Authorization: Basic am9lOnNlY3JldA==
34bc20
+Cookie: userpwd=am9lOnNlY3JldA==
34bc20
+
34bc20
+GET http://firsthost.com:9999/a/path/8980002 HTTP/1.1
34bc20
+Host: firsthost.com:9999
34bc20
+Accept: */*
34bc20
+Proxy-Connection: Keep-Alive
34bc20
+
34bc20
+</protocol>
34bc20
+</verify>
34bc20
+</testcase>
34bc20
-- 
34bc20
2.34.1
34bc20