diff options
Diffstat (limited to 'backport-CVE-2024-11053-pre3.patch')
-rw-r--r-- | backport-CVE-2024-11053-pre3.patch | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/backport-CVE-2024-11053-pre3.patch b/backport-CVE-2024-11053-pre3.patch new file mode 100644 index 0000000..286a7f4 --- /dev/null +++ b/backport-CVE-2024-11053-pre3.patch @@ -0,0 +1,349 @@ +From 9bee39bfed2c413b4cc4eb306a57ac92a1854907 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Sat, 12 Oct 2024 23:54:39 +0200 +Subject: [PATCH] url: use same credentials on redirect + +Previously it could lose the username and only use the password. + +Added test 998 and 999 to verify. + +Reported-by: Tobias Bora +Fixes #15262 +Closes #15282 + +Conflict:context adapt +Reference:https://github.com/curl/curl/commit/9bee39bfed2c413b4cc4eb306a57ac92a1854907 +--- + lib/transfer.c | 3 + + lib/url.c | 19 ++++--- + lib/urldata.h | 9 ++- + tests/data/Makefile.inc | 14 +++++++------- + tests/data/test998 | 92 ++++++++++++++++++++++++++++++ + tests/data/test999 | 81 ++++++++++++++++++++++++++ + 6 files changed, 195 insertions(+), 11 deletions(-) + create mode 100644 tests/data/test998 + create mode 100644 tests/data/test999 + +diff --git a/lib/transfer.c b/lib/transfer.c +index 79d648cab..3a9239254 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -679,6 +679,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) + return CURLE_OUT_OF_MEMORY; + } + ++ if(data->set.str[STRING_USERNAME] || ++ data->set.str[STRING_PASSWORD]) ++ data->state.creds_from = CREDS_OPTION; + if(!result) + result = Curl_setstropt(&data->state.aptr.user, + data->set.str[STRING_USERNAME]); +diff --git a/lib/url.c b/lib/url.c +index 45745bc60..261f61d8d 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1860,10 +1860,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, + return result; + + /* +- * User name and password set with their own options override the +- * credentials possibly set in the URL. ++ * username and password set with their own options override the credentials ++ * possibly set in the URL, but netrc does not. + */ +- if(!data->set.str[STRING_PASSWORD]) { ++ if(!data->state.aptr.passwd || (data->state.creds_from != CREDS_OPTION)) { + uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0); + if(!uc) { + char *decoded; +@@ -1876,12 +1876,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, + result = Curl_setstropt(&data->state.aptr.passwd, decoded); + if(result) + return result; ++ data->state.creds_from = CREDS_URL; + } + else if(uc != CURLUE_NO_PASSWORD) + return Curl_uc_to_curlcode(uc); + } + +- if(!data->set.str[STRING_USERNAME]) { ++ if(!data->state.aptr.user || (data->state.creds_from != CREDS_OPTION)) { + /* we don't use the URL API's URL decoder option here since it rejects + control codes and we want to allow them for some schemes in the user + and password fields */ +@@ -1895,13 +1896,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, + return result; + conn->user = decoded; + result = Curl_setstropt(&data->state.aptr.user, decoded); ++ data->state.creds_from = CREDS_URL; + } + else if(uc != CURLUE_NO_USER) + return Curl_uc_to_curlcode(uc); +- else if(data->state.aptr.passwd) { +- /* no user was set but a password, set a blank user */ +- result = Curl_setstropt(&data->state.aptr.user, ""); +- } + if(result) + return result; + } +@@ -2685,7 +2683,8 @@ static CURLcode override_login(struct Curl_easy *data, + int ret; + bool url_provided = FALSE; + +- if(data->state.aptr.user) { ++ if(data->state.aptr.user && ++ (data->state.creds_from != CREDS_NETRC)) { + /* there was a user name in the URL. Use the URL decoded version */ + userp = &data->state.aptr.user; + url_provided = TRUE; +@@ -2733,6 +2732,7 @@ static CURLcode override_login(struct Curl_easy *data, + result = Curl_setstropt(&data->state.aptr.user, *userp); + if(result) + return result; ++ data->state.creds_from = CREDS_NETRC; + } + } + if(data->state.aptr.user) { +@@ -2750,6 +2750,7 @@ static CURLcode override_login(struct Curl_easy *data, + CURLcode result = Curl_setstropt(&data->state.aptr.passwd, *passwdp); + if(result) + return result; ++ data->state.creds_from = CREDS_NETRC; + } + if(data->state.aptr.passwd) { + uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, +diff --git a/lib/urldata.h b/lib/urldata.h +index 6aa26237d..73f662159 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1206,6 +1206,11 @@ struct urlpieces { + char *query; + }; + ++#define CREDS_NONE 0 ++#define CREDS_URL 1 /* from URL */ ++#define CREDS_OPTION 2 /* set with a CURLOPT_ */ ++#define CREDS_NETRC 3 /* found in netrc */ ++ + struct UrlState { + /* Points to the connection cache */ + struct conncache *conn_cache; +@@ -1344,7 +1349,6 @@ struct UrlState { + char *proxyuser; + char *proxypasswd; + } aptr; +- + unsigned char httpwant; /* when non-zero, a specific HTTP version requested + to be used in the library's request(s) */ + unsigned char httpversion; /* the lowest HTTP version*10 reported by any +@@ -1354,6 +1358,9 @@ struct UrlState { + unsigned char dselect_bits; /* != 0 -> bitmask of socket events for this + transfer overriding anything the socket may + report */ ++ unsigned int creds_from:2; /* where is the server credentials originating ++ from, see the CREDS_* defines above */ ++ + #ifdef CURLDEBUG + BIT(conncache_lock); + #endif +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 480a88208..02bf2ae25 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -133,7 +133,7 @@ test961 test962 test963 test964 test965 test966 test967 test968 test969 \ + test961 test962 test963 test964 test965 test966 test967 test968 test969 \ + test970 test971 test972 test973 test974 test975 test976 test977 test978 \ + test979 test980 test981 test982 test983 test984 test985 test986 test987 \ +-test988 test989 test990 test991 \ ++test988 test989 test990 test991 test998 test999 \ + \ + test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \ + test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \ +diff --git a/tests/data/test998 b/tests/data/test998 +new file mode 100644 +index 000000000..c3a8f5169 +--- /dev/null ++++ b/tests/data/test998 +@@ -0,0 +1,92 @@ ++<testcase> ++<info> ++<keywords> ++HTTP ++--location-trusted ++</keywords> ++</info> ++ ++# ++# Server-side ++<reply> ++<data> ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://somewhere.else.example/a/path/%TESTNUMBER0002 ++ ++</data> ++<data2> ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Content-Length: 6 ++Content-Type: text/html ++Funny-head: yesyes ++ ++-foo- ++</data2> ++ ++<datacheck> ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://somewhere.else.example/a/path/%TESTNUMBER0002 ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Content-Length: 6 ++Content-Type: text/html ++Funny-head: yesyes ++ ++-foo- ++</datacheck> ++ ++</reply> ++ ++# ++# Client-side ++<client> ++<features> ++proxy ++</features> ++<server> ++http ++</server> ++<name> ++HTTP with auth in URL redirected to another host ++</name> ++<command> ++-x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER --location-trusted ++</command> ++</client> ++ ++# ++# Verify data after the test has been "shot" ++<verify> ++<strip> ++QUIT ++</strip> ++<protocol> ++GET http://somwhere.example/998 HTTP/1.1
++Host: somwhere.example
++Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
++User-Agent: curl/%VERSION
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://somewhere.else.example/a/path/9980002 HTTP/1.1
++Host: somewhere.else.example
++Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
++User-Agent: curl/%VERSION
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++</protocol> ++</verify> ++</testcase> +diff --git a/tests/data/test999 b/tests/data/test999 +new file mode 100644 +index 000000000..990a8d09a +--- /dev/null ++++ b/tests/data/test999 +@@ -0,0 +1,81 @@ ++<testcase> ++<info> ++<keywords> ++HTTP ++--location-trusted ++</keywords> ++</info> ++ ++# ++# Server-side ++<reply> ++<data nocheck="yes"> ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Content-Length: 6 ++Content-Type: text/html ++Funny-head: yesyes ++ ++-foo- ++</data> ++ ++<datacheck> ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://somewhere.else.example/a/path/%TESTNUMBER0002 ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Content-Length: 6 ++Content-Type: text/html ++Funny-head: yesyes ++ ++-foo- ++</datacheck> ++ ++</reply> ++ ++# ++# Client-side ++<client> ++<features> ++proxy ++</features> ++<server> ++http ++</server> ++<name> ++HTTP with auth in first URL but not second ++</name> ++<command> ++-x %HOSTIP:%HTTPPORT http://alberto:einstein@somwhere.example/%TESTNUMBER http://somewhere.else.example/%TESTNUMBER ++</command> ++</client> ++ ++# ++# Verify data after the test has been "shot" ++<verify> ++<strip> ++QUIT ++</strip> ++<protocol> ++GET http://somwhere.example/%TESTNUMBER HTTP/1.1
++Host: somwhere.example
++Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
++User-Agent: curl/%VERSION
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://somewhere.else.example/%TESTNUMBER HTTP/1.1
++Host: somewhere.else.example
++User-Agent: curl/%VERSION
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++</protocol> ++</verify> ++</testcase> +-- +2.33.0 + |