• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From 620ea21410030a9977396b4661806bc187231b79 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Mon, 25 Apr 2022 16:24:33 +0200
4Subject: [PATCH] transfer: redirects to other protocols or ports clear auth
5
6... unless explicitly permitted.
7
8Bug: https://curl.se/docs/CVE-2022-27774.html
9Reported-by: Harry Sintonen
10Closes #8748
11---
12 lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
13 1 file changed, 48 insertions(+), 1 deletion(-)
14
15diff --git a/lib/transfer.c b/lib/transfer.c
16index 53ef0b03b8e0..315da876c4a8 100644
17--- a/lib/transfer.c
18+++ b/lib/transfer.c
19@@ -1611,10 +1611,57 @@ CURLcode Curl_follow(struct Curl_easy *data,
20       return CURLE_OUT_OF_MEMORY;
21   }
22   else {
23-
24     uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0);
25     if(uc)
26       return Curl_uc_to_curlcode(uc);
27+
28+    /* Clear auth if this redirects to a different port number or protocol,
29+       unless permitted */
30+    if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
31+      char *portnum;
32+      int port;
33+      bool clear = FALSE;
34+
35+      if(data->set.use_port && data->state.allow_port)
36+        /* a custom port is used */
37+        port = (int)data->set.use_port;
38+      else {
39+        uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
40+                          CURLU_DEFAULT_PORT);
41+        if(uc) {
42+          free(newurl);
43+          return Curl_uc_to_curlcode(uc);
44+        }
45+        port = atoi(portnum);
46+        free(portnum);
47+      }
48+      if(port != data->info.conn_remote_port) {
49+        infof(data, "Clear auth, redirects to port from %u to %u",
50+              data->info.conn_remote_port, port);
51+        clear = TRUE;
52+      }
53+      else {
54+        char *scheme;
55+        const struct Curl_handler *p;
56+        uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
57+        if(uc) {
58+          free(newurl);
59+          return Curl_uc_to_curlcode(uc);
60+        }
61+
62+        p = Curl_builtin_scheme(scheme);
63+        if(p && (p->protocol != data->info.conn_protocol)) {
64+          infof(data, "Clear auth, redirects scheme from %s to %s",
65+                data->info.conn_scheme, scheme);
66+          clear = TRUE;
67+        }
68+        free(scheme);
69+      }
70+      if(clear) {
71+        Curl_safefree(data->state.aptr.user);
72+        Curl_safefree(data->state.aptr.passwd);
73+      }
74+    }
75   }
76
77   if(type == FOLLOW_FAKE) {
78