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

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