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

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