From 531c0747a3ec8803d52a96f53b64c0823f72a7a0 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 15 Feb 2023 14:51:53 +0100 Subject: [PATCH 01/29] share HSTS between handles Resolves: CVE-2023-23915 - HSTS amnesia with --parallel Resolves: CVE-2023-23914 - HSTS ignored on multiple requests --- 0006-curl-7.87.0-hsts-CVEs.patch | 575 +++++++++++++++++++++++++++++++ curl.spec | 9 +- 2 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 0006-curl-7.87.0-hsts-CVEs.patch diff --git a/0006-curl-7.87.0-hsts-CVEs.patch b/0006-curl-7.87.0-hsts-CVEs.patch new file mode 100644 index 0000000..759ece8 --- /dev/null +++ b/0006-curl-7.87.0-hsts-CVEs.patch @@ -0,0 +1,575 @@ +From 117fce3d4fe11c36a20403cd4d6850e5b8771b41 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:20 +0100 +Subject: [PATCH 1/5] share: add sharing of HSTS cache among handles + +Closes #10138 + +Upstream-commit: 076a2f629119222aeeb50f5a03bf9f9052fabb9a +Signed-off-by: Kamil Dudka +--- + docs/libcurl/opts/CURLSHOPT_SHARE.3 | 4 +++ + docs/libcurl/symbols-in-versions | 1 + + include/curl/curl.h | 1 + + lib/hsts.c | 15 +++++++++ + lib/hsts.h | 2 ++ + lib/setopt.c | 48 ++++++++++++++++++++++++----- + lib/share.c | 32 +++++++++++++++++-- + lib/share.h | 6 +++- + lib/transfer.c | 3 ++ + lib/url.c | 6 +++- + lib/urldata.h | 2 ++ + 11 files changed, 109 insertions(+), 11 deletions(-) + +diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3 +index 92783b6..b15af82 100644 +--- a/docs/libcurl/opts/CURLSHOPT_SHARE.3 ++++ b/docs/libcurl/opts/CURLSHOPT_SHARE.3 +@@ -79,6 +79,10 @@ Added in 7.61.0. + + Note that when you use the multi interface, all easy handles added to the same + multi handle will share PSL cache by default without using this option. ++.IP CURL_LOCK_DATA_HSTS ++The in-memory HSTS cache. ++ ++Added in 7.88.0 + .SH PROTOCOLS + All + .SH EXAMPLE +diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions +index 5ee245d..41fffc3 100644 +--- a/docs/libcurl/symbols-in-versions ++++ b/docs/libcurl/symbols-in-versions +@@ -73,6 +73,7 @@ CURL_LOCK_ACCESS_SINGLE 7.10.3 + CURL_LOCK_DATA_CONNECT 7.10.3 + CURL_LOCK_DATA_COOKIE 7.10.3 + CURL_LOCK_DATA_DNS 7.10.3 ++CURL_LOCK_DATA_HSTS 7.88.0 + CURL_LOCK_DATA_NONE 7.10.3 + CURL_LOCK_DATA_PSL 7.61.0 + CURL_LOCK_DATA_SHARE 7.10.4 +diff --git a/include/curl/curl.h b/include/curl/curl.h +index 139df99..5758e3b 100644 +--- a/include/curl/curl.h ++++ b/include/curl/curl.h +@@ -2953,6 +2953,7 @@ typedef enum { + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, ++ CURL_LOCK_DATA_HSTS, + CURL_LOCK_DATA_LAST + } curl_lock_data; + +diff --git a/lib/hsts.c b/lib/hsts.c +index c449120..339237b 100644 +--- a/lib/hsts.c ++++ b/lib/hsts.c +@@ -39,6 +39,7 @@ + #include "parsedate.h" + #include "fopen.h" + #include "rename.h" ++#include "share.h" + + /* The last 3 #include files should be in this order */ + #include "curl_printf.h" +@@ -551,4 +552,18 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) + return CURLE_OK; + } + ++void Curl_hsts_loadfiles(struct Curl_easy *data) ++{ ++ struct curl_slist *l = data->set.hstslist; ++ if(l) { ++ Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE); ++ ++ while(l) { ++ (void)Curl_hsts_loadfile(data, data->hsts, l->data); ++ l = l->next; ++ } ++ Curl_share_unlock(data, CURL_LOCK_DATA_HSTS); ++ } ++} ++ + #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ +diff --git a/lib/hsts.h b/lib/hsts.h +index 0e36a77..3da7574 100644 +--- a/lib/hsts.h ++++ b/lib/hsts.h +@@ -59,9 +59,11 @@ CURLcode Curl_hsts_loadfile(struct Curl_easy *data, + struct hsts *h, const char *file); + CURLcode Curl_hsts_loadcb(struct Curl_easy *data, + struct hsts *h); ++void Curl_hsts_loadfiles(struct Curl_easy *data); + #else + #define Curl_hsts_cleanup(x) + #define Curl_hsts_loadcb(x,y) CURLE_OK + #define Curl_hsts_save(x,y,z) ++#define Curl_hsts_loadfiles(x) + #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ + #endif /* HEADER_CURL_HSTS_H */ +diff --git a/lib/setopt.c b/lib/setopt.c +index b77e95b..f71a606 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2260,9 +2260,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + data->cookies = NULL; + #endif + ++#ifndef CURL_DISABLE_HSTS ++ if(data->share->hsts == data->hsts) ++ data->hsts = NULL; ++#endif ++#ifdef USE_SSL + if(data->share->sslsession == data->state.session) + data->state.session = NULL; +- ++#endif + #ifdef USE_LIBPSL + if(data->psl == &data->share->psl) + data->psl = data->multi? &data->multi->psl: NULL; +@@ -2296,10 +2301,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + data->cookies = data->share->cookies; + } + #endif /* CURL_DISABLE_HTTP */ ++#ifndef CURL_DISABLE_HSTS ++ if(data->share->hsts) { ++ /* first free the private one if any */ ++ Curl_hsts_cleanup(&data->hsts); ++ data->hsts = data->share->hsts; ++ } ++#endif /* CURL_DISABLE_HTTP */ ++#ifdef USE_SSL + if(data->share->sslsession) { + data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->state.session = data->share->sslsession; + } ++#endif + #ifdef USE_LIBPSL + if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) + data->psl = &data->share->psl; +@@ -3049,19 +3063,39 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + case CURLOPT_HSTSWRITEDATA: + data->set.hsts_write_userp = va_arg(param, void *); + break; +- case CURLOPT_HSTS: ++ case CURLOPT_HSTS: { ++ struct curl_slist *h; + if(!data->hsts) { + data->hsts = Curl_hsts_init(); + if(!data->hsts) + return CURLE_OUT_OF_MEMORY; + } + argptr = va_arg(param, char *); +- result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr); +- if(result) +- return result; +- if(argptr) +- (void)Curl_hsts_loadfile(data, data->hsts, argptr); ++ if(argptr) { ++ result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr); ++ if(result) ++ return result; ++ /* this needs to build a list of file names to read from, so that it can ++ read them later, as we might get a shared HSTS handle to load them ++ into */ ++ h = curl_slist_append(data->set.hstslist, argptr); ++ if(!h) { ++ curl_slist_free_all(data->set.hstslist); ++ data->set.hstslist = NULL; ++ return CURLE_OUT_OF_MEMORY; ++ } ++ data->set.hstslist = h; /* store the list for later use */ ++ } ++ else { ++ /* clear the list of HSTS files */ ++ curl_slist_free_all(data->set.hstslist); ++ data->set.hstslist = NULL; ++ if(!data->share || !data->share->hsts) ++ /* throw away the HSTS cache unless shared */ ++ Curl_hsts_cleanup(&data->hsts); ++ } + break; ++ } + case CURLOPT_HSTS_CTRL: + arg = va_arg(param, long); + if(arg & CURLHSTS_ENABLE) { +diff --git a/lib/share.c b/lib/share.c +index 1a083e7..69ee00b 100644 +--- a/lib/share.c ++++ b/lib/share.c +@@ -29,9 +29,11 @@ + #include "share.h" + #include "psl.h" + #include "vtls/vtls.h" +-#include "curl_memory.h" ++#include "hsts.h" + +-/* The last #include file should be: */ ++/* The last 3 #include files should be in this order */ ++#include "curl_printf.h" ++#include "curl_memory.h" + #include "memdebug.h" + + struct Curl_share * +@@ -89,6 +91,18 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) + #endif + break; + ++ case CURL_LOCK_DATA_HSTS: ++#ifndef CURL_DISABLE_HSTS ++ if(!share->hsts) { ++ share->hsts = Curl_hsts_init(); ++ if(!share->hsts) ++ res = CURLSHE_NOMEM; ++ } ++#else /* CURL_DISABLE_HSTS */ ++ res = CURLSHE_NOT_BUILT_IN; ++#endif ++ break; ++ + case CURL_LOCK_DATA_SSL_SESSION: + #ifdef USE_SSL + if(!share->sslsession) { +@@ -141,6 +155,16 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) + #endif + break; + ++ case CURL_LOCK_DATA_HSTS: ++#ifndef CURL_DISABLE_HSTS ++ if(share->hsts) { ++ Curl_hsts_cleanup(&share->hsts); ++ } ++#else /* CURL_DISABLE_HSTS */ ++ res = CURLSHE_NOT_BUILT_IN; ++#endif ++ break; ++ + case CURL_LOCK_DATA_SSL_SESSION: + #ifdef USE_SSL + Curl_safefree(share->sslsession); +@@ -207,6 +231,10 @@ curl_share_cleanup(struct Curl_share *share) + Curl_cookie_cleanup(share->cookies); + #endif + ++#ifndef CURL_DISABLE_HSTS ++ Curl_hsts_cleanup(&share->hsts); ++#endif ++ + #ifdef USE_SSL + if(share->sslsession) { + size_t i; +diff --git a/lib/share.h b/lib/share.h +index 32be416..2449730 100644 +--- a/lib/share.h ++++ b/lib/share.h +@@ -59,10 +59,14 @@ struct Curl_share { + #ifdef USE_LIBPSL + struct PslCache psl; + #endif +- ++#ifndef CURL_DISABLE_HSTS ++ struct hsts *hsts; ++#endif ++#ifdef USE_SSL + struct Curl_ssl_session *sslsession; + size_t max_ssl_sessions; + long sessionage; ++#endif + }; + + CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, +diff --git a/lib/transfer.c b/lib/transfer.c +index ba0410f..d433117 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1398,6 +1398,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) + if(data->state.resolve) + result = Curl_loadhostpairs(data); + ++ /* If there is a list of hsts files to read */ ++ Curl_hsts_loadfiles(data); ++ + if(!result) { + /* Allow data->set.use_port to set which port to use. This needs to be + * disabled for example when we follow Location: headers to URLs using +diff --git a/lib/url.c b/lib/url.c +index 3ab63a0..831ae06 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -434,7 +434,11 @@ CURLcode Curl_close(struct Curl_easy **datap) + Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]); + Curl_altsvc_cleanup(&data->asi); + Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]); +- Curl_hsts_cleanup(&data->hsts); ++#ifndef CURL_DISABLE_HSTS ++ if(!data->share || !data->share->hsts) ++ Curl_hsts_cleanup(&data->hsts); ++ curl_slist_free_all(data->set.hstslist); /* clean up list */ ++#endif + #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) + Curl_http_auth_cleanup_digest(data); + #endif +diff --git a/lib/urldata.h b/lib/urldata.h +index 3d7545c..5b4b34f 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1662,6 +1662,8 @@ struct UserDefined { + + void *seek_client; /* pointer to pass to the seek callback */ + #ifndef CURL_DISABLE_HSTS ++ struct curl_slist *hstslist; /* list of HSTS files set by ++ curl_easy_setopt(HSTS) calls */ + curl_hstsread_callback hsts_read; + void *hsts_read_userp; + curl_hstswrite_callback hsts_write; +-- +2.39.1 + + +From 32066a5fa8f649da2aa7a4e4e86bc0b73d32212f Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH 2/5] tool_operate: share HSTS between handles + +Upstream-commit: 0bf8b796a0ea98395b390c7807187982215f5c11 +Signed-off-by: Kamil Dudka +--- + src/tool_operate.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/tool_operate.c b/src/tool_operate.c +index 79db063..a5b024e 100644 +--- a/src/tool_operate.c ++++ b/src/tool_operate.c +@@ -2722,6 +2722,7 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[]) + curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); + curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); + curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL); ++ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS); + + /* Get the required arguments for each operation */ + do { +-- +2.39.1 + + +From fe6b64ac33a0994e5f50ef8b3d0916b3a248a7e8 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH 3/5] hsts: handle adding the same host name again + +It will then use the largest expire time of the two entries. + +Upstream-commit: ca02a77f05bd5cef20618c8f741aa48b7be0a648 +Signed-off-by: Kamil Dudka +--- + lib/hsts.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/lib/hsts.c b/lib/hsts.c +index 339237b..8d6723e 100644 +--- a/lib/hsts.c ++++ b/lib/hsts.c +@@ -426,14 +426,23 @@ static CURLcode hsts_add(struct hsts *h, char *line) + if(2 == rc) { + time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) : + TIME_T_MAX; +- CURLcode result; ++ CURLcode result = CURLE_OK; + char *p = host; + bool subdomain = FALSE; ++ struct stsentry *e; + if(p[0] == '.') { + p++; + subdomain = TRUE; + } +- result = hsts_create(h, p, subdomain, expires); ++ /* only add it if not already present */ ++ e = Curl_hsts(h, p, subdomain); ++ if(!e) ++ result = hsts_create(h, p, subdomain, expires); ++ else { ++ /* the same host name, use the largest expire time */ ++ if(expires > e->expires) ++ e->expires = expires; ++ } + if(result) + return result; + } +-- +2.39.1 + + +From c52b93434c65ec8a44193a6f2b833a1efec8f643 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH 4/5] runtests: support crlf="yes" for verify/proxy + +Upstream-commit: dc0725244a3163f1e2d5f51165db3a1a430f3ba0 +Signed-off-by: Kamil Dudka +--- + tests/FILEFORMAT.md | 4 ++-- + tests/runtests.pl | 5 +++++ + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md +index 8143967..be11167 100644 +--- a/tests/FILEFORMAT.md ++++ b/tests/FILEFORMAT.md +@@ -566,7 +566,7 @@ changing protocol data such as port numbers or user-agent strings. + One perl op per line that operates on the protocol dump. This is pretty + advanced. Example: `s/^EPRT .*/EPRT stripped/`. + +-### `` ++### `` + + the protocol dump curl should transmit, if `nonewline` is set, we will cut off + the trailing newline of this given data before comparing with the one actually +@@ -576,7 +576,7 @@ comparisons are made. + `crlf=yes` forces the newlines to become CRLF even if not written so in the + test. + +-### `` ++### `` + + The protocol dump curl should transmit to an HTTP proxy (when the http-proxy + server is used), if `nonewline` is set, we will cut off the trailing newline +diff --git a/tests/runtests.pl b/tests/runtests.pl +index c6a739e..f49e385 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -4744,6 +4744,11 @@ sub singletest { + } + } + ++ if($hash{'crlf'} || ++ ($has_hyper && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) { ++ map subNewlines(0, \$_), @protstrip; ++ } ++ + $res = compare($testnum, $testname, "proxy", \@out, \@protstrip); + if($res) { + return $errorreturncode; +-- +2.39.1 + + +From e428f66157caedc1f58ff5206915842937b0950e Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH 5/5] test446: verify hsts with two URLs + +Upstream-commit: ea5aaaa5ede53819f8bc7ae767fc2d13d3704d37 +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.inc | 2 +- + tests/data/test446 | 84 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 85 insertions(+), 1 deletion(-) + create mode 100644 tests/data/test446 + +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 3e0221a..fb51cd6 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -71,7 +71,7 @@ test408 test409 test410 test411 test412 test413 test414 test415 test416 \ + \ + test430 test431 test432 test433 test434 test435 test436 \ + \ +-test440 test441 test442 test443 test444 test445 \ ++test440 test441 test442 test443 test444 test445 test446 \ + \ + test490 test491 test492 test493 test494 test495 test496 \ + \ +diff --git a/tests/data/test446 b/tests/data/test446 +new file mode 100644 +index 0000000..0e2dfdc +--- /dev/null ++++ b/tests/data/test446 +@@ -0,0 +1,84 @@ ++ ++ ++ ++ ++HTTP ++HTTP proxy ++HSTS ++trailing-dot ++ ++ ++ ++ ++ ++# we use this as response to a CONNECT ++ ++HTTP/1.1 200 OK ++ ++ ++ ++HTTP/1.1 200 OK ++Content-Length: 6 ++Strict-Transport-Security: max-age=604800 ++ ++-foo- ++ ++ ++HTTP/1.1 200 OK ++Content-Length: 6 ++Strict-Transport-Security: max-age=6048000 ++ ++-baa- ++ ++ ++ ++ ++ ++https ++http-proxy ++ ++ ++HSTS ++proxy ++https ++debug ++ ++ ++CURL_HSTS_HTTP=yes ++CURL_TIME=2000000000 ++ ++ ++ ++HSTS with two URLs ++ ++ ++-x http://%HOSTIP:%PROXYPORT --hsts log/hsts%TESTNUMBER http://this.hsts.example./%TESTNUMBER http://another.example.com/%TESTNUMBER0002 ++ ++ ++ ++ ++# we let it CONNECT to the server to confirm HSTS but deny from there ++ ++GET http://this.hsts.example./%TESTNUMBER HTTP/1.1 ++Host: this.hsts.example. ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://another.example.com/%TESTNUMBER0002 HTTP/1.1 ++Host: another.example.com ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ ++# Your HSTS cache. https://curl.se/docs/hsts.html ++# This file was generated by libcurl! Edit at your own risk. ++this.hsts.example "20330525 03:33:20" ++another.example.com "20330727 03:33:20" ++ ++ ++ ++ +-- +2.39.1 + diff --git a/curl.spec b/curl.spec index 61f3004..d5fb421 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.87.0 -Release: 4%{?dist} +Release: 5%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -13,6 +13,9 @@ Source2: mykey.asc # fix regression in a public header file (#2162716) Patch1: 0001-curl-7.87.0-header-file-regression.patch +# share HSTS between handles (CVE-2023-23915 CVE-2023-23914) +Patch6: 0006-curl-7.87.0-hsts-CVEs.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -201,6 +204,7 @@ be installed. # upstream patches %patch1 -p1 +%patch6 -p1 # Fedora patches %patch101 -p1 @@ -435,6 +439,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Feb 15 2023 Kamil Dudka - 7.87.0-5 +- share HSTS between handles (CVE-2023-23915 CVE-2023-23914) + * Fri Jan 20 2023 Kamil Dudka - 7.87.0-4 - fix regression in a public header file (#2162716) From 5e6ef31ed95b567e079bc7037390facd504218ae Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 15 Feb 2023 18:01:30 +0100 Subject: [PATCH 02/29] Resolves: CVE-2023-23916 - fix HTTP multi-header compression denial of service --- 0007-curl-7.87.0-CVE-2023-23916.patch | 243 ++++++++++++++++++++++++++ curl.spec | 5 + 2 files changed, 248 insertions(+) create mode 100644 0007-curl-7.87.0-CVE-2023-23916.patch diff --git a/0007-curl-7.87.0-CVE-2023-23916.patch b/0007-curl-7.87.0-CVE-2023-23916.patch new file mode 100644 index 0000000..b82ffc5 --- /dev/null +++ b/0007-curl-7.87.0-CVE-2023-23916.patch @@ -0,0 +1,243 @@ +From bc5fc958b017895728962c9d44c469418cbec1a0 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +Date: Mon, 13 Feb 2023 08:33:09 +0100 +Subject: [PATCH] content_encoding: do not reset stage counter for each header + +Test 418 verifies + +Closes #10492 + +Upstream-commit: 119fb187192a9ea13dc90d9d20c215fc82799ab9 +Signed-off-by: Kamil Dudka +--- + lib/content_encoding.c | 7 +- + lib/urldata.h | 1 + + tests/data/Makefile.inc | 1 + + tests/data/test387 | 2 +- + tests/data/test418 | 152 ++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 158 insertions(+), 5 deletions(-) + create mode 100644 tests/data/test418 + +diff --git a/lib/content_encoding.c b/lib/content_encoding.c +index bfc13e2..94344d6 100644 +--- a/lib/content_encoding.c ++++ b/lib/content_encoding.c +@@ -1045,7 +1045,6 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, + const char *enclist, int maybechunked) + { + struct SingleRequest *k = &data->req; +- int counter = 0; + + do { + const char *name; +@@ -1080,9 +1079,9 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, + if(!encoding) + encoding = &error_encoding; /* Defer error at stack use. */ + +- if(++counter >= MAX_ENCODE_STACK) { +- failf(data, "Reject response due to %u content encodings", +- counter); ++ if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) { ++ failf(data, "Reject response due to more than %u content encodings", ++ MAX_ENCODE_STACK); + return CURLE_BAD_CONTENT_ENCODING; + } + /* Stack the unencoding stage. */ +diff --git a/lib/urldata.h b/lib/urldata.h +index 5b4b34f..8c8c20b 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -707,6 +707,7 @@ struct SingleRequest { + struct dohdata *doh; /* DoH specific data for this request */ + #endif + unsigned char setcookies; ++ unsigned char writer_stack_depth; /* Unencoding stack depth. */ + BIT(header); /* incoming data has HTTP header */ + BIT(content_range); /* set TRUE if Content-Range: was found */ + BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index fb51cd6..86b6f85 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -68,6 +68,7 @@ test380 test381 test383 test384 test385 test386 test387 test388 test389 \ + test390 test391 test392 test393 test394 test395 test396 test397 test398 \ + test399 test400 test401 test402 test403 test404 test405 test406 test407 \ + test408 test409 test410 test411 test412 test413 test414 test415 test416 \ ++ test418 \ + \ + test430 test431 test432 test433 test434 test435 test436 \ + \ +diff --git a/tests/data/test387 b/tests/data/test387 +index 015ec25..644fc7f 100644 +--- a/tests/data/test387 ++++ b/tests/data/test387 +@@ -47,7 +47,7 @@ Accept: */* + 61 + + +-curl: (61) Reject response due to 5 content encodings ++curl: (61) Reject response due to more than 5 content encodings + + + +diff --git a/tests/data/test418 b/tests/data/test418 +new file mode 100644 +index 0000000..50e974e +--- /dev/null ++++ b/tests/data/test418 +@@ -0,0 +1,152 @@ ++ ++ ++ ++HTTP ++gzip ++ ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 200 OK ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++Transfer-Encoding: gzip ++ ++-foo- ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ ++ ++Response with multiple Transfer-Encoding headers ++ ++ ++http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ ++ ++ ++# CURLE_BAD_CONTENT_ENCODING is 61 ++ ++61 ++ ++ ++curl: (61) Reject response due to more than 5 content encodings ++ ++ ++ +-- +2.39.1 + diff --git a/curl.spec b/curl.spec index d5fb421..af07f42 100644 --- a/curl.spec +++ b/curl.spec @@ -16,6 +16,9 @@ Patch1: 0001-curl-7.87.0-header-file-regression.patch # share HSTS between handles (CVE-2023-23915 CVE-2023-23914) Patch6: 0006-curl-7.87.0-hsts-CVEs.patch +# fix HTTP multi-header compression denial of service (CVE-2023-23916) +Patch7: 0007-curl-7.87.0-CVE-2023-23916.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -205,6 +208,7 @@ be installed. # upstream patches %patch1 -p1 %patch6 -p1 +%patch7 -p1 # Fedora patches %patch101 -p1 @@ -440,6 +444,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Wed Feb 15 2023 Kamil Dudka - 7.87.0-5 +- fix HTTP multi-header compression denial of service (CVE-2023-23916) - share HSTS between handles (CVE-2023-23915 CVE-2023-23914) * Fri Jan 20 2023 Kamil Dudka - 7.87.0-4 From ec2bc20d6e59b5aabc431a9c2c97b5774593a323 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 15 Mar 2023 16:46:54 +0100 Subject: [PATCH 03/29] tests: make sure gnuserv-tls has SRP support before using it --- 0002-curl-7.87.0-tests-tls-srp.patch | 54 ++++++++++++++++++++++++++++ curl.spec | 9 ++++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 0002-curl-7.87.0-tests-tls-srp.patch diff --git a/0002-curl-7.87.0-tests-tls-srp.patch b/0002-curl-7.87.0-tests-tls-srp.patch new file mode 100644 index 0000000..f2ad919 --- /dev/null +++ b/0002-curl-7.87.0-tests-tls-srp.patch @@ -0,0 +1,54 @@ +From 34ba217b433f222f486a42f2157866ab40dba221 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 15 Feb 2023 15:04:07 +0100 +Subject: [PATCH] tests: make sure gnuserv-tls has SRP support before using it + +Reported-by: fundawang on github +Fixes #10522 +Closes #10524 + +Upstream-commit: 2fdc1d816ebf3c77f43068103bec1b3a3767881a +Signed-off-by: Kamil Dudka +--- + tests/runtests.pl | 2 +- + tests/sshhelp.pm | 11 ++++++++++- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/tests/runtests.pl b/tests/runtests.pl +index f49e385..d2e0e52 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -5373,7 +5373,7 @@ sub startservers { + elsif($what eq "httptls") { + if(!$httptlssrv) { + # for now, we can't run http TLS-EXT tests without gnutls-serv +- return "no gnutls-serv"; ++ return "no gnutls-serv (with SRP support)"; + } + if($torture && $run{'httptls'} && + !responsive_httptls_server($verbose, "IPv4")) { +diff --git a/tests/sshhelp.pm b/tests/sshhelp.pm +index 2d419c1..0c553da 100644 +--- a/tests/sshhelp.pm ++++ b/tests/sshhelp.pm +@@ -408,7 +408,16 @@ sub find_sshkeygen { + # Find httptlssrv (gnutls-serv) and return canonical filename + # + sub find_httptlssrv { +- return find_exe_file_hpath($httptlssrvexe); ++ my $p = find_exe_file_hpath($httptlssrvexe); ++ my @o = `$p -l`; ++ my $found; ++ for(@o) { ++ if(/Key exchange: SRP/) { ++ $found = 1; ++ last; ++ } ++ } ++ return $p if($found); + } + + +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index af07f42..86ee916 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.87.0 -Release: 5%{?dist} +Release: 6%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -13,6 +13,9 @@ Source2: mykey.asc # fix regression in a public header file (#2162716) Patch1: 0001-curl-7.87.0-header-file-regression.patch +# tests: make sure gnuserv-tls has SRP support before using it +Patch2: 0002-curl-7.87.0-tests-tls-srp.patch + # share HSTS between handles (CVE-2023-23915 CVE-2023-23914) Patch6: 0006-curl-7.87.0-hsts-CVEs.patch @@ -207,6 +210,7 @@ be installed. # upstream patches %patch1 -p1 +%patch2 -p1 %patch6 -p1 %patch7 -p1 @@ -443,6 +447,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Mar 15 2023 Kamil Dudka - 7.87.0-6 +- tests: make sure gnuserv-tls has SRP support before using it + * Wed Feb 15 2023 Kamil Dudka - 7.87.0-5 - fix HTTP multi-header compression denial of service (CVE-2023-23916) - share HSTS between handles (CVE-2023-23915 CVE-2023-23914) From 070308204190e2e781f0b1fec5877c6a40c634bd Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 24 Mar 2023 13:14:43 +0100 Subject: [PATCH 04/29] Resolves: CVE-2023-27533 - fix TELNET option IAC injection --- 0023-curl-7.87.0-CVE-2023-27533.patch | 59 +++++++++++++++++++++++++++ curl.spec | 9 +++- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 0023-curl-7.87.0-CVE-2023-27533.patch diff --git a/0023-curl-7.87.0-CVE-2023-27533.patch b/0023-curl-7.87.0-CVE-2023-27533.patch new file mode 100644 index 0000000..8810c27 --- /dev/null +++ b/0023-curl-7.87.0-CVE-2023-27533.patch @@ -0,0 +1,59 @@ +From c9828d86040737a47da862197b5def7ff6b0e3c4 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 6 Mar 2023 12:07:33 +0100 +Subject: [PATCH] telnet: only accept option arguments in ascii + +To avoid embedded telnet negotiation commands etc. + +Reported-by: Harry Sintonen +Closes #10728 + +Upstream-commit: 538b1e79a6e7b0bb829ab4cecc828d32105d0684 +Signed-off-by: Kamil Dudka +--- + lib/telnet.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/lib/telnet.c b/lib/telnet.c +index 22bc81e..baea885 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -770,6 +770,17 @@ static void printsub(struct Curl_easy *data, + } + } + ++static bool str_is_nonascii(const char *str) ++{ ++ size_t len = strlen(str); ++ while(len--) { ++ if(*str & 0x80) ++ return TRUE; ++ str++; ++ } ++ return FALSE; ++} ++ + static CURLcode check_telnet_options(struct Curl_easy *data) + { + struct curl_slist *head; +@@ -784,6 +795,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data) + /* Add the user name as an environment variable if it + was given on the command line */ + if(data->state.aptr.user) { ++ if(str_is_nonascii(data->conn->user)) ++ return CURLE_BAD_FUNCTION_ARGUMENT; + msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { +@@ -798,6 +811,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data) + for(head = data->set.telnet_options; head; head = head->next) { + if(sscanf(head->data, "%127[^= ]%*[ =]%255s", + option_keyword, option_arg) == 2) { ++ if(str_is_nonascii(option_arg)) ++ continue; + + /* Terminal type */ + if(strcasecompare(option_keyword, "TTYPE")) { +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 86ee916..108f44d 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.87.0 -Release: 6%{?dist} +Release: 7%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -22,6 +22,9 @@ Patch6: 0006-curl-7.87.0-hsts-CVEs.patch # fix HTTP multi-header compression denial of service (CVE-2023-23916) Patch7: 0007-curl-7.87.0-CVE-2023-23916.patch +# fix TELNET option IAC injection (CVE-2023-27533) +Patch23: 0023-curl-7.87.0-CVE-2023-27533.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -213,6 +216,7 @@ be installed. %patch2 -p1 %patch6 -p1 %patch7 -p1 +%patch23 -p1 # Fedora patches %patch101 -p1 @@ -447,6 +451,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix TELNET option IAC injection (CVE-2023-27533) + * Wed Mar 15 2023 Kamil Dudka - 7.87.0-6 - tests: make sure gnuserv-tls has SRP support before using it From bdb83efe757fb9a6191c0b196a9a05fcb9014659 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 24 Mar 2023 13:16:13 +0100 Subject: [PATCH 05/29] Resolves: CVE-2023-27534 - fix SFTP path ~ resolving discrepancy --- 0024-curl-7.87.0-CVE-2023-27534.patch | 126 ++++++++++++++++++++++++++ curl.spec | 5 + 2 files changed, 131 insertions(+) create mode 100644 0024-curl-7.87.0-CVE-2023-27534.patch diff --git a/0024-curl-7.87.0-CVE-2023-27534.patch b/0024-curl-7.87.0-CVE-2023-27534.patch new file mode 100644 index 0000000..ea589f3 --- /dev/null +++ b/0024-curl-7.87.0-CVE-2023-27534.patch @@ -0,0 +1,126 @@ +From 5ebdef4442b438ab1a899edb169489fc259fae1a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 9 Mar 2023 16:22:11 +0100 +Subject: [PATCH] curl_path: create the new path with dynbuf + +Closes #10729 + +Upstream-commit: 4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6 +Signed-off-by: Kamil Dudka +--- + lib/curl_path.c | 75 +++++++++++++++++++++++-------------------------- + 1 file changed, 35 insertions(+), 40 deletions(-) + +diff --git a/lib/curl_path.c b/lib/curl_path.c +index f00e3ee..8106042 100644 +--- a/lib/curl_path.c ++++ b/lib/curl_path.c +@@ -32,70 +32,65 @@ + #include "escape.h" + #include "memdebug.h" + ++#define MAX_SSHPATH_LEN 100000 /* arbitrary */ ++ + /* figure out the path to work with in this particular request */ + CURLcode Curl_getworkingpath(struct Curl_easy *data, + char *homedir, /* when SFTP is used */ + char **path) /* returns the allocated + real path to work with */ + { +- char *real_path = NULL; + char *working_path; + size_t working_path_len; ++ struct dynbuf npath; + CURLcode result = + Curl_urldecode(data->state.up.path, 0, &working_path, + &working_path_len, REJECT_ZERO); + if(result) + return result; + ++ /* new path to switch to in case we need to */ ++ Curl_dyn_init(&npath, MAX_SSHPATH_LEN); ++ + /* Check for /~/, indicating relative to the user's home directory */ +- if(data->conn->handler->protocol & CURLPROTO_SCP) { +- real_path = malloc(working_path_len + 1); +- if(!real_path) { ++ if((data->conn->handler->protocol & CURLPROTO_SCP) && ++ (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) { ++ /* It is referenced to the home directory, so strip the leading '/~/' */ ++ if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) { + free(working_path); + return CURLE_OUT_OF_MEMORY; + } +- if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) +- /* It is referenced to the home directory, so strip the leading '/~/' */ +- memcpy(real_path, working_path + 3, working_path_len - 2); +- else +- memcpy(real_path, working_path, 1 + working_path_len); + } +- else if(data->conn->handler->protocol & CURLPROTO_SFTP) { +- if((working_path_len > 1) && (working_path[1] == '~')) { +- size_t homelen = strlen(homedir); +- real_path = malloc(homelen + working_path_len + 1); +- if(!real_path) { +- free(working_path); +- return CURLE_OUT_OF_MEMORY; +- } +- /* It is referenced to the home directory, so strip the +- leading '/' */ +- memcpy(real_path, homedir, homelen); +- /* Only add a trailing '/' if homedir does not end with one */ +- if(homelen == 0 || real_path[homelen - 1] != '/') { +- real_path[homelen] = '/'; +- homelen++; +- real_path[homelen] = '\0'; +- } +- if(working_path_len > 3) { +- memcpy(real_path + homelen, working_path + 3, +- 1 + working_path_len -3); +- } ++ else if((data->conn->handler->protocol & CURLPROTO_SFTP) && ++ (working_path_len > 2) && !memcmp(working_path, "/~/", 3)) { ++ size_t len; ++ const char *p; ++ int copyfrom = 3; ++ if(Curl_dyn_add(&npath, homedir)) { ++ free(working_path); ++ return CURLE_OUT_OF_MEMORY; + } +- else { +- real_path = malloc(working_path_len + 1); +- if(!real_path) { +- free(working_path); +- return CURLE_OUT_OF_MEMORY; +- } +- memcpy(real_path, working_path, 1 + working_path_len); ++ /* Copy a separating '/' if homedir does not end with one */ ++ len = Curl_dyn_len(&npath); ++ p = Curl_dyn_ptr(&npath); ++ if(len && (p[len-1] != '/')) ++ copyfrom = 2; ++ ++ if(Curl_dyn_addn(&npath, ++ &working_path[copyfrom], working_path_len - copyfrom)) { ++ free(working_path); ++ return CURLE_OUT_OF_MEMORY; + } + } + +- free(working_path); ++ if(Curl_dyn_len(&npath)) { ++ free(working_path); + +- /* store the pointer for the caller to receive */ +- *path = real_path; ++ /* store the pointer for the caller to receive */ ++ *path = Curl_dyn_ptr(&npath); ++ } ++ else ++ *path = working_path; + + return CURLE_OK; + } +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 108f44d..2fd9e4a 100644 --- a/curl.spec +++ b/curl.spec @@ -25,6 +25,9 @@ Patch7: 0007-curl-7.87.0-CVE-2023-23916.patch # fix TELNET option IAC injection (CVE-2023-27533) Patch23: 0023-curl-7.87.0-CVE-2023-27533.patch +# fix SFTP path ~ resolving discrepancy (CVE-2023-27534) +Patch24: 0024-curl-7.87.0-CVE-2023-27534.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -217,6 +220,7 @@ be installed. %patch6 -p1 %patch7 -p1 %patch23 -p1 +%patch24 -p1 # Fedora patches %patch101 -p1 @@ -452,6 +456,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix SFTP path ~ resolving discrepancy (CVE-2023-27534) - fix TELNET option IAC injection (CVE-2023-27533) * Wed Mar 15 2023 Kamil Dudka - 7.87.0-6 From 8c6f543d9e51bb5a3362781a784a4b10fa61be61 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 24 Mar 2023 13:24:04 +0100 Subject: [PATCH 06/29] Resolves: CVE-2023-27535 - fix FTP too eager connection reuse --- 0025-curl-7.87.0-CVE-2023-27535.patch | 166 ++++++++++++++++++++++++++ curl.spec | 5 + 2 files changed, 171 insertions(+) create mode 100644 0025-curl-7.87.0-CVE-2023-27535.patch diff --git a/0025-curl-7.87.0-CVE-2023-27535.patch b/0025-curl-7.87.0-CVE-2023-27535.patch new file mode 100644 index 0000000..4d3cf52 --- /dev/null +++ b/0025-curl-7.87.0-CVE-2023-27535.patch @@ -0,0 +1,166 @@ +From b79a0e768fcd71003b33feb5deea697dd0903e48 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 9 Mar 2023 17:47:06 +0100 +Subject: [PATCH] ftp: add more conditions for connection reuse + +Reported-by: Harry Sintonen +Closes #10730 + +Upstream-commit: 8f4608468b890dce2dad9f91d5607ee7e9c1aba1 +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 28 ++++++++++++++++++++++++++-- + lib/ftp.h | 5 +++++ + lib/setopt.c | 2 +- + lib/url.c | 16 +++++++++++++++- + lib/urldata.h | 4 ++-- + 5 files changed, 49 insertions(+), 6 deletions(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index 8f0ac2e..d90509e 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -4069,6 +4069,8 @@ static CURLcode ftp_disconnect(struct Curl_easy *data, + } + + freedirs(ftpc); ++ Curl_safefree(ftpc->account); ++ Curl_safefree(ftpc->alternative_to_user); + Curl_safefree(ftpc->prevpath); + Curl_safefree(ftpc->server_os); + Curl_pp_disconnect(pp); +@@ -4338,11 +4340,31 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, + char *type; + struct FTP *ftp; + CURLcode result = CURLE_OK; ++ struct ftp_conn *ftpc = &conn->proto.ftpc; + +- data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1); ++ ftp = calloc(sizeof(struct FTP), 1); + if(!ftp) + return CURLE_OUT_OF_MEMORY; + ++ /* clone connection related data that is FTP specific */ ++ if(data->set.str[STRING_FTP_ACCOUNT]) { ++ ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]); ++ if(!ftpc->account) { ++ free(ftp); ++ return CURLE_OUT_OF_MEMORY; ++ } ++ } ++ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) { ++ ftpc->alternative_to_user = ++ strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); ++ if(!ftpc->alternative_to_user) { ++ Curl_safefree(ftpc->account); ++ free(ftp); ++ return CURLE_OUT_OF_MEMORY; ++ } ++ } ++ data->req.p.ftp = ftp; ++ + ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ + + /* FTP URLs support an extension like ";type=" that +@@ -4377,7 +4399,9 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, + /* get some initial data into the ftp struct */ + ftp->transfer = PPTRANSFER_BODY; + ftp->downloadsize = 0; +- conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ ++ ftpc->known_filesize = -1; /* unknown size for now */ ++ ftpc->use_ssl = data->set.use_ssl; ++ ftpc->ccc = data->set.ftp_ccc; + + return result; + } +diff --git a/lib/ftp.h b/lib/ftp.h +index 7f6f432..3f33e27 100644 +--- a/lib/ftp.h ++++ b/lib/ftp.h +@@ -119,6 +119,8 @@ struct FTP { + struct */ + struct ftp_conn { + struct pingpong pp; ++ char *account; ++ char *alternative_to_user; + char *entrypath; /* the PWD reply when we logged on */ + char *file; /* url-decoded file name (or path) */ + char **dirs; /* realloc()ed array for path components */ +@@ -148,6 +150,9 @@ struct ftp_conn { + ftpstate state; /* always use ftp.c:state() to change state! */ + ftpstate state_saved; /* transfer type saved to be reloaded after + data connection is established */ ++ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or ++ IMAP or POP3 or others! (type: curl_usessl)*/ ++ unsigned char ccc; /* ccc level for this connection */ + curl_off_t retr_size_saved; /* Size of retrieved file saved */ + char *server_os; /* The target server operating system. */ + curl_off_t known_filesize; /* file size is different from -1, if wildcard +diff --git a/lib/setopt.c b/lib/setopt.c +index f71a606..d1905c6 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2351,7 +2351,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + arg = va_arg(param, long); + if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST)) + return CURLE_BAD_FUNCTION_ARGUMENT; +- data->set.use_ssl = (curl_usessl)arg; ++ data->set.use_ssl = (unsigned char)arg; + break; + + case CURLOPT_SSL_OPTIONS: +diff --git a/lib/url.c b/lib/url.c +index 831ae06..3b11b7e 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1352,10 +1352,24 @@ ConnectionExists(struct Curl_easy *data, + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + continue; + +- if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { ++#ifdef USE_SSH ++ else if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; + } ++#endif ++#ifndef CURL_DISABLE_FTP ++ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { ++ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ ++ if(Curl_timestrcmp(needle->proto.ftpc.account, ++ check->proto.ftpc.account) || ++ Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, ++ check->proto.ftpc.alternative_to_user) || ++ (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || ++ (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) ++ continue; ++ } ++#endif + + if((needle->handler->flags&PROTOPT_SSL) + #ifndef CURL_DISABLE_PROXY +diff --git a/lib/urldata.h b/lib/urldata.h +index 8c8c20b..ce90304 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1750,8 +1750,6 @@ struct UserDefined { + #ifndef CURL_DISABLE_NETRC + unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */ + #endif +- curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or +- IMAP or POP3 or others! */ + unsigned int new_file_perms; /* when creating remote files */ + unsigned int new_directory_perms; /* when creating remote dirs */ + int ssh_auth_types; /* allowed SSH auth types */ +@@ -1810,6 +1808,8 @@ struct UserDefined { + BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some + recipients */ + #endif ++ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or ++ IMAP or POP3 or others! (type: curl_usessl)*/ + unsigned char connect_only; /* make connection/request, then let + application use the socket */ + BIT(is_fread_set); /* has read callback been set to non-NULL? */ +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 2fd9e4a..3217d50 100644 --- a/curl.spec +++ b/curl.spec @@ -28,6 +28,9 @@ Patch23: 0023-curl-7.87.0-CVE-2023-27533.patch # fix SFTP path ~ resolving discrepancy (CVE-2023-27534) Patch24: 0024-curl-7.87.0-CVE-2023-27534.patch +# fix FTP too eager connection reuse (CVE-2023-27535) +Patch25: 0025-curl-7.87.0-CVE-2023-27535.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -221,6 +224,7 @@ be installed. %patch7 -p1 %patch23 -p1 %patch24 -p1 +%patch25 -p1 # Fedora patches %patch101 -p1 @@ -456,6 +460,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix FTP too eager connection reuse (CVE-2023-27535) - fix SFTP path ~ resolving discrepancy (CVE-2023-27534) - fix TELNET option IAC injection (CVE-2023-27533) From 4b9d35186873af2621fa67eb44cc064c843c3cbc Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 24 Mar 2023 13:25:23 +0100 Subject: [PATCH 07/29] Resolves: CVE-2023-27536 - fix GSS delegation too eager connection re-use --- 0026-curl-7.87.0-CVE-2023-27536.patch | 54 +++++++++++++++++++++++++++ curl.spec | 5 +++ 2 files changed, 59 insertions(+) create mode 100644 0026-curl-7.87.0-CVE-2023-27536.patch diff --git a/0026-curl-7.87.0-CVE-2023-27536.patch b/0026-curl-7.87.0-CVE-2023-27536.patch new file mode 100644 index 0000000..268e206 --- /dev/null +++ b/0026-curl-7.87.0-CVE-2023-27536.patch @@ -0,0 +1,54 @@ +From 9d6dd7bc1dea42ae8e710aeae714e2a2c290de61 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 10 Mar 2023 09:22:43 +0100 +Subject: [PATCH] url: only reuse connections with same GSS delegation + +Reported-by: Harry Sintonen +Closes #10731 + +Upstream-commit: cb49e67303dbafbab1cebf4086e3ec15b7d56ee5 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 6 ++++++ + lib/urldata.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/lib/url.c b/lib/url.c +index 3b11b7e..cbbc7f3 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1345,6 +1345,11 @@ ConnectionExists(struct Curl_easy *data, + } + } + ++ /* GSS delegation differences do not actually affect every connection ++ and auth method, but this check takes precaution before efficiency */ ++ if(needle->gssapi_delegation != check->gssapi_delegation) ++ continue; ++ + /* If multiplexing isn't enabled on the h2 connection and h1 is + explicitly requested, handle it: */ + if((needle->handler->protocol & PROTO_FAMILY_HTTP) && +@@ -1662,6 +1667,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) + conn->fclosesocket = data->set.fclosesocket; + conn->closesocket_client = data->set.closesocket_client; + conn->lastused = Curl_now(); /* used now */ ++ conn->gssapi_delegation = data->set.gssapi_delegation; + + return conn; + error: +diff --git a/lib/urldata.h b/lib/urldata.h +index ce90304..9e16f26 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1111,6 +1111,7 @@ struct connectdata { + unsigned char ip_version; /* copied from the Curl_easy at creation time */ + unsigned char httpversion; /* the HTTP version*10 reported by the server */ + unsigned char connect_only; ++ unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */ + }; + + /* The end of connectdata. */ +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 3217d50..6cd2a58 100644 --- a/curl.spec +++ b/curl.spec @@ -31,6 +31,9 @@ Patch24: 0024-curl-7.87.0-CVE-2023-27534.patch # fix FTP too eager connection reuse (CVE-2023-27535) Patch25: 0025-curl-7.87.0-CVE-2023-27535.patch +# fix GSS delegation too eager connection re-use (CVE-2023-27536) +Patch26: 0026-curl-7.87.0-CVE-2023-27536.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -225,6 +228,7 @@ be installed. %patch23 -p1 %patch24 -p1 %patch25 -p1 +%patch26 -p1 # Fedora patches %patch101 -p1 @@ -460,6 +464,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix GSS delegation too eager connection re-use (CVE-2023-27536) - fix FTP too eager connection reuse (CVE-2023-27535) - fix SFTP path ~ resolving discrepancy (CVE-2023-27534) - fix TELNET option IAC injection (CVE-2023-27533) From be852f01b83d2cffb3d00130c44a6e74e5affdcb Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 24 Mar 2023 13:26:50 +0100 Subject: [PATCH 08/29] Resolves: CVE-2023-27537 - fix HSTS double-free --- 0027-curl-7.87.0-CVE-2023-27537.patch | 40 +++++++++++++++++++++++++++ curl.spec | 5 ++++ 2 files changed, 45 insertions(+) create mode 100644 0027-curl-7.87.0-CVE-2023-27537.patch diff --git a/0027-curl-7.87.0-CVE-2023-27537.patch b/0027-curl-7.87.0-CVE-2023-27537.patch new file mode 100644 index 0000000..df90d49 --- /dev/null +++ b/0027-curl-7.87.0-CVE-2023-27537.patch @@ -0,0 +1,40 @@ +From ed7451520fd1b5da62a5371c07db69bed36a5486 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 9 Mar 2023 18:01:34 +0100 +Subject: [PATCH] CURLSHOPT_SHARE.3: HSTS sharing is not thread-safe + +Reported-by: Hiroki Kurosawa +Closes #10732 + +Upstream-commit: dca4cdf071be095bcdc7126eaa77a8946ea4790b +Signed-off-by: Kamil Dudka +--- + docs/libcurl/opts/CURLSHOPT_SHARE.3 | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3 +index b15af82..4544160 100644 +--- a/docs/libcurl/opts/CURLSHOPT_SHARE.3 ++++ b/docs/libcurl/opts/CURLSHOPT_SHARE.3 +@@ -57,8 +57,7 @@ implemented until 7.23.0. + Put the connection cache in the share object and make all easy handles using + this share object share the connection cache. + +-Note that due to a known bug, it is not safe to share connections this way +-between multiple concurrent threads. ++It is not supported to share connections between multiple concurrent threads. + + Connections that are used for HTTP/1.1 Pipelining or HTTP/2 multiplexing only + get additional transfers added to them if the existing connection is held by +@@ -82,6 +81,8 @@ multi handle will share PSL cache by default without using this option. + .IP CURL_LOCK_DATA_HSTS + The in-memory HSTS cache. + ++It is not supported to share the HSTS between multiple concurrent threads. ++ + Added in 7.88.0 + .SH PROTOCOLS + All +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 6cd2a58..d33a3b3 100644 --- a/curl.spec +++ b/curl.spec @@ -34,6 +34,9 @@ Patch25: 0025-curl-7.87.0-CVE-2023-27535.patch # fix GSS delegation too eager connection re-use (CVE-2023-27536) Patch26: 0026-curl-7.87.0-CVE-2023-27536.patch +# fix HSTS double-free (CVE-2023-27537) +Patch27: 0027-curl-7.87.0-CVE-2023-27537.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -229,6 +232,7 @@ be installed. %patch24 -p1 %patch25 -p1 %patch26 -p1 +%patch27 -p1 # Fedora patches %patch101 -p1 @@ -464,6 +468,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix HSTS double-free (CVE-2023-27537) - fix GSS delegation too eager connection re-use (CVE-2023-27536) - fix FTP too eager connection reuse (CVE-2023-27535) - fix SFTP path ~ resolving discrepancy (CVE-2023-27534) From a3bc8ee146d975e61a010a14029dce309989330c Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 24 Mar 2023 13:28:18 +0100 Subject: [PATCH 09/29] Resolves: CVE-2023-27538 - fix SSH connection too eager reuse still --- 0028-curl-7.87.0-CVE-2023-27538.patch | 30 +++++++++++++++++++++++++++ curl.spec | 5 +++++ 2 files changed, 35 insertions(+) create mode 100644 0028-curl-7.87.0-CVE-2023-27538.patch diff --git a/0028-curl-7.87.0-CVE-2023-27538.patch b/0028-curl-7.87.0-CVE-2023-27538.patch new file mode 100644 index 0000000..0fb2fe8 --- /dev/null +++ b/0028-curl-7.87.0-CVE-2023-27538.patch @@ -0,0 +1,30 @@ +From 133e25afe4b8961b9c12334ee0bd3374db9a1fd4 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 10 Mar 2023 08:22:51 +0100 +Subject: [PATCH] url: fix the SSH connection reuse check + +Reported-by: Harry Sintonen +Closes #10735 + +Upstream-commit: af369db4d3833272b8ed443f7fcc2e757a0872eb +Signed-off-by: Kamil Dudka +--- + lib/url.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/url.c b/lib/url.c +index 0c31486..3b11b7e 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1353,7 +1353,7 @@ ConnectionExists(struct Curl_easy *data, + continue; + + #ifdef USE_SSH +- else if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { ++ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; + } +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index d33a3b3..fb4b8d9 100644 --- a/curl.spec +++ b/curl.spec @@ -37,6 +37,9 @@ Patch26: 0026-curl-7.87.0-CVE-2023-27536.patch # fix HSTS double-free (CVE-2023-27537) Patch27: 0027-curl-7.87.0-CVE-2023-27537.patch +# fix SSH connection too eager reuse still (CVE-2023-27538) +Patch28: 0028-curl-7.87.0-CVE-2023-27538.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -233,6 +236,7 @@ be installed. %patch25 -p1 %patch26 -p1 %patch27 -p1 +%patch28 -p1 # Fedora patches %patch101 -p1 @@ -468,6 +472,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix SSH connection too eager reuse still (CVE-2023-27538) - fix HSTS double-free (CVE-2023-27537) - fix GSS delegation too eager connection re-use (CVE-2023-27536) - fix FTP too eager connection reuse (CVE-2023-27535) From 7a1d94d30cbb5b05d30659355ea407955b49905b Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 21 Apr 2023 13:50:00 +0200 Subject: [PATCH 10/29] Resolves: #2185433 - cfilters: use the first non-connected filter --- 0003-curl-7.87.0-cfilters-ostree.patch | 40 ++++++++++++++++++++++++++ curl.spec | 9 +++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 0003-curl-7.87.0-cfilters-ostree.patch diff --git a/0003-curl-7.87.0-cfilters-ostree.patch b/0003-curl-7.87.0-cfilters-ostree.patch new file mode 100644 index 0000000..8f48861 --- /dev/null +++ b/0003-curl-7.87.0-cfilters-ostree.patch @@ -0,0 +1,40 @@ +From 4388f4af77c6741873062dc8da5c6cbcef2d5dfd Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 26 Dec 2022 09:59:20 +0100 +Subject: [PATCH] cfilters:Curl_conn_get_select_socks: use the first + non-connected filter + +When there are filters addded for both socket and SSL, the code +previously checked the SSL sockets during connect when it *should* first +check the socket layer until that has connected. + +Fixes #10157 +Fixes #10146 +Closes #10160 + +Reviewed-by: Stefan Eissing + +Upstream-commit: 728400f875e845f72ee5602edb905f6301ade3e7 +Signed-off-by: Kamil Dudka +--- + lib/cfilters.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/cfilters.c b/lib/cfilters.c +index bcb33da..94471e8 100644 +--- a/lib/cfilters.c ++++ b/lib/cfilters.c +@@ -437,6 +437,10 @@ int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex, + DEBUGASSERT(data); + DEBUGASSERT(data->conn); + cf = data->conn->cfilter[sockindex]; ++ ++ /* if the next one is not yet connected, that's the one we want */ ++ while(cf && cf->next && !cf->next->connected) ++ cf = cf->next; + if(cf) { + return cf->cft->get_select_socks(cf, data, socks); + } +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index fb4b8d9..d8ebf77 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.87.0 -Release: 7%{?dist} +Release: 8%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -16,6 +16,9 @@ Patch1: 0001-curl-7.87.0-header-file-regression.patch # tests: make sure gnuserv-tls has SRP support before using it Patch2: 0002-curl-7.87.0-tests-tls-srp.patch +# cfilters: use the first non-connected filter (#2185433) +Patch3: 0003-curl-7.87.0-cfilters-ostree.patch + # share HSTS between handles (CVE-2023-23915 CVE-2023-23914) Patch6: 0006-curl-7.87.0-hsts-CVEs.patch @@ -229,6 +232,7 @@ be installed. # upstream patches %patch1 -p1 %patch2 -p1 +%patch3 -p1 %patch6 -p1 %patch7 -p1 %patch23 -p1 @@ -471,6 +475,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Fri Apr 21 2023 Kamil Dudka - 7.87.0-8 +- cfilters: use the first non-connected filter (#2185433) + * Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 - fix SSH connection too eager reuse still (CVE-2023-27538) - fix HSTS double-free (CVE-2023-27537) From 472ff9ff394deee558414aea9cd405309e2642b9 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 3 May 2023 13:48:50 +0200 Subject: [PATCH 11/29] Resolves: #2192665 - vtls: fix hostname handling in filters --- 0008-curl-7.87.0-vtls-hostname.patch | 177 +++++++++++++++++++++++++++ curl.spec | 9 +- 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 0008-curl-7.87.0-vtls-hostname.patch diff --git a/0008-curl-7.87.0-vtls-hostname.patch b/0008-curl-7.87.0-vtls-hostname.patch new file mode 100644 index 0000000..24d6a31 --- /dev/null +++ b/0008-curl-7.87.0-vtls-hostname.patch @@ -0,0 +1,177 @@ +From d12c233950e22052a8541abd69565772c13f832e Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Tue, 17 Jan 2023 11:21:29 +0100 +Subject: [PATCH] vtls: fix hostname handling in filters + +- Copy the hostname and dispname to ssl_connect_data. + +Use a copy instead of referencing the `connectdata` instance since this +may get free'ed on connection reuse. + +Reported-by: Stefan Talpalaru +Reported-by: sergio-nsk@users.noreply.github.com + +Fixes https://github.com/curl/curl/issues/10273 +Fixes https://github.com/curl/curl/issues/10309 + +Closes https://github.com/curl/curl/pull/10310 + +Upstream-commit: f8da4f2f2d0451dc0a126ae3e5077b4527ccdc86 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 14 ++++++++++ + lib/vtls/vtls.c | 66 ++++++++++++++++++++++++++++++--------------- + lib/vtls/vtls_int.h | 4 +-- + 3 files changed, 61 insertions(+), 23 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index cbbc7f3..5192204 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -3406,6 +3406,20 @@ static void reuse_conn(struct Curl_easy *data, + } + #endif + ++ /* Finding a connection for reuse in the cache matches, among other ++ * things on the "remote-relevant" hostname. This is not necessarily ++ * the authority of the URL, e.g. conn->host. For example: ++ * - we use a proxy (not tunneling). we want to send all requests ++ * that use the same proxy on this connection. ++ * - we have a "connect-to" setting that may redirect the hostname of ++ * a new request to the same remote endpoint of an existing conn. ++ * We want to reuse an existing conn to the remote endpoint. ++ * Since connection reuse does not match on conn->host necessarily, we ++ * switch `existing` conn to `temp` conn's host settings. ++ * TODO: is this correct in the case of TLS connections that have ++ * used the original hostname in SNI to negotiate? Do we send ++ * requests for another host through the different SNI? ++ */ + Curl_free_idnconverted_hostname(&existing->host); + Curl_free_idnconverted_hostname(&existing->conn_to_host); + Curl_safefree(existing->host.rawalloc); +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 873ee6b..c7ec77a 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -1430,47 +1430,71 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, + + #ifdef USE_SSL + ++static void free_hostname(struct ssl_connect_data *connssl) ++{ ++ if(connssl->dispname != connssl->hostname) ++ free(connssl->dispname); ++ free(connssl->hostname); ++ connssl->hostname = connssl->dispname = NULL; ++} ++ + static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) + { + struct ssl_connect_data *connssl = cf->ctx; +- /* TODO: close_one closes BOTH conn->ssl AND conn->proxy_ssl for this +- * sockindex (if in use). Gladly, it is safe to call more than once. */ + if(connssl) { + Curl_ssl->close(cf, data); + connssl->state = ssl_connection_none; ++ free_hostname(connssl); + } + cf->connected = FALSE; + } + +-static void reinit_hostname(struct Curl_cfilter *cf) ++static CURLcode reinit_hostname(struct Curl_cfilter *cf) + { + struct ssl_connect_data *connssl = cf->ctx; ++ const char *ehostname, *edispname; ++ int eport; + ++ /* We need the hostname for SNI negotiation. Once handshaked, this ++ * remains the SNI hostname for the TLS connection. But when the ++ * connection is reused, the settings in cf->conn might change. ++ * So we keep a copy of the hostname we use for SNI. ++ */ + #ifndef CURL_DISABLE_PROXY + if(Curl_ssl_cf_is_proxy(cf)) { +- /* TODO: there is not definition for a proxy setup on a secondary conn */ +- connssl->hostname = cf->conn->http_proxy.host.name; +- connssl->dispname = cf->conn->http_proxy.host.dispname; +- connssl->port = cf->conn->http_proxy.port; ++ ehostname = cf->conn->http_proxy.host.name; ++ edispname = cf->conn->http_proxy.host.dispname; ++ eport = cf->conn->http_proxy.port; + } + else + #endif + { +- /* TODO: secondaryhostname is set to the IP address we connect to +- * in the FTP handler, it is assumed that host verification uses the +- * hostname from FIRSTSOCKET */ +- if(cf->sockindex == SECONDARYSOCKET && 0) { +- connssl->hostname = cf->conn->secondaryhostname; +- connssl->dispname = connssl->hostname; +- connssl->port = cf->conn->secondary_port; ++ ehostname = cf->conn->host.name; ++ edispname = cf->conn->host.dispname; ++ eport = cf->conn->remote_port; ++ } ++ ++ /* change if ehostname changed */ ++ if(ehostname && (!connssl->hostname ++ || strcmp(ehostname, connssl->hostname))) { ++ free_hostname(connssl); ++ connssl->hostname = strdup(ehostname); ++ if(!connssl->hostname) { ++ free_hostname(connssl); ++ return CURLE_OUT_OF_MEMORY; + } ++ if(!edispname || !strcmp(ehostname, edispname)) ++ connssl->dispname = connssl->hostname; + else { +- connssl->hostname = cf->conn->host.name; +- connssl->dispname = cf->conn->host.dispname; +- connssl->port = cf->conn->remote_port; ++ connssl->dispname = strdup(edispname); ++ if(!connssl->dispname) { ++ free_hostname(connssl); ++ return CURLE_OUT_OF_MEMORY; ++ } + } + } +- DEBUGASSERT(connssl->hostname); ++ connssl->port = eport; ++ return CURLE_OK; + } + + static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) +@@ -1513,10 +1537,10 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, + if(result || !*done) + goto out; + +- /* TODO: right now we do not fully control when hostname is set, +- * assign it on each connect call. */ +- reinit_hostname(cf); + *done = FALSE; ++ result = reinit_hostname(cf); ++ if(result) ++ goto out; + + if(blocking) { + result = ssl_connect(cf, data); +diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h +index 6710a2b..010c20b 100644 +--- a/lib/vtls/vtls_int.h ++++ b/lib/vtls/vtls_int.h +@@ -33,8 +33,8 @@ + struct ssl_connect_data { + ssl_connection_state state; + ssl_connect_state connecting_state; +- const char *hostname; /* hostnaem for verification */ +- const char *dispname; /* display version of hostname */ ++ char *hostname; /* hostname for verification */ ++ char *dispname; /* display version of hostname */ + int port; /* remote port at origin */ + struct ssl_backend_data *backend; /* vtls backend specific props */ + struct Curl_easy *call_data; /* data handle used in current call, +-- +2.40.1 + diff --git a/curl.spec b/curl.spec index d8ebf77..21fd2a8 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.87.0 -Release: 8%{?dist} +Release: 9%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -25,6 +25,9 @@ Patch6: 0006-curl-7.87.0-hsts-CVEs.patch # fix HTTP multi-header compression denial of service (CVE-2023-23916) Patch7: 0007-curl-7.87.0-CVE-2023-23916.patch +# vtls: fix hostname handling in filters (#2192665) +Patch8: 0008-curl-7.87.0-vtls-hostname.patch + # fix TELNET option IAC injection (CVE-2023-27533) Patch23: 0023-curl-7.87.0-CVE-2023-27533.patch @@ -235,6 +238,7 @@ be installed. %patch3 -p1 %patch6 -p1 %patch7 -p1 +%patch8 -p1 %patch23 -p1 %patch24 -p1 %patch25 -p1 @@ -475,6 +479,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed May 03 2023 Kamil Dudka - 7.87.0-9 +- vtls: fix hostname handling in filters (#2192665) + * Fri Apr 21 2023 Kamil Dudka - 7.87.0-8 - cfilters: use the first non-connected filter (#2185433) From 23fee3d38607b49d63fbbc7e2f374f489b7be184 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 3 May 2023 15:41:31 +0200 Subject: [PATCH 12/29] Resolves: #2192665 - http_proxy: fix memory corruption with http proxy tunneling --- curl.spec | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/curl.spec b/curl.spec index 21fd2a8..9b139d7 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.87.0 -Release: 9%{?dist} +Release: 10%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -28,6 +28,9 @@ Patch7: 0007-curl-7.87.0-CVE-2023-23916.patch # vtls: fix hostname handling in filters (#2192665) Patch8: 0008-curl-7.87.0-vtls-hostname.patch +# http_proxy: fix memory corruption with http proxy tunneling (#2192665) +Patch9: 0009-curl-7.87.0-http-proxy.patch + # fix TELNET option IAC injection (CVE-2023-27533) Patch23: 0023-curl-7.87.0-CVE-2023-27533.patch @@ -239,6 +242,7 @@ be installed. %patch6 -p1 %patch7 -p1 %patch8 -p1 +%patch9 -p1 %patch23 -p1 %patch24 -p1 %patch25 -p1 @@ -479,6 +483,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed May 03 2023 Kamil Dudka - 7.87.0-10 +- http_proxy: fix memory corruption with http proxy tunneling (#2192665) + * Wed May 03 2023 Kamil Dudka - 7.87.0-9 - vtls: fix hostname handling in filters (#2192665) From ac9ca2137b4a7ce3b44ce16dedabe950e183e933 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 3 May 2023 15:46:13 +0200 Subject: [PATCH 13/29] 0009-curl-7.87.0-http-proxy.patch: add forgotten patch --- 0009-curl-7.87.0-http-proxy.patch | 263 ++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 0009-curl-7.87.0-http-proxy.patch diff --git a/0009-curl-7.87.0-http-proxy.patch b/0009-curl-7.87.0-http-proxy.patch new file mode 100644 index 0000000..8fca8a5 --- /dev/null +++ b/0009-curl-7.87.0-http-proxy.patch @@ -0,0 +1,263 @@ +From bc893dea666ffa09fa015f0a585eb62a489749fc Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 5 Jan 2023 09:38:11 +0100 +Subject: [PATCH] http_proxy: do not assign data->req.p.http use local copy + +Avoid the tricky reusing of the data->req.p.http pointer for http proxy +tunneling. + +Fixes #10194 +Closes #10234 + +Upstream-commit: 3f3ddee0665176040b3eaf89a912a922726ecb18 +Signed-off-by: Kamil Dudka +--- + lib/http.c | 32 ++++++++++++++++++-------------- + lib/http.h | 3 +++ + lib/http_proxy.c | 25 +++++++------------------ + lib/rtsp.c | 2 +- + 4 files changed, 29 insertions(+), 33 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index 1b75022..4cf6043 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1256,8 +1256,8 @@ static size_t readmoredata(char *buffer, + size_t nitems, + void *userp) + { +- struct Curl_easy *data = (struct Curl_easy *)userp; +- struct HTTP *http = data->req.p.http; ++ struct HTTP *http = (struct HTTP *)userp; ++ struct Curl_easy *data = http->backup.data; + size_t fullsize = size * nitems; + + if(!http->postsize) +@@ -1309,6 +1309,7 @@ static size_t readmoredata(char *buffer, + */ + CURLcode Curl_buffer_send(struct dynbuf *in, + struct Curl_easy *data, ++ struct HTTP *http, + /* add the number of sent bytes to this + counter */ + curl_off_t *bytes_written, +@@ -1321,7 +1322,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, + char *ptr; + size_t size; + struct connectdata *conn = data->conn; +- struct HTTP *http = data->req.p.http; + size_t sendsize; + curl_socket_t sockfd; + size_t headersize; +@@ -1456,10 +1456,11 @@ CURLcode Curl_buffer_send(struct dynbuf *in, + http->backup.fread_in = data->state.in; + http->backup.postdata = http->postdata; + http->backup.postsize = http->postsize; ++ http->backup.data = data; + + /* set the new pointers for the request-sending */ + data->state.fread_func = (curl_read_callback)readmoredata; +- data->state.in = (void *)data; ++ data->state.in = (void *)http; + http->postdata = ptr; + http->postsize = (curl_off_t)size; + +@@ -1468,7 +1469,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, + + http->send_buffer = *in; /* copy the whole struct */ + http->sending = HTTPSEND_REQUEST; +- + return CURLE_OK; + } + http->sending = HTTPSEND_BODY; +@@ -2359,7 +2359,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + curl_off_t included_body = 0; + #else + /* from this point down, this function should not be used */ +-#define Curl_buffer_send(a,b,c,d,e) CURLE_OK ++#define Curl_buffer_send(a,b,c,d,e,f) CURLE_OK + #endif + CURLcode result = CURLE_OK; + struct HTTP *http = data->req.p.http; +@@ -2403,7 +2403,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + Curl_pgrsSetUploadSize(data, http->postsize); + + /* this sends the buffer and frees all the buffer resources */ +- result = Curl_buffer_send(r, data, &data->info.request_size, 0, ++ result = Curl_buffer_send(r, data, data->req.p.http, ++ &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending PUT request"); +@@ -2424,7 +2425,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + if(result) + return result; + +- result = Curl_buffer_send(r, data, &data->info.request_size, 0, ++ result = Curl_buffer_send(r, data, data->req.p.http, ++ &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); +@@ -2495,7 +2497,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + http->sending = HTTPSEND_BODY; + + /* this sends the buffer and frees all the buffer resources */ +- result = Curl_buffer_send(r, data, &data->info.request_size, 0, ++ result = Curl_buffer_send(r, data, data->req.p.http, ++ &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending POST request"); +@@ -2612,11 +2615,10 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + else { + /* A huge POST coming up, do data separate from the request */ + http->postdata = data->set.postfields; +- + http->sending = HTTPSEND_BODY; +- ++ http->backup.data = data; + data->state.fread_func = (curl_read_callback)readmoredata; +- data->state.in = (void *)data; ++ data->state.in = (void *)http; + + /* set the upload size to the progress meter */ + Curl_pgrsSetUploadSize(data, http->postsize); +@@ -2655,7 +2657,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + } + } + /* issue the request */ +- result = Curl_buffer_send(r, data, &data->info.request_size, included_body, ++ result = Curl_buffer_send(r, data, data->req.p.http, ++ &data->info.request_size, included_body, + FIRSTSOCKET); + + if(result) +@@ -2671,7 +2674,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + return result; + + /* issue the request */ +- result = Curl_buffer_send(r, data, &data->info.request_size, 0, ++ result = Curl_buffer_send(r, data, data->req.p.http, ++ &data->info.request_size, 0, + FIRSTSOCKET); + if(result) + failf(data, "Failed sending HTTP request"); +diff --git a/lib/http.h b/lib/http.h +index ecfe4ee..bd2b5f6 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -73,8 +73,10 @@ char *Curl_checkProxyheaders(struct Curl_easy *data, + const struct connectdata *conn, + const char *thisheader, + const size_t thislen); ++struct HTTP; /* see below */ + CURLcode Curl_buffer_send(struct dynbuf *in, + struct Curl_easy *data, ++ struct HTTP *http, + curl_off_t *bytes_written, + curl_off_t included_body_bytes, + int socketindex); +@@ -220,6 +222,7 @@ struct HTTP { + void *fread_in; /* backup storage for fread_in pointer */ + const char *postdata; + curl_off_t postsize; ++ struct Curl_easy *data; + } backup; + + enum { +diff --git a/lib/http_proxy.c b/lib/http_proxy.c +index e30730a..14f11e9 100644 +--- a/lib/http_proxy.c ++++ b/lib/http_proxy.c +@@ -63,8 +63,7 @@ struct tunnel_state { + int sockindex; + const char *hostname; + int remote_port; +- struct HTTP http_proxy; +- struct HTTP *prot_save; ++ struct HTTP CONNECT; + struct dynbuf rcvbuf; + struct dynbuf req; + size_t nsend; +@@ -149,17 +148,6 @@ static CURLcode tunnel_init(struct tunnel_state **pts, + Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS); + Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST); + +- /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the +- * member conn->proto.http; we want [protocol] through HTTP and we have +- * to change the member temporarily for connecting to the HTTP +- * proxy. After Curl_proxyCONNECT we have to set back the member to the +- * original pointer +- * +- * This function might be called several times in the multi interface case +- * if the proxy's CONNECT response is not instant. +- */ +- ts->prot_save = data->req.p.http; +- data->req.p.http = &ts->http_proxy; + *pts = ts; + connkeep(conn, "HTTP proxy CONNECT"); + return tunnel_reinit(ts, conn, data); +@@ -210,7 +198,6 @@ static void tunnel_go_state(struct Curl_cfilter *cf, + Curl_dyn_reset(&ts->rcvbuf); + Curl_dyn_reset(&ts->req); + /* restore the protocol pointer */ +- data->req.p.http = ts->prot_save; + data->info.httpcode = 0; /* clear it as it might've been used for the + proxy */ + /* If a proxy-authorization header was used for the proxy, then we should +@@ -338,7 +325,8 @@ static CURLcode start_CONNECT(struct Curl_easy *data, + goto out; + + /* Send the connect request to the proxy */ +- result = Curl_buffer_send(&ts->req, data, &data->info.request_size, 0, ++ result = Curl_buffer_send(&ts->req, data, &ts->CONNECT, ++ &data->info.request_size, 0, + ts->sockindex); + ts->headerlines = 0; + +@@ -356,7 +344,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data, + bool *done) + { + struct SingleRequest *k = &data->req; +- struct HTTP *http = data->req.p.http; ++ struct HTTP *http = &ts->CONNECT; + CURLcode result = CURLE_OK; + + if(http->sending != HTTPSEND_REQUEST) +@@ -377,7 +365,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data, + result = Curl_write(data, + conn->writesockfd, /* socket to send to */ + k->upload_fromhere, /* buffer pointer */ +- ts->nsend, /* buffer size */ ++ ts->nsend, /* buffer size */ + &bytes_written); /* actually sent */ + if(result) + goto out; +@@ -1131,8 +1119,9 @@ static int http_proxy_cf_get_select_socks(struct Curl_cfilter *cf, + wait for the socket to become readable to be able to get the + response headers or if we're still sending the request, wait + for write. */ +- if(ts->http_proxy.sending == HTTPSEND_REQUEST) ++ if(ts->CONNECT.sending == HTTPSEND_REQUEST) { + return GETSOCK_WRITESOCK(0); ++ } + return GETSOCK_READSOCK(0); + } + return GETSOCK_WRITESOCK(0); +diff --git a/lib/rtsp.c b/lib/rtsp.c +index 75e620d..80d1cf1 100644 +--- a/lib/rtsp.c ++++ b/lib/rtsp.c +@@ -592,7 +592,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) + } + + /* issue the request */ +- result = Curl_buffer_send(&req_buffer, data, ++ result = Curl_buffer_send(&req_buffer, data, data->req.p.http, + &data->info.request_size, 0, FIRSTSOCKET); + if(result) { + failf(data, "Failed sending RTSP request"); +-- +2.40.1 + From f854769ba434c9fffd92498b590b8d0e29c9a616 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 20 Mar 2023 15:39:59 +0100 Subject: [PATCH 14/29] Resolves: #2192665 - new upstream release - 8.0.1 --- 0001-curl-7.87.0-header-file-regression.patch | 55 -- 0002-curl-7.87.0-tests-tls-srp.patch | 54 -- 0003-curl-7.87.0-cfilters-ostree.patch | 40 -- 0006-curl-7.87.0-hsts-CVEs.patch | 575 ------------------ 0007-curl-7.87.0-CVE-2023-23916.patch | 243 -------- 0008-curl-7.87.0-vtls-hostname.patch | 177 ------ 0009-curl-7.87.0-http-proxy.patch | 263 -------- 0023-curl-7.87.0-CVE-2023-27533.patch | 59 -- 0024-curl-7.87.0-CVE-2023-27534.patch | 126 ---- 0025-curl-7.87.0-CVE-2023-27535.patch | 166 ----- 0026-curl-7.87.0-CVE-2023-27536.patch | 54 -- 0027-curl-7.87.0-CVE-2023-27537.patch | 40 -- 0028-curl-7.87.0-CVE-2023-27538.patch | 30 - curl.spec | 59 +- sources | 4 +- 15 files changed, 7 insertions(+), 1938 deletions(-) delete mode 100644 0001-curl-7.87.0-header-file-regression.patch delete mode 100644 0002-curl-7.87.0-tests-tls-srp.patch delete mode 100644 0003-curl-7.87.0-cfilters-ostree.patch delete mode 100644 0006-curl-7.87.0-hsts-CVEs.patch delete mode 100644 0007-curl-7.87.0-CVE-2023-23916.patch delete mode 100644 0008-curl-7.87.0-vtls-hostname.patch delete mode 100644 0009-curl-7.87.0-http-proxy.patch delete mode 100644 0023-curl-7.87.0-CVE-2023-27533.patch delete mode 100644 0024-curl-7.87.0-CVE-2023-27534.patch delete mode 100644 0025-curl-7.87.0-CVE-2023-27535.patch delete mode 100644 0026-curl-7.87.0-CVE-2023-27536.patch delete mode 100644 0027-curl-7.87.0-CVE-2023-27537.patch delete mode 100644 0028-curl-7.87.0-CVE-2023-27538.patch diff --git a/0001-curl-7.87.0-header-file-regression.patch b/0001-curl-7.87.0-header-file-regression.patch deleted file mode 100644 index 9c479dc..0000000 --- a/0001-curl-7.87.0-header-file-regression.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 613d3c45879636e88b88fcebee48dc77de345291 Mon Sep 17 00:00:00 2001 -From: Patrick Monnerat -Date: Fri, 23 Dec 2022 15:35:27 +0100 -Subject: [PATCH] typecheck: accept expressions for option/info parameters - -As expressions can have side effects, evaluate only once. - -To enable deprecation reporting only once, get rid of the __typeof__ -use to define the local temporary variable and use the target type -(CURLoption/CURLINFO). This also avoids multiple reports on type -conflicts (if some) by the curlcheck_* macros. - -Note that CURLOPT_* and CURLINFO_* symbols may be deprecated, but not -their values: a curl_easy_setopt call with an integer constant as option -will never report a deprecation. - -Reported-by: Thomas Klausner -Fixes #10148 -Closes #10149 - -Upstream-commit: e2aed004302e51cfa5b6ce8c8ab65ef92aa83196 -Signed-off-by: Kamil Dudka ---- - include/curl/typecheck-gcc.h | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h -index bf655bb..85aa8b7 100644 ---- a/include/curl/typecheck-gcc.h -+++ b/include/curl/typecheck-gcc.h -@@ -42,9 +42,8 @@ - */ - #define curl_easy_setopt(handle, option, value) \ - __extension__({ \ -- CURL_IGNORE_DEPRECATION(__typeof__(option) _curl_opt = option;) \ -+ CURLoption _curl_opt = (option); \ - if(__builtin_constant_p(_curl_opt)) { \ -- (void) option; \ - CURL_IGNORE_DEPRECATION( \ - if(curlcheck_long_option(_curl_opt)) \ - if(!curlcheck_long(value)) \ -@@ -120,9 +119,8 @@ - /* wraps curl_easy_getinfo() with typechecking */ - #define curl_easy_getinfo(handle, info, arg) \ - __extension__({ \ -- CURL_IGNORE_DEPRECATION(__typeof__(info) _curl_info = info;) \ -+ CURLINFO _curl_info = (info); \ - if(__builtin_constant_p(_curl_info)) { \ -- (void) info; \ - CURL_IGNORE_DEPRECATION( \ - if(curlcheck_string_info(_curl_info)) \ - if(!curlcheck_arr((arg), char *)) \ --- -2.39.0 - diff --git a/0002-curl-7.87.0-tests-tls-srp.patch b/0002-curl-7.87.0-tests-tls-srp.patch deleted file mode 100644 index f2ad919..0000000 --- a/0002-curl-7.87.0-tests-tls-srp.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 34ba217b433f222f486a42f2157866ab40dba221 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Wed, 15 Feb 2023 15:04:07 +0100 -Subject: [PATCH] tests: make sure gnuserv-tls has SRP support before using it - -Reported-by: fundawang on github -Fixes #10522 -Closes #10524 - -Upstream-commit: 2fdc1d816ebf3c77f43068103bec1b3a3767881a -Signed-off-by: Kamil Dudka ---- - tests/runtests.pl | 2 +- - tests/sshhelp.pm | 11 ++++++++++- - 2 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/tests/runtests.pl b/tests/runtests.pl -index f49e385..d2e0e52 100755 ---- a/tests/runtests.pl -+++ b/tests/runtests.pl -@@ -5373,7 +5373,7 @@ sub startservers { - elsif($what eq "httptls") { - if(!$httptlssrv) { - # for now, we can't run http TLS-EXT tests without gnutls-serv -- return "no gnutls-serv"; -+ return "no gnutls-serv (with SRP support)"; - } - if($torture && $run{'httptls'} && - !responsive_httptls_server($verbose, "IPv4")) { -diff --git a/tests/sshhelp.pm b/tests/sshhelp.pm -index 2d419c1..0c553da 100644 ---- a/tests/sshhelp.pm -+++ b/tests/sshhelp.pm -@@ -408,7 +408,16 @@ sub find_sshkeygen { - # Find httptlssrv (gnutls-serv) and return canonical filename - # - sub find_httptlssrv { -- return find_exe_file_hpath($httptlssrvexe); -+ my $p = find_exe_file_hpath($httptlssrvexe); -+ my @o = `$p -l`; -+ my $found; -+ for(@o) { -+ if(/Key exchange: SRP/) { -+ $found = 1; -+ last; -+ } -+ } -+ return $p if($found); - } - - --- -2.39.2 - diff --git a/0003-curl-7.87.0-cfilters-ostree.patch b/0003-curl-7.87.0-cfilters-ostree.patch deleted file mode 100644 index 8f48861..0000000 --- a/0003-curl-7.87.0-cfilters-ostree.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 4388f4af77c6741873062dc8da5c6cbcef2d5dfd Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Mon, 26 Dec 2022 09:59:20 +0100 -Subject: [PATCH] cfilters:Curl_conn_get_select_socks: use the first - non-connected filter - -When there are filters addded for both socket and SSL, the code -previously checked the SSL sockets during connect when it *should* first -check the socket layer until that has connected. - -Fixes #10157 -Fixes #10146 -Closes #10160 - -Reviewed-by: Stefan Eissing - -Upstream-commit: 728400f875e845f72ee5602edb905f6301ade3e7 -Signed-off-by: Kamil Dudka ---- - lib/cfilters.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/lib/cfilters.c b/lib/cfilters.c -index bcb33da..94471e8 100644 ---- a/lib/cfilters.c -+++ b/lib/cfilters.c -@@ -437,6 +437,10 @@ int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex, - DEBUGASSERT(data); - DEBUGASSERT(data->conn); - cf = data->conn->cfilter[sockindex]; -+ -+ /* if the next one is not yet connected, that's the one we want */ -+ while(cf && cf->next && !cf->next->connected) -+ cf = cf->next; - if(cf) { - return cf->cft->get_select_socks(cf, data, socks); - } --- -2.39.2 - diff --git a/0006-curl-7.87.0-hsts-CVEs.patch b/0006-curl-7.87.0-hsts-CVEs.patch deleted file mode 100644 index 759ece8..0000000 --- a/0006-curl-7.87.0-hsts-CVEs.patch +++ /dev/null @@ -1,575 +0,0 @@ -From 117fce3d4fe11c36a20403cd4d6850e5b8771b41 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Tue, 27 Dec 2022 11:50:20 +0100 -Subject: [PATCH 1/5] share: add sharing of HSTS cache among handles - -Closes #10138 - -Upstream-commit: 076a2f629119222aeeb50f5a03bf9f9052fabb9a -Signed-off-by: Kamil Dudka ---- - docs/libcurl/opts/CURLSHOPT_SHARE.3 | 4 +++ - docs/libcurl/symbols-in-versions | 1 + - include/curl/curl.h | 1 + - lib/hsts.c | 15 +++++++++ - lib/hsts.h | 2 ++ - lib/setopt.c | 48 ++++++++++++++++++++++++----- - lib/share.c | 32 +++++++++++++++++-- - lib/share.h | 6 +++- - lib/transfer.c | 3 ++ - lib/url.c | 6 +++- - lib/urldata.h | 2 ++ - 11 files changed, 109 insertions(+), 11 deletions(-) - -diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3 -index 92783b6..b15af82 100644 ---- a/docs/libcurl/opts/CURLSHOPT_SHARE.3 -+++ b/docs/libcurl/opts/CURLSHOPT_SHARE.3 -@@ -79,6 +79,10 @@ Added in 7.61.0. - - Note that when you use the multi interface, all easy handles added to the same - multi handle will share PSL cache by default without using this option. -+.IP CURL_LOCK_DATA_HSTS -+The in-memory HSTS cache. -+ -+Added in 7.88.0 - .SH PROTOCOLS - All - .SH EXAMPLE -diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions -index 5ee245d..41fffc3 100644 ---- a/docs/libcurl/symbols-in-versions -+++ b/docs/libcurl/symbols-in-versions -@@ -73,6 +73,7 @@ CURL_LOCK_ACCESS_SINGLE 7.10.3 - CURL_LOCK_DATA_CONNECT 7.10.3 - CURL_LOCK_DATA_COOKIE 7.10.3 - CURL_LOCK_DATA_DNS 7.10.3 -+CURL_LOCK_DATA_HSTS 7.88.0 - CURL_LOCK_DATA_NONE 7.10.3 - CURL_LOCK_DATA_PSL 7.61.0 - CURL_LOCK_DATA_SHARE 7.10.4 -diff --git a/include/curl/curl.h b/include/curl/curl.h -index 139df99..5758e3b 100644 ---- a/include/curl/curl.h -+++ b/include/curl/curl.h -@@ -2953,6 +2953,7 @@ typedef enum { - CURL_LOCK_DATA_SSL_SESSION, - CURL_LOCK_DATA_CONNECT, - CURL_LOCK_DATA_PSL, -+ CURL_LOCK_DATA_HSTS, - CURL_LOCK_DATA_LAST - } curl_lock_data; - -diff --git a/lib/hsts.c b/lib/hsts.c -index c449120..339237b 100644 ---- a/lib/hsts.c -+++ b/lib/hsts.c -@@ -39,6 +39,7 @@ - #include "parsedate.h" - #include "fopen.h" - #include "rename.h" -+#include "share.h" - - /* The last 3 #include files should be in this order */ - #include "curl_printf.h" -@@ -551,4 +552,18 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) - return CURLE_OK; - } - -+void Curl_hsts_loadfiles(struct Curl_easy *data) -+{ -+ struct curl_slist *l = data->set.hstslist; -+ if(l) { -+ Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE); -+ -+ while(l) { -+ (void)Curl_hsts_loadfile(data, data->hsts, l->data); -+ l = l->next; -+ } -+ Curl_share_unlock(data, CURL_LOCK_DATA_HSTS); -+ } -+} -+ - #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ -diff --git a/lib/hsts.h b/lib/hsts.h -index 0e36a77..3da7574 100644 ---- a/lib/hsts.h -+++ b/lib/hsts.h -@@ -59,9 +59,11 @@ CURLcode Curl_hsts_loadfile(struct Curl_easy *data, - struct hsts *h, const char *file); - CURLcode Curl_hsts_loadcb(struct Curl_easy *data, - struct hsts *h); -+void Curl_hsts_loadfiles(struct Curl_easy *data); - #else - #define Curl_hsts_cleanup(x) - #define Curl_hsts_loadcb(x,y) CURLE_OK - #define Curl_hsts_save(x,y,z) -+#define Curl_hsts_loadfiles(x) - #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ - #endif /* HEADER_CURL_HSTS_H */ -diff --git a/lib/setopt.c b/lib/setopt.c -index b77e95b..f71a606 100644 ---- a/lib/setopt.c -+++ b/lib/setopt.c -@@ -2260,9 +2260,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) - data->cookies = NULL; - #endif - -+#ifndef CURL_DISABLE_HSTS -+ if(data->share->hsts == data->hsts) -+ data->hsts = NULL; -+#endif -+#ifdef USE_SSL - if(data->share->sslsession == data->state.session) - data->state.session = NULL; -- -+#endif - #ifdef USE_LIBPSL - if(data->psl == &data->share->psl) - data->psl = data->multi? &data->multi->psl: NULL; -@@ -2296,10 +2301,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) - data->cookies = data->share->cookies; - } - #endif /* CURL_DISABLE_HTTP */ -+#ifndef CURL_DISABLE_HSTS -+ if(data->share->hsts) { -+ /* first free the private one if any */ -+ Curl_hsts_cleanup(&data->hsts); -+ data->hsts = data->share->hsts; -+ } -+#endif /* CURL_DISABLE_HTTP */ -+#ifdef USE_SSL - if(data->share->sslsession) { - data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; - data->state.session = data->share->sslsession; - } -+#endif - #ifdef USE_LIBPSL - if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) - data->psl = &data->share->psl; -@@ -3049,19 +3063,39 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) - case CURLOPT_HSTSWRITEDATA: - data->set.hsts_write_userp = va_arg(param, void *); - break; -- case CURLOPT_HSTS: -+ case CURLOPT_HSTS: { -+ struct curl_slist *h; - if(!data->hsts) { - data->hsts = Curl_hsts_init(); - if(!data->hsts) - return CURLE_OUT_OF_MEMORY; - } - argptr = va_arg(param, char *); -- result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr); -- if(result) -- return result; -- if(argptr) -- (void)Curl_hsts_loadfile(data, data->hsts, argptr); -+ if(argptr) { -+ result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr); -+ if(result) -+ return result; -+ /* this needs to build a list of file names to read from, so that it can -+ read them later, as we might get a shared HSTS handle to load them -+ into */ -+ h = curl_slist_append(data->set.hstslist, argptr); -+ if(!h) { -+ curl_slist_free_all(data->set.hstslist); -+ data->set.hstslist = NULL; -+ return CURLE_OUT_OF_MEMORY; -+ } -+ data->set.hstslist = h; /* store the list for later use */ -+ } -+ else { -+ /* clear the list of HSTS files */ -+ curl_slist_free_all(data->set.hstslist); -+ data->set.hstslist = NULL; -+ if(!data->share || !data->share->hsts) -+ /* throw away the HSTS cache unless shared */ -+ Curl_hsts_cleanup(&data->hsts); -+ } - break; -+ } - case CURLOPT_HSTS_CTRL: - arg = va_arg(param, long); - if(arg & CURLHSTS_ENABLE) { -diff --git a/lib/share.c b/lib/share.c -index 1a083e7..69ee00b 100644 ---- a/lib/share.c -+++ b/lib/share.c -@@ -29,9 +29,11 @@ - #include "share.h" - #include "psl.h" - #include "vtls/vtls.h" --#include "curl_memory.h" -+#include "hsts.h" - --/* The last #include file should be: */ -+/* The last 3 #include files should be in this order */ -+#include "curl_printf.h" -+#include "curl_memory.h" - #include "memdebug.h" - - struct Curl_share * -@@ -89,6 +91,18 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) - #endif - break; - -+ case CURL_LOCK_DATA_HSTS: -+#ifndef CURL_DISABLE_HSTS -+ if(!share->hsts) { -+ share->hsts = Curl_hsts_init(); -+ if(!share->hsts) -+ res = CURLSHE_NOMEM; -+ } -+#else /* CURL_DISABLE_HSTS */ -+ res = CURLSHE_NOT_BUILT_IN; -+#endif -+ break; -+ - case CURL_LOCK_DATA_SSL_SESSION: - #ifdef USE_SSL - if(!share->sslsession) { -@@ -141,6 +155,16 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...) - #endif - break; - -+ case CURL_LOCK_DATA_HSTS: -+#ifndef CURL_DISABLE_HSTS -+ if(share->hsts) { -+ Curl_hsts_cleanup(&share->hsts); -+ } -+#else /* CURL_DISABLE_HSTS */ -+ res = CURLSHE_NOT_BUILT_IN; -+#endif -+ break; -+ - case CURL_LOCK_DATA_SSL_SESSION: - #ifdef USE_SSL - Curl_safefree(share->sslsession); -@@ -207,6 +231,10 @@ curl_share_cleanup(struct Curl_share *share) - Curl_cookie_cleanup(share->cookies); - #endif - -+#ifndef CURL_DISABLE_HSTS -+ Curl_hsts_cleanup(&share->hsts); -+#endif -+ - #ifdef USE_SSL - if(share->sslsession) { - size_t i; -diff --git a/lib/share.h b/lib/share.h -index 32be416..2449730 100644 ---- a/lib/share.h -+++ b/lib/share.h -@@ -59,10 +59,14 @@ struct Curl_share { - #ifdef USE_LIBPSL - struct PslCache psl; - #endif -- -+#ifndef CURL_DISABLE_HSTS -+ struct hsts *hsts; -+#endif -+#ifdef USE_SSL - struct Curl_ssl_session *sslsession; - size_t max_ssl_sessions; - long sessionage; -+#endif - }; - - CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, -diff --git a/lib/transfer.c b/lib/transfer.c -index ba0410f..d433117 100644 ---- a/lib/transfer.c -+++ b/lib/transfer.c -@@ -1398,6 +1398,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) - if(data->state.resolve) - result = Curl_loadhostpairs(data); - -+ /* If there is a list of hsts files to read */ -+ Curl_hsts_loadfiles(data); -+ - if(!result) { - /* Allow data->set.use_port to set which port to use. This needs to be - * disabled for example when we follow Location: headers to URLs using -diff --git a/lib/url.c b/lib/url.c -index 3ab63a0..831ae06 100644 ---- a/lib/url.c -+++ b/lib/url.c -@@ -434,7 +434,11 @@ CURLcode Curl_close(struct Curl_easy **datap) - Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]); - Curl_altsvc_cleanup(&data->asi); - Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]); -- Curl_hsts_cleanup(&data->hsts); -+#ifndef CURL_DISABLE_HSTS -+ if(!data->share || !data->share->hsts) -+ Curl_hsts_cleanup(&data->hsts); -+ curl_slist_free_all(data->set.hstslist); /* clean up list */ -+#endif - #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) - Curl_http_auth_cleanup_digest(data); - #endif -diff --git a/lib/urldata.h b/lib/urldata.h -index 3d7545c..5b4b34f 100644 ---- a/lib/urldata.h -+++ b/lib/urldata.h -@@ -1662,6 +1662,8 @@ struct UserDefined { - - void *seek_client; /* pointer to pass to the seek callback */ - #ifndef CURL_DISABLE_HSTS -+ struct curl_slist *hstslist; /* list of HSTS files set by -+ curl_easy_setopt(HSTS) calls */ - curl_hstsread_callback hsts_read; - void *hsts_read_userp; - curl_hstswrite_callback hsts_write; --- -2.39.1 - - -From 32066a5fa8f649da2aa7a4e4e86bc0b73d32212f Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Tue, 27 Dec 2022 11:50:23 +0100 -Subject: [PATCH 2/5] tool_operate: share HSTS between handles - -Upstream-commit: 0bf8b796a0ea98395b390c7807187982215f5c11 -Signed-off-by: Kamil Dudka ---- - src/tool_operate.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/tool_operate.c b/src/tool_operate.c -index 79db063..a5b024e 100644 ---- a/src/tool_operate.c -+++ b/src/tool_operate.c -@@ -2722,6 +2722,7 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[]) - curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); - curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); - curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL); -+ curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS); - - /* Get the required arguments for each operation */ - do { --- -2.39.1 - - -From fe6b64ac33a0994e5f50ef8b3d0916b3a248a7e8 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Tue, 27 Dec 2022 11:50:23 +0100 -Subject: [PATCH 3/5] hsts: handle adding the same host name again - -It will then use the largest expire time of the two entries. - -Upstream-commit: ca02a77f05bd5cef20618c8f741aa48b7be0a648 -Signed-off-by: Kamil Dudka ---- - lib/hsts.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - -diff --git a/lib/hsts.c b/lib/hsts.c -index 339237b..8d6723e 100644 ---- a/lib/hsts.c -+++ b/lib/hsts.c -@@ -426,14 +426,23 @@ static CURLcode hsts_add(struct hsts *h, char *line) - if(2 == rc) { - time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) : - TIME_T_MAX; -- CURLcode result; -+ CURLcode result = CURLE_OK; - char *p = host; - bool subdomain = FALSE; -+ struct stsentry *e; - if(p[0] == '.') { - p++; - subdomain = TRUE; - } -- result = hsts_create(h, p, subdomain, expires); -+ /* only add it if not already present */ -+ e = Curl_hsts(h, p, subdomain); -+ if(!e) -+ result = hsts_create(h, p, subdomain, expires); -+ else { -+ /* the same host name, use the largest expire time */ -+ if(expires > e->expires) -+ e->expires = expires; -+ } - if(result) - return result; - } --- -2.39.1 - - -From c52b93434c65ec8a44193a6f2b833a1efec8f643 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Tue, 27 Dec 2022 11:50:23 +0100 -Subject: [PATCH 4/5] runtests: support crlf="yes" for verify/proxy - -Upstream-commit: dc0725244a3163f1e2d5f51165db3a1a430f3ba0 -Signed-off-by: Kamil Dudka ---- - tests/FILEFORMAT.md | 4 ++-- - tests/runtests.pl | 5 +++++ - 2 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md -index 8143967..be11167 100644 ---- a/tests/FILEFORMAT.md -+++ b/tests/FILEFORMAT.md -@@ -566,7 +566,7 @@ changing protocol data such as port numbers or user-agent strings. - One perl op per line that operates on the protocol dump. This is pretty - advanced. Example: `s/^EPRT .*/EPRT stripped/`. - --### `` -+### `` - - the protocol dump curl should transmit, if `nonewline` is set, we will cut off - the trailing newline of this given data before comparing with the one actually -@@ -576,7 +576,7 @@ comparisons are made. - `crlf=yes` forces the newlines to become CRLF even if not written so in the - test. - --### `` -+### `` - - The protocol dump curl should transmit to an HTTP proxy (when the http-proxy - server is used), if `nonewline` is set, we will cut off the trailing newline -diff --git a/tests/runtests.pl b/tests/runtests.pl -index c6a739e..f49e385 100755 ---- a/tests/runtests.pl -+++ b/tests/runtests.pl -@@ -4744,6 +4744,11 @@ sub singletest { - } - } - -+ if($hash{'crlf'} || -+ ($has_hyper && ($keywords{"HTTP"} || $keywords{"HTTPS"}))) { -+ map subNewlines(0, \$_), @protstrip; -+ } -+ - $res = compare($testnum, $testname, "proxy", \@out, \@protstrip); - if($res) { - return $errorreturncode; --- -2.39.1 - - -From e428f66157caedc1f58ff5206915842937b0950e Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Tue, 27 Dec 2022 11:50:23 +0100 -Subject: [PATCH 5/5] test446: verify hsts with two URLs - -Upstream-commit: ea5aaaa5ede53819f8bc7ae767fc2d13d3704d37 -Signed-off-by: Kamil Dudka ---- - tests/data/Makefile.inc | 2 +- - tests/data/test446 | 84 +++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 85 insertions(+), 1 deletion(-) - create mode 100644 tests/data/test446 - -diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc -index 3e0221a..fb51cd6 100644 ---- a/tests/data/Makefile.inc -+++ b/tests/data/Makefile.inc -@@ -71,7 +71,7 @@ test408 test409 test410 test411 test412 test413 test414 test415 test416 \ - \ - test430 test431 test432 test433 test434 test435 test436 \ - \ --test440 test441 test442 test443 test444 test445 \ -+test440 test441 test442 test443 test444 test445 test446 \ - \ - test490 test491 test492 test493 test494 test495 test496 \ - \ -diff --git a/tests/data/test446 b/tests/data/test446 -new file mode 100644 -index 0000000..0e2dfdc ---- /dev/null -+++ b/tests/data/test446 -@@ -0,0 +1,84 @@ -+ -+ -+ -+ -+HTTP -+HTTP proxy -+HSTS -+trailing-dot -+ -+ -+ -+ -+ -+# we use this as response to a CONNECT -+ -+HTTP/1.1 200 OK -+ -+ -+ -+HTTP/1.1 200 OK -+Content-Length: 6 -+Strict-Transport-Security: max-age=604800 -+ -+-foo- -+ -+ -+HTTP/1.1 200 OK -+Content-Length: 6 -+Strict-Transport-Security: max-age=6048000 -+ -+-baa- -+ -+ -+ -+ -+ -+https -+http-proxy -+ -+ -+HSTS -+proxy -+https -+debug -+ -+ -+CURL_HSTS_HTTP=yes -+CURL_TIME=2000000000 -+ -+ -+ -+HSTS with two URLs -+ -+ -+-x http://%HOSTIP:%PROXYPORT --hsts log/hsts%TESTNUMBER http://this.hsts.example./%TESTNUMBER http://another.example.com/%TESTNUMBER0002 -+ -+ -+ -+ -+# we let it CONNECT to the server to confirm HSTS but deny from there -+ -+GET http://this.hsts.example./%TESTNUMBER HTTP/1.1 -+Host: this.hsts.example. -+User-Agent: curl/%VERSION -+Accept: */* -+Proxy-Connection: Keep-Alive -+ -+GET http://another.example.com/%TESTNUMBER0002 HTTP/1.1 -+Host: another.example.com -+User-Agent: curl/%VERSION -+Accept: */* -+Proxy-Connection: Keep-Alive -+ -+ -+ -+ -+# Your HSTS cache. https://curl.se/docs/hsts.html -+# This file was generated by libcurl! Edit at your own risk. -+this.hsts.example "20330525 03:33:20" -+another.example.com "20330727 03:33:20" -+ -+ -+ -+ --- -2.39.1 - diff --git a/0007-curl-7.87.0-CVE-2023-23916.patch b/0007-curl-7.87.0-CVE-2023-23916.patch deleted file mode 100644 index b82ffc5..0000000 --- a/0007-curl-7.87.0-CVE-2023-23916.patch +++ /dev/null @@ -1,243 +0,0 @@ -From bc5fc958b017895728962c9d44c469418cbec1a0 Mon Sep 17 00:00:00 2001 -From: Patrick Monnerat -Date: Mon, 13 Feb 2023 08:33:09 +0100 -Subject: [PATCH] content_encoding: do not reset stage counter for each header - -Test 418 verifies - -Closes #10492 - -Upstream-commit: 119fb187192a9ea13dc90d9d20c215fc82799ab9 -Signed-off-by: Kamil Dudka ---- - lib/content_encoding.c | 7 +- - lib/urldata.h | 1 + - tests/data/Makefile.inc | 1 + - tests/data/test387 | 2 +- - tests/data/test418 | 152 ++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 158 insertions(+), 5 deletions(-) - create mode 100644 tests/data/test418 - -diff --git a/lib/content_encoding.c b/lib/content_encoding.c -index bfc13e2..94344d6 100644 ---- a/lib/content_encoding.c -+++ b/lib/content_encoding.c -@@ -1045,7 +1045,6 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - const char *enclist, int maybechunked) - { - struct SingleRequest *k = &data->req; -- int counter = 0; - - do { - const char *name; -@@ -1080,9 +1079,9 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - if(!encoding) - encoding = &error_encoding; /* Defer error at stack use. */ - -- if(++counter >= MAX_ENCODE_STACK) { -- failf(data, "Reject response due to %u content encodings", -- counter); -+ if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) { -+ failf(data, "Reject response due to more than %u content encodings", -+ MAX_ENCODE_STACK); - return CURLE_BAD_CONTENT_ENCODING; - } - /* Stack the unencoding stage. */ -diff --git a/lib/urldata.h b/lib/urldata.h -index 5b4b34f..8c8c20b 100644 ---- a/lib/urldata.h -+++ b/lib/urldata.h -@@ -707,6 +707,7 @@ struct SingleRequest { - struct dohdata *doh; /* DoH specific data for this request */ - #endif - unsigned char setcookies; -+ unsigned char writer_stack_depth; /* Unencoding stack depth. */ - BIT(header); /* incoming data has HTTP header */ - BIT(content_range); /* set TRUE if Content-Range: was found */ - BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding -diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc -index fb51cd6..86b6f85 100644 ---- a/tests/data/Makefile.inc -+++ b/tests/data/Makefile.inc -@@ -68,6 +68,7 @@ test380 test381 test383 test384 test385 test386 test387 test388 test389 \ - test390 test391 test392 test393 test394 test395 test396 test397 test398 \ - test399 test400 test401 test402 test403 test404 test405 test406 test407 \ - test408 test409 test410 test411 test412 test413 test414 test415 test416 \ -+ test418 \ - \ - test430 test431 test432 test433 test434 test435 test436 \ - \ -diff --git a/tests/data/test387 b/tests/data/test387 -index 015ec25..644fc7f 100644 ---- a/tests/data/test387 -+++ b/tests/data/test387 -@@ -47,7 +47,7 @@ Accept: */* - 61 - - --curl: (61) Reject response due to 5 content encodings -+curl: (61) Reject response due to more than 5 content encodings - - - -diff --git a/tests/data/test418 b/tests/data/test418 -new file mode 100644 -index 0000000..50e974e ---- /dev/null -+++ b/tests/data/test418 -@@ -0,0 +1,152 @@ -+ -+ -+ -+HTTP -+gzip -+ -+ -+ -+# -+# Server-side -+ -+ -+HTTP/1.1 200 OK -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+Transfer-Encoding: gzip -+ -+-foo- -+ -+ -+ -+# -+# Client-side -+ -+ -+http -+ -+ -+Response with multiple Transfer-Encoding headers -+ -+ -+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS -+ -+ -+ -+# -+# Verify data after the test has been "shot" -+ -+ -+GET /%TESTNUMBER HTTP/1.1 -+Host: %HOSTIP:%HTTPPORT -+User-Agent: curl/%VERSION -+Accept: */* -+ -+ -+ -+# CURLE_BAD_CONTENT_ENCODING is 61 -+ -+61 -+ -+ -+curl: (61) Reject response due to more than 5 content encodings -+ -+ -+ --- -2.39.1 - diff --git a/0008-curl-7.87.0-vtls-hostname.patch b/0008-curl-7.87.0-vtls-hostname.patch deleted file mode 100644 index 24d6a31..0000000 --- a/0008-curl-7.87.0-vtls-hostname.patch +++ /dev/null @@ -1,177 +0,0 @@ -From d12c233950e22052a8541abd69565772c13f832e Mon Sep 17 00:00:00 2001 -From: Stefan Eissing -Date: Tue, 17 Jan 2023 11:21:29 +0100 -Subject: [PATCH] vtls: fix hostname handling in filters - -- Copy the hostname and dispname to ssl_connect_data. - -Use a copy instead of referencing the `connectdata` instance since this -may get free'ed on connection reuse. - -Reported-by: Stefan Talpalaru -Reported-by: sergio-nsk@users.noreply.github.com - -Fixes https://github.com/curl/curl/issues/10273 -Fixes https://github.com/curl/curl/issues/10309 - -Closes https://github.com/curl/curl/pull/10310 - -Upstream-commit: f8da4f2f2d0451dc0a126ae3e5077b4527ccdc86 -Signed-off-by: Kamil Dudka ---- - lib/url.c | 14 ++++++++++ - lib/vtls/vtls.c | 66 ++++++++++++++++++++++++++++++--------------- - lib/vtls/vtls_int.h | 4 +-- - 3 files changed, 61 insertions(+), 23 deletions(-) - -diff --git a/lib/url.c b/lib/url.c -index cbbc7f3..5192204 100644 ---- a/lib/url.c -+++ b/lib/url.c -@@ -3406,6 +3406,20 @@ static void reuse_conn(struct Curl_easy *data, - } - #endif - -+ /* Finding a connection for reuse in the cache matches, among other -+ * things on the "remote-relevant" hostname. This is not necessarily -+ * the authority of the URL, e.g. conn->host. For example: -+ * - we use a proxy (not tunneling). we want to send all requests -+ * that use the same proxy on this connection. -+ * - we have a "connect-to" setting that may redirect the hostname of -+ * a new request to the same remote endpoint of an existing conn. -+ * We want to reuse an existing conn to the remote endpoint. -+ * Since connection reuse does not match on conn->host necessarily, we -+ * switch `existing` conn to `temp` conn's host settings. -+ * TODO: is this correct in the case of TLS connections that have -+ * used the original hostname in SNI to negotiate? Do we send -+ * requests for another host through the different SNI? -+ */ - Curl_free_idnconverted_hostname(&existing->host); - Curl_free_idnconverted_hostname(&existing->conn_to_host); - Curl_safefree(existing->host.rawalloc); -diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c -index 873ee6b..c7ec77a 100644 ---- a/lib/vtls/vtls.c -+++ b/lib/vtls/vtls.c -@@ -1430,47 +1430,71 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, - - #ifdef USE_SSL - -+static void free_hostname(struct ssl_connect_data *connssl) -+{ -+ if(connssl->dispname != connssl->hostname) -+ free(connssl->dispname); -+ free(connssl->hostname); -+ connssl->hostname = connssl->dispname = NULL; -+} -+ - static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) - { - struct ssl_connect_data *connssl = cf->ctx; -- /* TODO: close_one closes BOTH conn->ssl AND conn->proxy_ssl for this -- * sockindex (if in use). Gladly, it is safe to call more than once. */ - if(connssl) { - Curl_ssl->close(cf, data); - connssl->state = ssl_connection_none; -+ free_hostname(connssl); - } - cf->connected = FALSE; - } - --static void reinit_hostname(struct Curl_cfilter *cf) -+static CURLcode reinit_hostname(struct Curl_cfilter *cf) - { - struct ssl_connect_data *connssl = cf->ctx; -+ const char *ehostname, *edispname; -+ int eport; - -+ /* We need the hostname for SNI negotiation. Once handshaked, this -+ * remains the SNI hostname for the TLS connection. But when the -+ * connection is reused, the settings in cf->conn might change. -+ * So we keep a copy of the hostname we use for SNI. -+ */ - #ifndef CURL_DISABLE_PROXY - if(Curl_ssl_cf_is_proxy(cf)) { -- /* TODO: there is not definition for a proxy setup on a secondary conn */ -- connssl->hostname = cf->conn->http_proxy.host.name; -- connssl->dispname = cf->conn->http_proxy.host.dispname; -- connssl->port = cf->conn->http_proxy.port; -+ ehostname = cf->conn->http_proxy.host.name; -+ edispname = cf->conn->http_proxy.host.dispname; -+ eport = cf->conn->http_proxy.port; - } - else - #endif - { -- /* TODO: secondaryhostname is set to the IP address we connect to -- * in the FTP handler, it is assumed that host verification uses the -- * hostname from FIRSTSOCKET */ -- if(cf->sockindex == SECONDARYSOCKET && 0) { -- connssl->hostname = cf->conn->secondaryhostname; -- connssl->dispname = connssl->hostname; -- connssl->port = cf->conn->secondary_port; -+ ehostname = cf->conn->host.name; -+ edispname = cf->conn->host.dispname; -+ eport = cf->conn->remote_port; -+ } -+ -+ /* change if ehostname changed */ -+ if(ehostname && (!connssl->hostname -+ || strcmp(ehostname, connssl->hostname))) { -+ free_hostname(connssl); -+ connssl->hostname = strdup(ehostname); -+ if(!connssl->hostname) { -+ free_hostname(connssl); -+ return CURLE_OUT_OF_MEMORY; - } -+ if(!edispname || !strcmp(ehostname, edispname)) -+ connssl->dispname = connssl->hostname; - else { -- connssl->hostname = cf->conn->host.name; -- connssl->dispname = cf->conn->host.dispname; -- connssl->port = cf->conn->remote_port; -+ connssl->dispname = strdup(edispname); -+ if(!connssl->dispname) { -+ free_hostname(connssl); -+ return CURLE_OUT_OF_MEMORY; -+ } - } - } -- DEBUGASSERT(connssl->hostname); -+ connssl->port = eport; -+ return CURLE_OK; - } - - static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) -@@ -1513,10 +1537,10 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, - if(result || !*done) - goto out; - -- /* TODO: right now we do not fully control when hostname is set, -- * assign it on each connect call. */ -- reinit_hostname(cf); - *done = FALSE; -+ result = reinit_hostname(cf); -+ if(result) -+ goto out; - - if(blocking) { - result = ssl_connect(cf, data); -diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h -index 6710a2b..010c20b 100644 ---- a/lib/vtls/vtls_int.h -+++ b/lib/vtls/vtls_int.h -@@ -33,8 +33,8 @@ - struct ssl_connect_data { - ssl_connection_state state; - ssl_connect_state connecting_state; -- const char *hostname; /* hostnaem for verification */ -- const char *dispname; /* display version of hostname */ -+ char *hostname; /* hostname for verification */ -+ char *dispname; /* display version of hostname */ - int port; /* remote port at origin */ - struct ssl_backend_data *backend; /* vtls backend specific props */ - struct Curl_easy *call_data; /* data handle used in current call, --- -2.40.1 - diff --git a/0009-curl-7.87.0-http-proxy.patch b/0009-curl-7.87.0-http-proxy.patch deleted file mode 100644 index 8fca8a5..0000000 --- a/0009-curl-7.87.0-http-proxy.patch +++ /dev/null @@ -1,263 +0,0 @@ -From bc893dea666ffa09fa015f0a585eb62a489749fc Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Thu, 5 Jan 2023 09:38:11 +0100 -Subject: [PATCH] http_proxy: do not assign data->req.p.http use local copy - -Avoid the tricky reusing of the data->req.p.http pointer for http proxy -tunneling. - -Fixes #10194 -Closes #10234 - -Upstream-commit: 3f3ddee0665176040b3eaf89a912a922726ecb18 -Signed-off-by: Kamil Dudka ---- - lib/http.c | 32 ++++++++++++++++++-------------- - lib/http.h | 3 +++ - lib/http_proxy.c | 25 +++++++------------------ - lib/rtsp.c | 2 +- - 4 files changed, 29 insertions(+), 33 deletions(-) - -diff --git a/lib/http.c b/lib/http.c -index 1b75022..4cf6043 100644 ---- a/lib/http.c -+++ b/lib/http.c -@@ -1256,8 +1256,8 @@ static size_t readmoredata(char *buffer, - size_t nitems, - void *userp) - { -- struct Curl_easy *data = (struct Curl_easy *)userp; -- struct HTTP *http = data->req.p.http; -+ struct HTTP *http = (struct HTTP *)userp; -+ struct Curl_easy *data = http->backup.data; - size_t fullsize = size * nitems; - - if(!http->postsize) -@@ -1309,6 +1309,7 @@ static size_t readmoredata(char *buffer, - */ - CURLcode Curl_buffer_send(struct dynbuf *in, - struct Curl_easy *data, -+ struct HTTP *http, - /* add the number of sent bytes to this - counter */ - curl_off_t *bytes_written, -@@ -1321,7 +1322,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, - char *ptr; - size_t size; - struct connectdata *conn = data->conn; -- struct HTTP *http = data->req.p.http; - size_t sendsize; - curl_socket_t sockfd; - size_t headersize; -@@ -1456,10 +1456,11 @@ CURLcode Curl_buffer_send(struct dynbuf *in, - http->backup.fread_in = data->state.in; - http->backup.postdata = http->postdata; - http->backup.postsize = http->postsize; -+ http->backup.data = data; - - /* set the new pointers for the request-sending */ - data->state.fread_func = (curl_read_callback)readmoredata; -- data->state.in = (void *)data; -+ data->state.in = (void *)http; - http->postdata = ptr; - http->postsize = (curl_off_t)size; - -@@ -1468,7 +1469,6 @@ CURLcode Curl_buffer_send(struct dynbuf *in, - - http->send_buffer = *in; /* copy the whole struct */ - http->sending = HTTPSEND_REQUEST; -- - return CURLE_OK; - } - http->sending = HTTPSEND_BODY; -@@ -2359,7 +2359,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - curl_off_t included_body = 0; - #else - /* from this point down, this function should not be used */ --#define Curl_buffer_send(a,b,c,d,e) CURLE_OK -+#define Curl_buffer_send(a,b,c,d,e,f) CURLE_OK - #endif - CURLcode result = CURLE_OK; - struct HTTP *http = data->req.p.http; -@@ -2403,7 +2403,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - Curl_pgrsSetUploadSize(data, http->postsize); - - /* this sends the buffer and frees all the buffer resources */ -- result = Curl_buffer_send(r, data, &data->info.request_size, 0, -+ result = Curl_buffer_send(r, data, data->req.p.http, -+ &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending PUT request"); -@@ -2424,7 +2425,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - if(result) - return result; - -- result = Curl_buffer_send(r, data, &data->info.request_size, 0, -+ result = Curl_buffer_send(r, data, data->req.p.http, -+ &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); -@@ -2495,7 +2497,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - http->sending = HTTPSEND_BODY; - - /* this sends the buffer and frees all the buffer resources */ -- result = Curl_buffer_send(r, data, &data->info.request_size, 0, -+ result = Curl_buffer_send(r, data, data->req.p.http, -+ &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending POST request"); -@@ -2612,11 +2615,10 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - else { - /* A huge POST coming up, do data separate from the request */ - http->postdata = data->set.postfields; -- - http->sending = HTTPSEND_BODY; -- -+ http->backup.data = data; - data->state.fread_func = (curl_read_callback)readmoredata; -- data->state.in = (void *)data; -+ data->state.in = (void *)http; - - /* set the upload size to the progress meter */ - Curl_pgrsSetUploadSize(data, http->postsize); -@@ -2655,7 +2657,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - } - } - /* issue the request */ -- result = Curl_buffer_send(r, data, &data->info.request_size, included_body, -+ result = Curl_buffer_send(r, data, data->req.p.http, -+ &data->info.request_size, included_body, - FIRSTSOCKET); - - if(result) -@@ -2671,7 +2674,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - return result; - - /* issue the request */ -- result = Curl_buffer_send(r, data, &data->info.request_size, 0, -+ result = Curl_buffer_send(r, data, data->req.p.http, -+ &data->info.request_size, 0, - FIRSTSOCKET); - if(result) - failf(data, "Failed sending HTTP request"); -diff --git a/lib/http.h b/lib/http.h -index ecfe4ee..bd2b5f6 100644 ---- a/lib/http.h -+++ b/lib/http.h -@@ -73,8 +73,10 @@ char *Curl_checkProxyheaders(struct Curl_easy *data, - const struct connectdata *conn, - const char *thisheader, - const size_t thislen); -+struct HTTP; /* see below */ - CURLcode Curl_buffer_send(struct dynbuf *in, - struct Curl_easy *data, -+ struct HTTP *http, - curl_off_t *bytes_written, - curl_off_t included_body_bytes, - int socketindex); -@@ -220,6 +222,7 @@ struct HTTP { - void *fread_in; /* backup storage for fread_in pointer */ - const char *postdata; - curl_off_t postsize; -+ struct Curl_easy *data; - } backup; - - enum { -diff --git a/lib/http_proxy.c b/lib/http_proxy.c -index e30730a..14f11e9 100644 ---- a/lib/http_proxy.c -+++ b/lib/http_proxy.c -@@ -63,8 +63,7 @@ struct tunnel_state { - int sockindex; - const char *hostname; - int remote_port; -- struct HTTP http_proxy; -- struct HTTP *prot_save; -+ struct HTTP CONNECT; - struct dynbuf rcvbuf; - struct dynbuf req; - size_t nsend; -@@ -149,17 +148,6 @@ static CURLcode tunnel_init(struct tunnel_state **pts, - Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS); - Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST); - -- /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the -- * member conn->proto.http; we want [protocol] through HTTP and we have -- * to change the member temporarily for connecting to the HTTP -- * proxy. After Curl_proxyCONNECT we have to set back the member to the -- * original pointer -- * -- * This function might be called several times in the multi interface case -- * if the proxy's CONNECT response is not instant. -- */ -- ts->prot_save = data->req.p.http; -- data->req.p.http = &ts->http_proxy; - *pts = ts; - connkeep(conn, "HTTP proxy CONNECT"); - return tunnel_reinit(ts, conn, data); -@@ -210,7 +198,6 @@ static void tunnel_go_state(struct Curl_cfilter *cf, - Curl_dyn_reset(&ts->rcvbuf); - Curl_dyn_reset(&ts->req); - /* restore the protocol pointer */ -- data->req.p.http = ts->prot_save; - data->info.httpcode = 0; /* clear it as it might've been used for the - proxy */ - /* If a proxy-authorization header was used for the proxy, then we should -@@ -338,7 +325,8 @@ static CURLcode start_CONNECT(struct Curl_easy *data, - goto out; - - /* Send the connect request to the proxy */ -- result = Curl_buffer_send(&ts->req, data, &data->info.request_size, 0, -+ result = Curl_buffer_send(&ts->req, data, &ts->CONNECT, -+ &data->info.request_size, 0, - ts->sockindex); - ts->headerlines = 0; - -@@ -356,7 +344,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data, - bool *done) - { - struct SingleRequest *k = &data->req; -- struct HTTP *http = data->req.p.http; -+ struct HTTP *http = &ts->CONNECT; - CURLcode result = CURLE_OK; - - if(http->sending != HTTPSEND_REQUEST) -@@ -377,7 +365,7 @@ static CURLcode send_CONNECT(struct Curl_easy *data, - result = Curl_write(data, - conn->writesockfd, /* socket to send to */ - k->upload_fromhere, /* buffer pointer */ -- ts->nsend, /* buffer size */ -+ ts->nsend, /* buffer size */ - &bytes_written); /* actually sent */ - if(result) - goto out; -@@ -1131,8 +1119,9 @@ static int http_proxy_cf_get_select_socks(struct Curl_cfilter *cf, - wait for the socket to become readable to be able to get the - response headers or if we're still sending the request, wait - for write. */ -- if(ts->http_proxy.sending == HTTPSEND_REQUEST) -+ if(ts->CONNECT.sending == HTTPSEND_REQUEST) { - return GETSOCK_WRITESOCK(0); -+ } - return GETSOCK_READSOCK(0); - } - return GETSOCK_WRITESOCK(0); -diff --git a/lib/rtsp.c b/lib/rtsp.c -index 75e620d..80d1cf1 100644 ---- a/lib/rtsp.c -+++ b/lib/rtsp.c -@@ -592,7 +592,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) - } - - /* issue the request */ -- result = Curl_buffer_send(&req_buffer, data, -+ result = Curl_buffer_send(&req_buffer, data, data->req.p.http, - &data->info.request_size, 0, FIRSTSOCKET); - if(result) { - failf(data, "Failed sending RTSP request"); --- -2.40.1 - diff --git a/0023-curl-7.87.0-CVE-2023-27533.patch b/0023-curl-7.87.0-CVE-2023-27533.patch deleted file mode 100644 index 8810c27..0000000 --- a/0023-curl-7.87.0-CVE-2023-27533.patch +++ /dev/null @@ -1,59 +0,0 @@ -From c9828d86040737a47da862197b5def7ff6b0e3c4 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Mon, 6 Mar 2023 12:07:33 +0100 -Subject: [PATCH] telnet: only accept option arguments in ascii - -To avoid embedded telnet negotiation commands etc. - -Reported-by: Harry Sintonen -Closes #10728 - -Upstream-commit: 538b1e79a6e7b0bb829ab4cecc828d32105d0684 -Signed-off-by: Kamil Dudka ---- - lib/telnet.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/lib/telnet.c b/lib/telnet.c -index 22bc81e..baea885 100644 ---- a/lib/telnet.c -+++ b/lib/telnet.c -@@ -770,6 +770,17 @@ static void printsub(struct Curl_easy *data, - } - } - -+static bool str_is_nonascii(const char *str) -+{ -+ size_t len = strlen(str); -+ while(len--) { -+ if(*str & 0x80) -+ return TRUE; -+ str++; -+ } -+ return FALSE; -+} -+ - static CURLcode check_telnet_options(struct Curl_easy *data) - { - struct curl_slist *head; -@@ -784,6 +795,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data) - /* Add the user name as an environment variable if it - was given on the command line */ - if(data->state.aptr.user) { -+ if(str_is_nonascii(data->conn->user)) -+ return CURLE_BAD_FUNCTION_ARGUMENT; - msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); - beg = curl_slist_append(tn->telnet_vars, option_arg); - if(!beg) { -@@ -798,6 +811,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data) - for(head = data->set.telnet_options; head; head = head->next) { - if(sscanf(head->data, "%127[^= ]%*[ =]%255s", - option_keyword, option_arg) == 2) { -+ if(str_is_nonascii(option_arg)) -+ continue; - - /* Terminal type */ - if(strcasecompare(option_keyword, "TTYPE")) { --- -2.39.2 - diff --git a/0024-curl-7.87.0-CVE-2023-27534.patch b/0024-curl-7.87.0-CVE-2023-27534.patch deleted file mode 100644 index ea589f3..0000000 --- a/0024-curl-7.87.0-CVE-2023-27534.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 5ebdef4442b438ab1a899edb169489fc259fae1a Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Thu, 9 Mar 2023 16:22:11 +0100 -Subject: [PATCH] curl_path: create the new path with dynbuf - -Closes #10729 - -Upstream-commit: 4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6 -Signed-off-by: Kamil Dudka ---- - lib/curl_path.c | 75 +++++++++++++++++++++++-------------------------- - 1 file changed, 35 insertions(+), 40 deletions(-) - -diff --git a/lib/curl_path.c b/lib/curl_path.c -index f00e3ee..8106042 100644 ---- a/lib/curl_path.c -+++ b/lib/curl_path.c -@@ -32,70 +32,65 @@ - #include "escape.h" - #include "memdebug.h" - -+#define MAX_SSHPATH_LEN 100000 /* arbitrary */ -+ - /* figure out the path to work with in this particular request */ - CURLcode Curl_getworkingpath(struct Curl_easy *data, - char *homedir, /* when SFTP is used */ - char **path) /* returns the allocated - real path to work with */ - { -- char *real_path = NULL; - char *working_path; - size_t working_path_len; -+ struct dynbuf npath; - CURLcode result = - Curl_urldecode(data->state.up.path, 0, &working_path, - &working_path_len, REJECT_ZERO); - if(result) - return result; - -+ /* new path to switch to in case we need to */ -+ Curl_dyn_init(&npath, MAX_SSHPATH_LEN); -+ - /* Check for /~/, indicating relative to the user's home directory */ -- if(data->conn->handler->protocol & CURLPROTO_SCP) { -- real_path = malloc(working_path_len + 1); -- if(!real_path) { -+ if((data->conn->handler->protocol & CURLPROTO_SCP) && -+ (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) { -+ /* It is referenced to the home directory, so strip the leading '/~/' */ -+ if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) { - free(working_path); - return CURLE_OUT_OF_MEMORY; - } -- if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) -- /* It is referenced to the home directory, so strip the leading '/~/' */ -- memcpy(real_path, working_path + 3, working_path_len - 2); -- else -- memcpy(real_path, working_path, 1 + working_path_len); - } -- else if(data->conn->handler->protocol & CURLPROTO_SFTP) { -- if((working_path_len > 1) && (working_path[1] == '~')) { -- size_t homelen = strlen(homedir); -- real_path = malloc(homelen + working_path_len + 1); -- if(!real_path) { -- free(working_path); -- return CURLE_OUT_OF_MEMORY; -- } -- /* It is referenced to the home directory, so strip the -- leading '/' */ -- memcpy(real_path, homedir, homelen); -- /* Only add a trailing '/' if homedir does not end with one */ -- if(homelen == 0 || real_path[homelen - 1] != '/') { -- real_path[homelen] = '/'; -- homelen++; -- real_path[homelen] = '\0'; -- } -- if(working_path_len > 3) { -- memcpy(real_path + homelen, working_path + 3, -- 1 + working_path_len -3); -- } -+ else if((data->conn->handler->protocol & CURLPROTO_SFTP) && -+ (working_path_len > 2) && !memcmp(working_path, "/~/", 3)) { -+ size_t len; -+ const char *p; -+ int copyfrom = 3; -+ if(Curl_dyn_add(&npath, homedir)) { -+ free(working_path); -+ return CURLE_OUT_OF_MEMORY; - } -- else { -- real_path = malloc(working_path_len + 1); -- if(!real_path) { -- free(working_path); -- return CURLE_OUT_OF_MEMORY; -- } -- memcpy(real_path, working_path, 1 + working_path_len); -+ /* Copy a separating '/' if homedir does not end with one */ -+ len = Curl_dyn_len(&npath); -+ p = Curl_dyn_ptr(&npath); -+ if(len && (p[len-1] != '/')) -+ copyfrom = 2; -+ -+ if(Curl_dyn_addn(&npath, -+ &working_path[copyfrom], working_path_len - copyfrom)) { -+ free(working_path); -+ return CURLE_OUT_OF_MEMORY; - } - } - -- free(working_path); -+ if(Curl_dyn_len(&npath)) { -+ free(working_path); - -- /* store the pointer for the caller to receive */ -- *path = real_path; -+ /* store the pointer for the caller to receive */ -+ *path = Curl_dyn_ptr(&npath); -+ } -+ else -+ *path = working_path; - - return CURLE_OK; - } --- -2.39.2 - diff --git a/0025-curl-7.87.0-CVE-2023-27535.patch b/0025-curl-7.87.0-CVE-2023-27535.patch deleted file mode 100644 index 4d3cf52..0000000 --- a/0025-curl-7.87.0-CVE-2023-27535.patch +++ /dev/null @@ -1,166 +0,0 @@ -From b79a0e768fcd71003b33feb5deea697dd0903e48 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Thu, 9 Mar 2023 17:47:06 +0100 -Subject: [PATCH] ftp: add more conditions for connection reuse - -Reported-by: Harry Sintonen -Closes #10730 - -Upstream-commit: 8f4608468b890dce2dad9f91d5607ee7e9c1aba1 -Signed-off-by: Kamil Dudka ---- - lib/ftp.c | 28 ++++++++++++++++++++++++++-- - lib/ftp.h | 5 +++++ - lib/setopt.c | 2 +- - lib/url.c | 16 +++++++++++++++- - lib/urldata.h | 4 ++-- - 5 files changed, 49 insertions(+), 6 deletions(-) - -diff --git a/lib/ftp.c b/lib/ftp.c -index 8f0ac2e..d90509e 100644 ---- a/lib/ftp.c -+++ b/lib/ftp.c -@@ -4069,6 +4069,8 @@ static CURLcode ftp_disconnect(struct Curl_easy *data, - } - - freedirs(ftpc); -+ Curl_safefree(ftpc->account); -+ Curl_safefree(ftpc->alternative_to_user); - Curl_safefree(ftpc->prevpath); - Curl_safefree(ftpc->server_os); - Curl_pp_disconnect(pp); -@@ -4338,11 +4340,31 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, - char *type; - struct FTP *ftp; - CURLcode result = CURLE_OK; -+ struct ftp_conn *ftpc = &conn->proto.ftpc; - -- data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1); -+ ftp = calloc(sizeof(struct FTP), 1); - if(!ftp) - return CURLE_OUT_OF_MEMORY; - -+ /* clone connection related data that is FTP specific */ -+ if(data->set.str[STRING_FTP_ACCOUNT]) { -+ ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]); -+ if(!ftpc->account) { -+ free(ftp); -+ return CURLE_OUT_OF_MEMORY; -+ } -+ } -+ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) { -+ ftpc->alternative_to_user = -+ strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); -+ if(!ftpc->alternative_to_user) { -+ Curl_safefree(ftpc->account); -+ free(ftp); -+ return CURLE_OUT_OF_MEMORY; -+ } -+ } -+ data->req.p.ftp = ftp; -+ - ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ - - /* FTP URLs support an extension like ";type=" that -@@ -4377,7 +4399,9 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, - /* get some initial data into the ftp struct */ - ftp->transfer = PPTRANSFER_BODY; - ftp->downloadsize = 0; -- conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ -+ ftpc->known_filesize = -1; /* unknown size for now */ -+ ftpc->use_ssl = data->set.use_ssl; -+ ftpc->ccc = data->set.ftp_ccc; - - return result; - } -diff --git a/lib/ftp.h b/lib/ftp.h -index 7f6f432..3f33e27 100644 ---- a/lib/ftp.h -+++ b/lib/ftp.h -@@ -119,6 +119,8 @@ struct FTP { - struct */ - struct ftp_conn { - struct pingpong pp; -+ char *account; -+ char *alternative_to_user; - char *entrypath; /* the PWD reply when we logged on */ - char *file; /* url-decoded file name (or path) */ - char **dirs; /* realloc()ed array for path components */ -@@ -148,6 +150,9 @@ struct ftp_conn { - ftpstate state; /* always use ftp.c:state() to change state! */ - ftpstate state_saved; /* transfer type saved to be reloaded after - data connection is established */ -+ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or -+ IMAP or POP3 or others! (type: curl_usessl)*/ -+ unsigned char ccc; /* ccc level for this connection */ - curl_off_t retr_size_saved; /* Size of retrieved file saved */ - char *server_os; /* The target server operating system. */ - curl_off_t known_filesize; /* file size is different from -1, if wildcard -diff --git a/lib/setopt.c b/lib/setopt.c -index f71a606..d1905c6 100644 ---- a/lib/setopt.c -+++ b/lib/setopt.c -@@ -2351,7 +2351,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) - arg = va_arg(param, long); - if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST)) - return CURLE_BAD_FUNCTION_ARGUMENT; -- data->set.use_ssl = (curl_usessl)arg; -+ data->set.use_ssl = (unsigned char)arg; - break; - - case CURLOPT_SSL_OPTIONS: -diff --git a/lib/url.c b/lib/url.c -index 831ae06..3b11b7e 100644 ---- a/lib/url.c -+++ b/lib/url.c -@@ -1352,10 +1352,24 @@ ConnectionExists(struct Curl_easy *data, - (data->state.httpwant < CURL_HTTP_VERSION_2_0)) - continue; - -- if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { -+#ifdef USE_SSH -+ else if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { - if(!ssh_config_matches(needle, check)) - continue; - } -+#endif -+#ifndef CURL_DISABLE_FTP -+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) { -+ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */ -+ if(Curl_timestrcmp(needle->proto.ftpc.account, -+ check->proto.ftpc.account) || -+ Curl_timestrcmp(needle->proto.ftpc.alternative_to_user, -+ check->proto.ftpc.alternative_to_user) || -+ (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) || -+ (needle->proto.ftpc.ccc != check->proto.ftpc.ccc)) -+ continue; -+ } -+#endif - - if((needle->handler->flags&PROTOPT_SSL) - #ifndef CURL_DISABLE_PROXY -diff --git a/lib/urldata.h b/lib/urldata.h -index 8c8c20b..ce90304 100644 ---- a/lib/urldata.h -+++ b/lib/urldata.h -@@ -1750,8 +1750,6 @@ struct UserDefined { - #ifndef CURL_DISABLE_NETRC - unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */ - #endif -- curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or -- IMAP or POP3 or others! */ - unsigned int new_file_perms; /* when creating remote files */ - unsigned int new_directory_perms; /* when creating remote dirs */ - int ssh_auth_types; /* allowed SSH auth types */ -@@ -1810,6 +1808,8 @@ struct UserDefined { - BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some - recipients */ - #endif -+ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or -+ IMAP or POP3 or others! (type: curl_usessl)*/ - unsigned char connect_only; /* make connection/request, then let - application use the socket */ - BIT(is_fread_set); /* has read callback been set to non-NULL? */ --- -2.39.2 - diff --git a/0026-curl-7.87.0-CVE-2023-27536.patch b/0026-curl-7.87.0-CVE-2023-27536.patch deleted file mode 100644 index 268e206..0000000 --- a/0026-curl-7.87.0-CVE-2023-27536.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 9d6dd7bc1dea42ae8e710aeae714e2a2c290de61 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Fri, 10 Mar 2023 09:22:43 +0100 -Subject: [PATCH] url: only reuse connections with same GSS delegation - -Reported-by: Harry Sintonen -Closes #10731 - -Upstream-commit: cb49e67303dbafbab1cebf4086e3ec15b7d56ee5 -Signed-off-by: Kamil Dudka ---- - lib/url.c | 6 ++++++ - lib/urldata.h | 1 + - 2 files changed, 7 insertions(+) - -diff --git a/lib/url.c b/lib/url.c -index 3b11b7e..cbbc7f3 100644 ---- a/lib/url.c -+++ b/lib/url.c -@@ -1345,6 +1345,11 @@ ConnectionExists(struct Curl_easy *data, - } - } - -+ /* GSS delegation differences do not actually affect every connection -+ and auth method, but this check takes precaution before efficiency */ -+ if(needle->gssapi_delegation != check->gssapi_delegation) -+ continue; -+ - /* If multiplexing isn't enabled on the h2 connection and h1 is - explicitly requested, handle it: */ - if((needle->handler->protocol & PROTO_FAMILY_HTTP) && -@@ -1662,6 +1667,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) - conn->fclosesocket = data->set.fclosesocket; - conn->closesocket_client = data->set.closesocket_client; - conn->lastused = Curl_now(); /* used now */ -+ conn->gssapi_delegation = data->set.gssapi_delegation; - - return conn; - error: -diff --git a/lib/urldata.h b/lib/urldata.h -index ce90304..9e16f26 100644 ---- a/lib/urldata.h -+++ b/lib/urldata.h -@@ -1111,6 +1111,7 @@ struct connectdata { - unsigned char ip_version; /* copied from the Curl_easy at creation time */ - unsigned char httpversion; /* the HTTP version*10 reported by the server */ - unsigned char connect_only; -+ unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */ - }; - - /* The end of connectdata. */ --- -2.39.2 - diff --git a/0027-curl-7.87.0-CVE-2023-27537.patch b/0027-curl-7.87.0-CVE-2023-27537.patch deleted file mode 100644 index df90d49..0000000 --- a/0027-curl-7.87.0-CVE-2023-27537.patch +++ /dev/null @@ -1,40 +0,0 @@ -From ed7451520fd1b5da62a5371c07db69bed36a5486 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Thu, 9 Mar 2023 18:01:34 +0100 -Subject: [PATCH] CURLSHOPT_SHARE.3: HSTS sharing is not thread-safe - -Reported-by: Hiroki Kurosawa -Closes #10732 - -Upstream-commit: dca4cdf071be095bcdc7126eaa77a8946ea4790b -Signed-off-by: Kamil Dudka ---- - docs/libcurl/opts/CURLSHOPT_SHARE.3 | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3 -index b15af82..4544160 100644 ---- a/docs/libcurl/opts/CURLSHOPT_SHARE.3 -+++ b/docs/libcurl/opts/CURLSHOPT_SHARE.3 -@@ -57,8 +57,7 @@ implemented until 7.23.0. - Put the connection cache in the share object and make all easy handles using - this share object share the connection cache. - --Note that due to a known bug, it is not safe to share connections this way --between multiple concurrent threads. -+It is not supported to share connections between multiple concurrent threads. - - Connections that are used for HTTP/1.1 Pipelining or HTTP/2 multiplexing only - get additional transfers added to them if the existing connection is held by -@@ -82,6 +81,8 @@ multi handle will share PSL cache by default without using this option. - .IP CURL_LOCK_DATA_HSTS - The in-memory HSTS cache. - -+It is not supported to share the HSTS between multiple concurrent threads. -+ - Added in 7.88.0 - .SH PROTOCOLS - All --- -2.39.2 - diff --git a/0028-curl-7.87.0-CVE-2023-27538.patch b/0028-curl-7.87.0-CVE-2023-27538.patch deleted file mode 100644 index 0fb2fe8..0000000 --- a/0028-curl-7.87.0-CVE-2023-27538.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 133e25afe4b8961b9c12334ee0bd3374db9a1fd4 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Fri, 10 Mar 2023 08:22:51 +0100 -Subject: [PATCH] url: fix the SSH connection reuse check - -Reported-by: Harry Sintonen -Closes #10735 - -Upstream-commit: af369db4d3833272b8ed443f7fcc2e757a0872eb -Signed-off-by: Kamil Dudka ---- - lib/url.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/url.c b/lib/url.c -index 0c31486..3b11b7e 100644 ---- a/lib/url.c -+++ b/lib/url.c -@@ -1353,7 +1353,7 @@ ConnectionExists(struct Curl_easy *data, - continue; - - #ifdef USE_SSH -- else if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { -+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { - if(!ssh_config_matches(needle, check)) - continue; - } --- -2.39.2 - diff --git a/curl.spec b/curl.spec index 9b139d7..db326c9 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl -Version: 7.87.0 -Release: 10%{?dist} +Version: 8.0.1 +Release: 1%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -10,45 +10,6 @@ Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc # which points to the GPG key as of April 7th 2016 of https://daniel.haxx.se/mykey.asc Source2: mykey.asc -# fix regression in a public header file (#2162716) -Patch1: 0001-curl-7.87.0-header-file-regression.patch - -# tests: make sure gnuserv-tls has SRP support before using it -Patch2: 0002-curl-7.87.0-tests-tls-srp.patch - -# cfilters: use the first non-connected filter (#2185433) -Patch3: 0003-curl-7.87.0-cfilters-ostree.patch - -# share HSTS between handles (CVE-2023-23915 CVE-2023-23914) -Patch6: 0006-curl-7.87.0-hsts-CVEs.patch - -# fix HTTP multi-header compression denial of service (CVE-2023-23916) -Patch7: 0007-curl-7.87.0-CVE-2023-23916.patch - -# vtls: fix hostname handling in filters (#2192665) -Patch8: 0008-curl-7.87.0-vtls-hostname.patch - -# http_proxy: fix memory corruption with http proxy tunneling (#2192665) -Patch9: 0009-curl-7.87.0-http-proxy.patch - -# fix TELNET option IAC injection (CVE-2023-27533) -Patch23: 0023-curl-7.87.0-CVE-2023-27533.patch - -# fix SFTP path ~ resolving discrepancy (CVE-2023-27534) -Patch24: 0024-curl-7.87.0-CVE-2023-27534.patch - -# fix FTP too eager connection reuse (CVE-2023-27535) -Patch25: 0025-curl-7.87.0-CVE-2023-27535.patch - -# fix GSS delegation too eager connection re-use (CVE-2023-27536) -Patch26: 0026-curl-7.87.0-CVE-2023-27536.patch - -# fix HSTS double-free (CVE-2023-27537) -Patch27: 0027-curl-7.87.0-CVE-2023-27537.patch - -# fix SSH connection too eager reuse still (CVE-2023-27538) -Patch28: 0028-curl-7.87.0-CVE-2023-27538.patch - # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -236,19 +197,6 @@ be installed. %setup -q # upstream patches -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 -%patch27 -p1 -%patch28 -p1 # Fedora patches %patch101 -p1 @@ -483,6 +431,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed May 03 2023 Kamil Dudka - 8.0.1-1 +- rebase to latest upstream release (#2192665) + * Wed May 03 2023 Kamil Dudka - 7.87.0-10 - http_proxy: fix memory corruption with http proxy tunneling (#2192665) diff --git a/sources b/sources index 7906eb7..fe0a4ce 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (curl-7.87.0.tar.xz) = aa125991592667280dce3788aabe81487cf8c55b0afc59d675cc30b76055bb7114f5380b4a0e3b6461a8f81bf9812fa26d493a85f7e01d84263d484a0d699ee7 -SHA512 (curl-7.87.0.tar.xz.asc) = 0bcc12bafc4ae50d80128af2cf4bf1a1ec6018ebb8d5b9c49f52b51c0c25acc77e820858965656549ef43c1f923f4e5fe75b0a3523623154b4cfb9dc8a1d76e4 +SHA512 (curl-8.0.1.tar.xz) = 3bb777982659ed697ae90f113ff7b65d6ce8ba9fe6a8984cfd6769d2f051a72ba953c911abe234c204ec2cc5a35d68b4d033037fad7fba31bb92a52543f8d13d +SHA512 (curl-8.0.1.tar.xz.asc) = 92c6a0570e9a8a708fe2f717b8b37a68dcb9cd4520ca50c9baafec5891bda103bce2d2dcb67f1387bf11bd7e51e0e64ccd52d196e61d58b598ad3aa1960386cf From a70e47eb40dea3908e69c6afaa85792bf7510239 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 15 Feb 2023 10:46:00 +0100 Subject: [PATCH 15/29] do not fail on warnings in the upstream test driver --- 0104-curl-7.88.0-tests-warnings.patch | 30 +++++++++++++++++++++++++++ curl.spec | 4 ++++ 2 files changed, 34 insertions(+) create mode 100644 0104-curl-7.88.0-tests-warnings.patch diff --git a/0104-curl-7.88.0-tests-warnings.patch b/0104-curl-7.88.0-tests-warnings.patch new file mode 100644 index 0000000..dff89f9 --- /dev/null +++ b/0104-curl-7.88.0-tests-warnings.patch @@ -0,0 +1,30 @@ +From d506d885aa16b4a87acbac082eea41dccdc7b69f Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 15 Feb 2023 10:42:38 +0100 +Subject: [PATCH] Revert "runtests: consider warnings fatal and error on them" + +While it might be useful for upstream developers, it is not so useful +for downstream consumers. + +This reverts upstream commit 22f795c834cfdbacbb1b55426028a581e3cf67a8. +--- + tests/runtests.pl | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tests/runtests.pl b/tests/runtests.pl +index 71644ad18..0cf85c3fe 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -75,8 +75,7 @@ BEGIN { + } + + use strict; +-# Promote all warnings to fatal +-use warnings FATAL => 'all'; ++use warnings; + use Cwd; + use Digest::MD5 qw(md5); + use MIME::Base64; +-- +2.39.1 + diff --git a/curl.spec b/curl.spec index db326c9..1cc3240 100644 --- a/curl.spec +++ b/curl.spec @@ -19,6 +19,9 @@ Patch102: 0102-curl-7.84.0-test3026.patch # test3012: temporarily disable valgrind (#2143040) Patch103: 0103-curl-7.87.0-test3012.patch +# do not fail on warnings in the upstream test driver +Patch104: 0104-curl-7.88.0-tests-warnings.patch + Provides: curl-full = %{version}-%{release} Provides: webclient URL: https://curl.se/ @@ -202,6 +205,7 @@ be installed. %patch101 -p1 %patch102 -p1 %patch103 -p1 +%patch104 -p1 # disable test 1112 (#565305), test 1455 (occasionally fails with 'bind failed # with errno 98: Address already in use' in Koji environment), and test 1801 From 0980c80da7d03d7dd215985777cd1d0144327618 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 15 Feb 2023 12:53:26 +0100 Subject: [PATCH 16/29] add glibc-langpack-en BR needed for test1560 to succeed Suggested-by: Paul Howarth --- curl.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/curl.spec b/curl.spec index 1cc3240..2f5be4a 100644 --- a/curl.spec +++ b/curl.spec @@ -60,6 +60,9 @@ BuildRequires: perl(Pod::Usage) BuildRequires: perl(strict) BuildRequires: perl(warnings) +# needed for test1560 to succeed +BuildRequires: glibc-langpack-en + # gnutls-serv is used by the upstream test-suite BuildRequires: gnutls-utils From 24723f4bdf070044ea46235b002a3d65e854075e Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 21 Apr 2023 14:32:13 +0200 Subject: [PATCH 17/29] curl.spec: apply patches automatically ... to ease maintenance and to avoid the following warning on Fedora Rawhide: ``` warning: %patchN is deprecated (4 usages found), use %patch N (or %patch -P N) ``` --- curl.spec | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/curl.spec b/curl.spec index 2f5be4a..9a3fa7d 100644 --- a/curl.spec +++ b/curl.spec @@ -200,15 +200,7 @@ be installed. %prep %{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' -%setup -q - -# upstream patches - -# Fedora patches -%patch101 -p1 -%patch102 -p1 -%patch103 -p1 -%patch104 -p1 +%autosetup -p1 # disable test 1112 (#565305), test 1455 (occasionally fails with 'bind failed # with errno 98: Address already in use' in Koji environment), and test 1801 @@ -439,6 +431,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Wed May 03 2023 Kamil Dudka - 8.0.1-1 +- apply patches automatically - rebase to latest upstream release (#2192665) * Wed May 03 2023 Kamil Dudka - 7.87.0-10 From e76d3e0e652b69f95a36d5d51367b53bc33f4d6e Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 21 Apr 2023 18:00:44 +0200 Subject: [PATCH 18/29] tests: attempt to fix a conflict on port numbers ... where stunnel listens for legacy HTTPS and HTTP/2, which manifests as a hard-to-explain failure of the following tests: 1630 1631 1632 1904 1941 1945 2050 2055 3028 ``` [...] startnew: perl -I../../tests ../../tests/secureserver.pl --pidfile ".https_server.pid" --logfile "log/https_stunnel.log" --ipv4 --proto https --stunnel "/usr/bin/stunnel" --srcdir "../../tests" --connect 42917 --accept 24642 RUN: HTTPS server is PID 114398 port 24642 * pid https => 114398 114402 [...] startnew: perl -I../../tests ../../tests/secureserver.pl --pidfile ".https2_server.pid" --logfile "log/https2_stunnel.log" --id 2 --ipv4 --proto https --stunnel "/usr/bin/stunnel" --srcdir "../../tests" --connect 36763 --accept 24642 startnew: child process has died, server might start up Warning: http2 server unexpectedly alive RUN: Process with pid 73992 signalled to die RUN: Process with pid 73992 forced to die with SIGKILL == Contents of files in the log/ dir after test 1630 === Start of file http2_server.log 14:01:21.881018 exit_signal_handler: 15 14:01:21.881372 signalled to die 14:01:21.881511 ========> IPv4 sws (port 36763 pid: 73992) exits with signal (15) === End of file http2_server.log === Start of file https2_stunnel.log [ ] Initializing inetd mode configuration [ ] Clients allowed=500 [.] stunnel 5.69 on x86_64-redhat-linux-gnu platform [.] Compiled/running with OpenSSL 3.0.8 7 Feb 2023 [.] Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,FIPS,OCSP,PSK,SNI [ ] errno: (*__errno_location ()) [ ] Initializing inetd mode configuration [.] Reading configuration from file /builddir/build/BUILD/curl-8.0.1/build-minimal/tests/https_stunnel.conf [.] UTF-8 byte order mark not detected [.] FIPS mode disabled [ ] Compression disabled [ ] No PRNG seeding was required [ ] Initializing service [curltest] [ ] Using the default TLS minimum version as specified in crypto policies. Not setting explicitly. [ ] Using the default TLS maximum version as specified in crypto policies. Not setting explicitly [ ] stunnel default security level set: 2 [ ] Ciphers: PROFILE=SYSTEM [ ] TLSv1.3 ciphersuites: TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 [ ] TLS options: 0x2100000 (+0x0, -0x0) [ ] Session resumption enabled [ ] Loading certificate from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem [ ] Certificate loaded from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem [ ] Loading private key from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem [ ] Private key loaded from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem [ ] Private key check succeeded [!] No trusted certificates found [ ] DH initialization needed for DHE-RSA-AES256-GCM-SHA384 [ ] DH initialization [ ] Could not load DH parameters from /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem [ ] Using dynamic DH parameters [ ] ECDH initialization [ ] ECDH initialized with curves X25519:P-256:X448:P-521:P-384 [.] Configuration successful [ ] Deallocating deployed section defaults [ ] Binding service [curltest] [ ] Listening file descriptor created (FD=8) [ ] Setting accept socket options (FD=8) [ ] Option SO_REUSEADDR set on accept socket [.] Binding service [curltest] to 0.0.0.0:24642: Address already in use (98) [ ] Listening file descriptor created (FD=8) [ ] Setting accept socket options (FD=8) [ ] Option SO_REUSEADDR set on accept socket [.] Binding service [curltest] to :::24642: Address already in use (98) [!] Binding service [curltest] failed [ ] Unbinding service [curltest] [ ] Service [curltest] closed [ ] Deallocating deployed section defaults [ ] Deallocating section [curltest] [ ] Initializing inetd mode configuration === End of file https2_stunnel.log ``` --- 0105-curl-8.0.1-tests-stunnel-port.patch | 97 ++++++++++++++++++++++++ curl.spec | 4 + 2 files changed, 101 insertions(+) create mode 100644 0105-curl-8.0.1-tests-stunnel-port.patch diff --git a/0105-curl-8.0.1-tests-stunnel-port.patch b/0105-curl-8.0.1-tests-stunnel-port.patch new file mode 100644 index 0000000..47d1419 --- /dev/null +++ b/0105-curl-8.0.1-tests-stunnel-port.patch @@ -0,0 +1,97 @@ +From c9a1d18e5f8f28b90c1b2fcc1f15699327067e59 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 21 Apr 2023 17:44:10 +0200 +Subject: [PATCH] tests/runtests.pl: attempt to fix a conflict on port numbers + +... where stunnel listens for legacy HTTPS and HTTP/2, which manifests +as a hard-to-explain failure of the following tests: 1630 1631 1632 1904 +1941 1945 2050 2055 3028 +``` +[...] +startnew: perl -I../../tests ../../tests/secureserver.pl --pidfile ".https_server.pid" --logfile "log/https_stunnel.log" --ipv4 --proto https --stunnel "/usr/bin/stunnel" --srcdir "../../tests" --connect 42917 --accept 24642 +RUN: HTTPS server is PID 114398 port 24642 +* pid https => 114398 114402 +[...] +startnew: perl -I../../tests ../../tests/secureserver.pl --pidfile ".https2_server.pid" --logfile "log/https2_stunnel.log" --id 2 --ipv4 --proto https --stunnel "/usr/bin/stunnel" --srcdir "../../tests" --connect 36763 --accept 24642 +startnew: child process has died, server might start up +Warning: http2 server unexpectedly alive +RUN: Process with pid 73992 signalled to die +RUN: Process with pid 73992 forced to die with SIGKILL +== Contents of files in the log/ dir after test 1630 +=== Start of file http2_server.log + 14:01:21.881018 exit_signal_handler: 15 + 14:01:21.881372 signalled to die + 14:01:21.881511 ========> IPv4 sws (port 36763 pid: 73992) exits with signal (15) +=== End of file http2_server.log +=== Start of file https2_stunnel.log + [ ] Initializing inetd mode configuration + [ ] Clients allowed=500 + [.] stunnel 5.69 on x86_64-redhat-linux-gnu platform + [.] Compiled/running with OpenSSL 3.0.8 7 Feb 2023 + [.] Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,FIPS,OCSP,PSK,SNI + [ ] errno: (*__errno_location ()) + [ ] Initializing inetd mode configuration + [.] Reading configuration from file /builddir/build/BUILD/curl-8.0.1/build-minimal/tests/https_stunnel.conf + [.] UTF-8 byte order mark not detected + [.] FIPS mode disabled + [ ] Compression disabled + [ ] No PRNG seeding was required + [ ] Initializing service [curltest] + [ ] Using the default TLS minimum version as specified in crypto policies. Not setting explicitly. + [ ] Using the default TLS maximum version as specified in crypto policies. Not setting explicitly + [ ] stunnel default security level set: 2 + [ ] Ciphers: PROFILE=SYSTEM + [ ] TLSv1.3 ciphersuites: TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 + [ ] TLS options: 0x2100000 (+0x0, -0x0) + [ ] Session resumption enabled + [ ] Loading certificate from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Certificate loaded from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Loading private key from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Private key loaded from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Private key check succeeded + [!] No trusted certificates found + [ ] DH initialization needed for DHE-RSA-AES256-GCM-SHA384 + [ ] DH initialization + [ ] Could not load DH parameters from /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Using dynamic DH parameters + [ ] ECDH initialization + [ ] ECDH initialized with curves X25519:P-256:X448:P-521:P-384 + [.] Configuration successful + [ ] Deallocating deployed section defaults + [ ] Binding service [curltest] + [ ] Listening file descriptor created (FD=8) + [ ] Setting accept socket options (FD=8) + [ ] Option SO_REUSEADDR set on accept socket + [.] Binding service [curltest] to 0.0.0.0:24642: Address already in use (98) + [ ] Listening file descriptor created (FD=8) + [ ] Setting accept socket options (FD=8) + [ ] Option SO_REUSEADDR set on accept socket + [.] Binding service [curltest] to :::24642: Address already in use (98) + [!] Binding service [curltest] failed + [ ] Unbinding service [curltest] + [ ] Service [curltest] closed + [ ] Deallocating deployed section defaults + [ ] Deallocating section [curltest] + [ ] Initializing inetd mode configuration +=== End of file https2_stunnel.log +``` +--- + tests/runtests.pl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/runtests.pl b/tests/runtests.pl +index 54f6923..bb362c9 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -1802,7 +1802,7 @@ sub runhttpsserver { + + my $pid2; + my $httpspid; +- my $port = 24512; # start attempt ++ my $port = 24512 * $idnum; # start attempt + for (1 .. 10) { + $port += int(rand(600)); + my $options = "$flags --accept $port"; +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 9a3fa7d..e79c83c 100644 --- a/curl.spec +++ b/curl.spec @@ -22,6 +22,9 @@ Patch103: 0103-curl-7.87.0-test3012.patch # do not fail on warnings in the upstream test driver Patch104: 0104-curl-7.88.0-tests-warnings.patch +# tests: attempt to fix a conflict on port numbers +Patch105: 0105-curl-8.0.1-tests-stunnel-port.patch + Provides: curl-full = %{version}-%{release} Provides: webclient URL: https://curl.se/ @@ -431,6 +434,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Wed May 03 2023 Kamil Dudka - 8.0.1-1 +- tests: attempt to fix a conflict on port numbers - apply patches automatically - rebase to latest upstream release (#2192665) From c2176d668adf421991074089d6752e181a9d1b50 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 21 Apr 2023 18:01:25 +0200 Subject: [PATCH 19/29] tests: re-enable temporarily disabled test-cases --- curl.spec | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/curl.spec b/curl.spec index e79c83c..3b1e1e5 100644 --- a/curl.spec +++ b/curl.spec @@ -205,35 +205,9 @@ be installed. %{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' %autosetup -p1 -# disable test 1112 (#565305), test 1455 (occasionally fails with 'bind failed -# with errno 98: Address already in use' in Koji environment), and test 1801 +# disable test 1801 # -printf "1112\n1455\n1184\n1801\n" >> tests/data/DISABLED - -# disable test 1319 on ppc64 (server times out) -%ifarch ppc64 -echo "1319" >> tests/data/DISABLED -%endif - -# disable tests 320..322 on ppc64le where it started to hang/fail -%ifarch ppc64le -printf "320\n321\n322\n" >> tests/data/DISABLED -%endif - -# temporarily disable tests 582 and 1452 on s390x (client times out) -%ifarch s390x -printf "582\n1452\n" >> tests/data/DISABLED -%endif - -# temporarily disable tests 702 703 716 on armv7hl (#1829180) -%ifarch armv7hl -printf "702\n703\n716\n" >> tests/data/DISABLED -%endif - -# temporarily disable tests 300{0,1} on x86_64 (stunnel clashes with itself) -%ifarch x86_64 -printf "3000\n3001\n" >> tests/data/DISABLED -%endif +echo "1801" >> tests/data/DISABLED # test3026: avoid pthread_create() failure due to resource exhaustion on i386 %ifarch %{ix86} @@ -434,6 +408,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Wed May 03 2023 Kamil Dudka - 8.0.1-1 +- tests: re-enable temporarily disabled test-cases - tests: attempt to fix a conflict on port numbers - apply patches automatically - rebase to latest upstream release (#2192665) From 3ce778ed47eec817969b48efed9dda8fd6e58d8b Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Mon, 5 Jun 2023 08:29:08 +0200 Subject: [PATCH 20/29] Resolves: CVE-2023-28322 - fix more POST-after-PUT confusion --- 0001-curl-8.0.1-CVE-2023-28322.patch | 437 +++++++++++++++++++++++++++ curl.spec | 8 +- 2 files changed, 444 insertions(+), 1 deletion(-) create mode 100644 0001-curl-8.0.1-CVE-2023-28322.patch diff --git a/0001-curl-8.0.1-CVE-2023-28322.patch b/0001-curl-8.0.1-CVE-2023-28322.patch new file mode 100644 index 0000000..133ef63 --- /dev/null +++ b/0001-curl-8.0.1-CVE-2023-28322.patch @@ -0,0 +1,437 @@ +From 074adec63f0dd7a8f0d823ee503dfb0626061505 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 25 Apr 2023 08:28:01 +0200 +Subject: [PATCH] lib: unify the upload/method handling + +By making sure we set state.upload based on the set.method value and not +independently as set.upload, we reduce confusion and mixup risks, both +internally and externally. + +Closes #11017 + +(cherry picked from commit 7815647d6582c0a4900be2e1de6c5e61272c496b) +Signed-off-by: Jan Macku +--- + lib/curl_rtmp.c | 4 ++-- + lib/file.c | 4 ++-- + lib/ftp.c | 8 ++++---- + lib/http.c | 4 ++-- + lib/imap.c | 6 +++--- + lib/rtsp.c | 4 ++-- + lib/setopt.c | 6 ++---- + lib/smb.c | 6 +++--- + lib/smtp.c | 4 ++-- + lib/tftp.c | 8 ++++---- + lib/transfer.c | 4 ++-- + lib/urldata.h | 2 +- + lib/vssh/libssh.c | 6 +++--- + lib/vssh/libssh2.c | 6 +++--- + lib/vssh/wolfssh.c | 2 +- + 15 files changed, 36 insertions(+), 38 deletions(-) + +diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c +index 2679a2cdc..406fb42ac 100644 +--- a/lib/curl_rtmp.c ++++ b/lib/curl_rtmp.c +@@ -231,7 +231,7 @@ static CURLcode rtmp_connect(struct Curl_easy *data, bool *done) + /* We have to know if it's a write before we send the + * connect request packet + */ +- if(data->set.upload) ++ if(data->state.upload) + r->Link.protocol |= RTMP_FEATURE_WRITE; + + /* For plain streams, use the buffer toggle trick to keep data flowing */ +@@ -263,7 +263,7 @@ static CURLcode rtmp_do(struct Curl_easy *data, bool *done) + if(!RTMP_ConnectStream(r, 0)) + return CURLE_FAILED_INIT; + +- if(data->set.upload) { ++ if(data->state.upload) { + Curl_pgrsSetUploadSize(data, data->state.infilesize); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); + } +diff --git a/lib/file.c b/lib/file.c +index 51c5d07ce..c751e8861 100644 +--- a/lib/file.c ++++ b/lib/file.c +@@ -240,7 +240,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done) + file->freepath = real_path; /* free this when done */ + + file->fd = fd; +- if(!data->set.upload && (fd == -1)) { ++ if(!data->state.upload && (fd == -1)) { + failf(data, "Couldn't open file %s", data->state.up.path); + file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE); + return CURLE_FILE_COULDNT_READ_FILE; +@@ -422,7 +422,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) + + Curl_pgrsStartNow(data); + +- if(data->set.upload) ++ if(data->state.upload) + return file_upload(data); + + file = data->req.p.file; +diff --git a/lib/ftp.c b/lib/ftp.c +index caf33d214..0b6e5cd4f 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1350,7 +1350,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data) + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->state.list_only?"NLST":"LIST")); +- else if(data->set.upload) ++ else if(data->state.upload) + result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", + conn->proto.ftpc.file); + else +@@ -3386,7 +3386,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, + /* the response code from the transfer showed an error already so no + use checking further */ + ; +- else if(data->set.upload) { ++ else if(data->state.upload) { + if((-1 != data->state.infilesize) && + (data->state.infilesize != data->req.writebytecount) && + !data->set.crlf && +@@ -3642,7 +3642,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) + connected back to us */ + } + } +- else if(data->set.upload) { ++ else if(data->state.upload) { + result = ftp_nb_type(data, conn, data->state.prefer_ascii, + FTP_STOR_TYPE); + if(result) +@@ -4231,7 +4231,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data) + ftpc->file = NULL; /* instead of point to a zero byte, + we make it a NULL pointer */ + +- if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) { ++ if(data->state.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) { + /* We need a file name when uploading. Return error! */ + failf(data, "Uploading to a URL without a file name"); + free(rawPath); +diff --git a/lib/http.c b/lib/http.c +index faa486cc6..400d2b081 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1960,7 +1960,7 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, + Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq; + const char *request; + if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && +- data->set.upload) ++ data->state.upload) + httpreq = HTTPREQ_PUT; + + /* Now set the 'request' pointer to the proper request string */ +@@ -2277,7 +2277,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn, + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && + (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) && + http->postsize < 0) || +- ((data->set.upload || httpreq == HTTPREQ_POST) && ++ ((data->state.upload || httpreq == HTTPREQ_POST) && + data->state.infilesize == -1))) { + if(conn->bits.authneg) + /* don't enable chunked during auth neg */ +diff --git a/lib/imap.c b/lib/imap.c +index c2f675d4b..1952e66a1 100644 +--- a/lib/imap.c ++++ b/lib/imap.c +@@ -1511,11 +1511,11 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status, + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && !imap->custom && +- (imap->uid || imap->mindex || data->set.upload || ++ (imap->uid || imap->mindex || data->state.upload || + data->set.mimepost.kind != MIMEKIND_NONE)) { + /* Handle responses after FETCH or APPEND transfer has finished */ + +- if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE) ++ if(!data->state.upload && data->set.mimepost.kind == MIMEKIND_NONE) + state(data, IMAP_FETCH_FINAL); + else { + /* End the APPEND command first by sending an empty line */ +@@ -1581,7 +1581,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, + selected = TRUE; + + /* Start the first command in the DO phase */ +- if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE) ++ if(data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE) + /* APPEND can be executed directly */ + result = imap_perform_append(data); + else if(imap->custom && (selected || !imap->mailbox)) +diff --git a/lib/rtsp.c b/lib/rtsp.c +index aef3560a9..6df3706b5 100644 +--- a/lib/rtsp.c ++++ b/lib/rtsp.c +@@ -495,7 +495,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) + rtspreq == RTSPREQ_SET_PARAMETER || + rtspreq == RTSPREQ_GET_PARAMETER) { + +- if(data->set.upload) { ++ if(data->state.upload) { + putsize = data->state.infilesize; + data->state.httpreq = HTTPREQ_PUT; + +@@ -514,7 +514,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) + result = + Curl_dyn_addf(&req_buffer, + "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", +- (data->set.upload ? putsize : postsize)); ++ (data->state.upload ? putsize : postsize)); + if(result) + return result; + } +diff --git a/lib/setopt.c b/lib/setopt.c +index 6bb88791c..2cbaf898a 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -329,8 +329,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + * We want to sent data to the remote host. If this is HTTP, that equals + * using the PUT request. + */ +- data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE; +- if(data->set.upload) { ++ arg = va_arg(param, long); ++ if(arg) { + /* If this is HTTP, PUT is what's needed to "upload" */ + data->set.method = HTTPREQ_PUT; + data->set.opt_no_body = FALSE; /* this is implied */ +@@ -660,7 +660,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + } + else + data->set.method = HTTPREQ_GET; +- data->set.upload = FALSE; + break; + + #ifndef CURL_DISABLE_MIME +@@ -884,7 +883,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + */ + if(va_arg(param, long)) { + data->set.method = HTTPREQ_GET; +- data->set.upload = FALSE; /* switch off upload */ + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; +diff --git a/lib/smb.c b/lib/smb.c +index 076200472..2baf764fa 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -530,7 +530,7 @@ static CURLcode smb_send_open(struct Curl_easy *data) + byte_count = strlen(req->path); + msg.name_length = smb_swap16((unsigned short)byte_count); + msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); +- if(data->set.upload) { ++ if(data->state.upload) { + msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); + msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); + } +@@ -762,7 +762,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) + void *msg = NULL; + const struct smb_nt_create_response *smb_m; + +- if(data->set.upload && (data->state.infilesize < 0)) { ++ if(data->state.upload && (data->state.infilesize < 0)) { + failf(data, "SMB upload needs to know the size up front"); + return CURLE_SEND_ERROR; + } +@@ -813,7 +813,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) + smb_m = (const struct smb_nt_create_response*) msg; + req->fid = smb_swap16(smb_m->fid); + data->req.offset = 0; +- if(data->set.upload) { ++ if(data->state.upload) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->req.size); + next_state = SMB_UPLOAD; +diff --git a/lib/smtp.c b/lib/smtp.c +index 7a030308d..c182cace7 100644 +--- a/lib/smtp.c ++++ b/lib/smtp.c +@@ -1419,7 +1419,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status, + result = status; /* use the already set error code */ + } + else if(!data->set.connect_only && data->set.mail_rcpt && +- (data->set.upload || data->set.mimepost.kind)) { ++ (data->state.upload || data->set.mimepost.kind)) { + /* Calculate the EOB taking into account any terminating CRLF from the + previous line of the email or the CRLF of the DATA command when there + is "no mail data". RFC-5321, sect. 4.1.1.4. +@@ -1511,7 +1511,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected, + smtp->eob = 2; + + /* Start the first command in the DO phase */ +- if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt) ++ if((data->state.upload || data->set.mimepost.kind) && data->set.mail_rcpt) + /* MAIL transfer */ + result = smtp_perform_mail(data); + else +diff --git a/lib/tftp.c b/lib/tftp.c +index 164d3c723..8ed1b887b 100644 +--- a/lib/tftp.c ++++ b/lib/tftp.c +@@ -370,7 +370,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, + + /* tsize should be ignored on upload: Who cares about the size of the + remote file? */ +- if(!data->set.upload) { ++ if(!data->state.upload) { + if(!tsize) { + failf(data, "invalid tsize -:%s:- value in OACK packet", value); + return CURLE_TFTP_ILLEGAL; +@@ -451,7 +451,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, + return result; + } + +- if(data->set.upload) { ++ if(data->state.upload) { + /* If we are uploading, send an WRQ */ + setpacketevent(&state->spacket, TFTP_EVENT_WRQ); + state->data->req.upload_fromhere = +@@ -486,7 +486,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, + if(!data->set.tftp_no_options) { + char buf[64]; + /* add tsize option */ +- if(data->set.upload && (data->state.infilesize != -1)) ++ if(data->state.upload && (data->state.infilesize != -1)) + msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, + data->state.infilesize); + else +@@ -540,7 +540,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state, + break; + + case TFTP_EVENT_OACK: +- if(data->set.upload) { ++ if(data->state.upload) { + result = tftp_connect_for_tx(state, event); + } + else { +diff --git a/lib/transfer.c b/lib/transfer.c +index a28395233..85910455c 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1294,6 +1294,7 @@ void Curl_init_CONNECT(struct Curl_easy *data) + { + data->state.fread_func = data->set.fread_func_set; + data->state.in = data->set.in_set; ++ data->state.upload = (data->state.httpreq == HTTPREQ_PUT); + } + + /* +@@ -1728,7 +1729,6 @@ CURLcode Curl_follow(struct Curl_easy *data, + data->state.httpreq != HTTPREQ_POST_MIME) || + !(data->set.keep_post & CURL_REDIR_POST_303))) { + data->state.httpreq = HTTPREQ_GET; +- data->set.upload = false; + infof(data, "Switch to %s", + data->req.no_body?"HEAD":"GET"); + } +@@ -1766,7 +1766,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) + + /* if we're talking upload, we can't do the checks below, unless the protocol + is HTTP as when uploading over HTTP we will still get a response */ +- if(data->set.upload && ++ if(data->state.upload && + !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP))) + return CURLE_OK; + +diff --git a/lib/urldata.h b/lib/urldata.h +index 8b54518d2..f3e782ad3 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1446,6 +1446,7 @@ struct UrlState { + BIT(rewindbeforesend);/* TRUE when the sending couldn't be stopped even + though it will be discarded. We must call the data + rewind callback before trying to send again. */ ++ BIT(upload); /* upload request */ + }; + + /* +@@ -1822,7 +1823,6 @@ struct UserDefined { + BIT(http_auto_referer); /* set "correct" referer when following + location: */ + BIT(opt_no_body); /* as set with CURLOPT_NOBODY */ +- BIT(upload); /* upload request */ + BIT(verbose); /* output verbosity */ + BIT(krb); /* Kerberos connection requested */ + BIT(reuse_forbid); /* forbidden to be reused, close after use */ +diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c +index b31f741ba..d60edaa30 100644 +--- a/lib/vssh/libssh.c ++++ b/lib/vssh/libssh.c +@@ -1209,7 +1209,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) + } + + case SSH_SFTP_TRANS_INIT: +- if(data->set.upload) ++ if(data->state.upload) + state(data, SSH_SFTP_UPLOAD_INIT); + else { + if(protop->path[strlen(protop->path)-1] == '/') +@@ -1802,7 +1802,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) + /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */ + ssh_set_blocking(sshc->ssh_session, 1); + +- if(data->set.upload) { ++ if(data->state.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; +@@ -1907,7 +1907,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) + break; + } + case SSH_SCP_DONE: +- if(data->set.upload) ++ if(data->state.upload) + state(data, SSH_SCP_SEND_EOF); + else + state(data, SSH_SCP_CHANNEL_FREE); +diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c +index f1154dc47..f2e5352d1 100644 +--- a/lib/vssh/libssh2.c ++++ b/lib/vssh/libssh2.c +@@ -2019,7 +2019,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) + } + + case SSH_SFTP_TRANS_INIT: +- if(data->set.upload) ++ if(data->state.upload) + state(data, SSH_SFTP_UPLOAD_INIT); + else { + if(sshp->path[strlen(sshp->path)-1] == '/') +@@ -2691,7 +2691,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) + break; + } + +- if(data->set.upload) { ++ if(data->state.upload) { + if(data->state.infilesize < 0) { + failf(data, "SCP requires a known file size for upload"); + sshc->actualcode = CURLE_UPLOAD_FAILED; +@@ -2831,7 +2831,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block) + break; + + case SSH_SCP_DONE: +- if(data->set.upload) ++ if(data->state.upload) + state(data, SSH_SCP_SEND_EOF); + else + state(data, SSH_SCP_CHANNEL_FREE); +diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c +index 17d59ecd2..2ca91b736 100644 +--- a/lib/vssh/wolfssh.c ++++ b/lib/vssh/wolfssh.c +@@ -557,7 +557,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) + } + break; + case SSH_SFTP_TRANS_INIT: +- if(data->set.upload) ++ if(data->state.upload) + state(data, SSH_SFTP_UPLOAD_INIT); + else { + if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') +-- +2.40.1 + diff --git a/curl.spec b/curl.spec index 3b1e1e5..ae2c45c 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.0.1 -Release: 1%{?dist} +Release: 2%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -10,6 +10,9 @@ Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc # which points to the GPG key as of April 7th 2016 of https://daniel.haxx.se/mykey.asc Source2: mykey.asc +# fix more POST-after-PUT confusion (CVE-2023-28322) +Patch1: 0001-curl-8.0.1-CVE-2023-28322.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -407,6 +410,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Mon Jun 05 2023 Jan Macku - 8.0.1-2 +- fix more POST-after-PUT confusion (CVE-2023-28322) + * Wed May 03 2023 Kamil Dudka - 8.0.1-1 - tests: re-enable temporarily disabled test-cases - tests: attempt to fix a conflict on port numbers From 0d582aa92f47ef275b1d103a96ef5c71a3632082 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Mon, 5 Jun 2023 08:43:27 +0200 Subject: [PATCH 21/29] Resolves: CVE-2023-28321 - fix IDN wildcard match --- 0002-curl-8.0.1-CVE-2023-28321.patch | 498 +++++++++++++++++++++++++++ curl.spec | 4 + 2 files changed, 502 insertions(+) create mode 100644 0002-curl-8.0.1-CVE-2023-28321.patch diff --git a/0002-curl-8.0.1-CVE-2023-28321.patch b/0002-curl-8.0.1-CVE-2023-28321.patch new file mode 100644 index 0000000..a69fdbd --- /dev/null +++ b/0002-curl-8.0.1-CVE-2023-28321.patch @@ -0,0 +1,498 @@ +From 9cfc8e3107920116ac31ab1fbf6439d38ab2f30e Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 24 Apr 2023 21:07:02 +0200 +Subject: [PATCH] hostcheck: fix host name wildcard checking + +The leftmost "label" of the host name can now only match against single +'*'. Like the browsers have worked for a long time. + +- extended unit test 1397 for this +- move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc + +Reported-by: Hiroki Kurosawa +Closes #11018 + +(cherry picked from commit 199f2d440d8659b42670c1b796220792b01a97bf) +Signed-off-by: Jan Macku +--- + lib/vtls/hostcheck.c | 50 +++++++-------- + tests/data/test1397 | 10 ++- + tests/unit/Makefile.am | 88 -------------------------- + tests/unit/Makefile.inc | 94 ++++++++++++++++++++++++++++ + tests/unit/unit1397.c | 134 ++++++++++++++++++++++++---------------- + 5 files changed, 202 insertions(+), 174 deletions(-) + +diff --git a/lib/vtls/hostcheck.c b/lib/vtls/hostcheck.c +index e827dc58f..d061c6356 100644 +--- a/lib/vtls/hostcheck.c ++++ b/lib/vtls/hostcheck.c +@@ -71,7 +71,12 @@ static bool pmatch(const char *hostname, size_t hostlen, + * apparent distinction between a name and an IP. We need to detect the use of + * an IP address and not wildcard match on such names. + * ++ * Only match on "*" being used for the leftmost label, not "a*", "a*b" nor ++ * "*b". ++ * + * Return TRUE on a match. FALSE if not. ++ * ++ * @unittest: 1397 + */ + + static bool hostmatch(const char *hostname, +@@ -79,53 +84,42 @@ static bool hostmatch(const char *hostname, + const char *pattern, + size_t patternlen) + { +- const char *pattern_label_end, *wildcard, *hostname_label_end; +- size_t prefixlen, suffixlen; ++ const char *pattern_label_end; + +- /* normalize pattern and hostname by stripping off trailing dots */ ++ DEBUGASSERT(pattern); + DEBUGASSERT(patternlen); ++ DEBUGASSERT(hostname); ++ DEBUGASSERT(hostlen); ++ ++ /* normalize pattern and hostname by stripping off trailing dots */ + if(hostname[hostlen-1]=='.') + hostlen--; + if(pattern[patternlen-1]=='.') + patternlen--; + +- wildcard = memchr(pattern, '*', patternlen); +- if(!wildcard) ++ if(strncmp(pattern, "*.", 2)) + return pmatch(hostname, hostlen, pattern, patternlen); + + /* detect IP address as hostname and fail the match if so */ +- if(Curl_host_is_ipnum(hostname)) ++ else if(Curl_host_is_ipnum(hostname)) + return FALSE; + + /* We require at least 2 dots in the pattern to avoid too wide wildcard + match. */ + pattern_label_end = memchr(pattern, '.', patternlen); + if(!pattern_label_end || +- (memrchr(pattern, '.', patternlen) == pattern_label_end) || +- strncasecompare(pattern, "xn--", 4)) ++ (memrchr(pattern, '.', patternlen) == pattern_label_end)) + return pmatch(hostname, hostlen, pattern, patternlen); +- +- hostname_label_end = memchr(hostname, '.', hostlen); +- if(!hostname_label_end) +- return FALSE; + else { +- size_t skiphost = hostname_label_end - hostname; +- size_t skiplen = pattern_label_end - pattern; +- if(!pmatch(hostname_label_end, hostlen - skiphost, +- pattern_label_end, patternlen - skiplen)) +- return FALSE; ++ const char *hostname_label_end = memchr(hostname, '.', hostlen); ++ if(hostname_label_end) { ++ size_t skiphost = hostname_label_end - hostname; ++ size_t skiplen = pattern_label_end - pattern; ++ return pmatch(hostname_label_end, hostlen - skiphost, ++ pattern_label_end, patternlen - skiplen); ++ } + } +- /* The wildcard must match at least one character, so the left-most +- label of the hostname is at least as large as the left-most label +- of the pattern. */ +- if(hostname_label_end - hostname < pattern_label_end - pattern) +- return FALSE; +- +- prefixlen = wildcard - pattern; +- suffixlen = pattern_label_end - (wildcard + 1); +- return strncasecompare(pattern, hostname, prefixlen) && +- strncasecompare(wildcard + 1, hostname_label_end - suffixlen, +- suffixlen) ? TRUE : FALSE; ++ return FALSE; + } + + /* +diff --git a/tests/data/test1397 b/tests/data/test1397 +index 84f962abe..f31b2c2a3 100644 +--- a/tests/data/test1397 ++++ b/tests/data/test1397 +@@ -2,8 +2,7 @@ + + + unittest +-ssl +-wildcard ++Curl_cert_hostcheck + + + +@@ -16,9 +15,8 @@ none + + unittest + +- +-Check wildcard certificate matching function Curl_cert_hostcheck +- ++ ++Curl_cert_hostcheck unit tests ++ + +- + +diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am +index 4f64ff596..e7a6aa452 100644 +--- a/tests/unit/Makefile.am ++++ b/tests/unit/Makefile.am +@@ -67,91 +67,3 @@ noinst_PROGRAMS = $(UNITPROGS) + else + noinst_PROGRAMS = + endif +- +-unit1300_SOURCES = unit1300.c $(UNITFILES) +- +-unit1302_SOURCES = unit1302.c $(UNITFILES) +- +-unit1303_SOURCES = unit1303.c $(UNITFILES) +- +-unit1304_SOURCES = unit1304.c $(UNITFILES) +- +-unit1305_SOURCES = unit1305.c $(UNITFILES) +- +-unit1307_SOURCES = unit1307.c $(UNITFILES) +- +-unit1308_SOURCES = unit1308.c $(UNITFILES) +- +-unit1309_SOURCES = unit1309.c $(UNITFILES) +- +-unit1323_SOURCES = unit1323.c $(UNITFILES) +- +-unit1330_SOURCES = unit1330.c $(UNITFILES) +- +-unit1394_SOURCES = unit1394.c $(UNITFILES) +-unit1394_LDADD = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ +-unit1394_LDFLAGS = $(top_builddir)/src/libcurltool.la +-unit1394_LIBS = +- +-unit1395_SOURCES = unit1395.c $(UNITFILES) +- +-unit1396_SOURCES = unit1396.c $(UNITFILES) +- +-unit1397_SOURCES = unit1397.c $(UNITFILES) +- +-unit1398_SOURCES = unit1398.c $(UNITFILES) +- +-unit1399_SOURCES = unit1399.c $(UNITFILES) +- +-unit1600_SOURCES = unit1600.c $(UNITFILES) +- +-unit1601_SOURCES = unit1601.c $(UNITFILES) +- +-unit1602_SOURCES = unit1602.c $(UNITFILES) +- +-unit1603_SOURCES = unit1603.c $(UNITFILES) +- +-unit1604_SOURCES = unit1604.c $(UNITFILES) +- +-unit1605_SOURCES = unit1605.c $(UNITFILES) +- +-unit1606_SOURCES = unit1606.c $(UNITFILES) +- +-unit1607_SOURCES = unit1607.c $(UNITFILES) +- +-unit1608_SOURCES = unit1608.c $(UNITFILES) +- +-unit1609_SOURCES = unit1609.c $(UNITFILES) +- +-unit1610_SOURCES = unit1610.c $(UNITFILES) +- +-unit1611_SOURCES = unit1611.c $(UNITFILES) +- +-unit1612_SOURCES = unit1612.c $(UNITFILES) +- +-unit1614_SOURCES = unit1614.c $(UNITFILES) +- +-unit1620_SOURCES = unit1620.c $(UNITFILES) +- +-unit1621_SOURCES = unit1621.c $(UNITFILES) +-unit1621_LDADD = $(top_builddir)/src/libcurltool.la $(top_builddir)/lib/libcurl.la @NSS_LIBS@ +- +-unit1650_SOURCES = unit1650.c $(UNITFILES) +- +-unit1651_SOURCES = unit1651.c $(UNITFILES) +- +-unit1652_SOURCES = unit1652.c $(UNITFILES) +- +-unit1653_SOURCES = unit1653.c $(UNITFILES) +- +-unit1654_SOURCES = unit1654.c $(UNITFILES) +- +-unit1655_SOURCES = unit1655.c $(UNITFILES) +- +-unit1660_SOURCES = unit1660.c $(UNITFILES) +- +-unit1661_SOURCES = unit1661.c $(UNITFILES) +- +-unit2600_SOURCES = unit2600.c $(UNITFILES) +- +-unit3200_SOURCES = unit3200.c $(UNITFILES) +diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc +index 4ab15b5db..20a9963d1 100644 +--- a/tests/unit/Makefile.inc ++++ b/tests/unit/Makefile.inc +@@ -40,3 +40,97 @@ UNITPROGS = unit1300 unit1302 unit1303 unit1304 unit1305 unit1307 \ + unit1660 unit1661 \ + unit2600 \ + unit3200 ++ ++unit1300_SOURCES = unit1300.c $(UNITFILES) ++ ++unit1302_SOURCES = unit1302.c $(UNITFILES) ++ ++unit1303_SOURCES = unit1303.c $(UNITFILES) ++ ++unit1304_SOURCES = unit1304.c $(UNITFILES) ++ ++unit1305_SOURCES = unit1305.c $(UNITFILES) ++ ++unit1307_SOURCES = unit1307.c $(UNITFILES) ++ ++unit1308_SOURCES = unit1308.c $(UNITFILES) ++ ++unit1309_SOURCES = unit1309.c $(UNITFILES) ++ ++unit1323_SOURCES = unit1323.c $(UNITFILES) ++ ++unit1330_SOURCES = unit1330.c $(UNITFILES) ++ ++unit1394_SOURCES = unit1394.c $(UNITFILES) ++unit1394_LDADD = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ ++unit1394_LDFLAGS = $(top_builddir)/src/libcurltool.la ++unit1394_LIBS = ++ ++unit1395_SOURCES = unit1395.c $(UNITFILES) ++ ++unit1396_SOURCES = unit1396.c $(UNITFILES) ++ ++unit1397_SOURCES = unit1397.c $(UNITFILES) ++ ++unit1398_SOURCES = unit1398.c $(UNITFILES) ++ ++unit1399_SOURCES = unit1399.c $(UNITFILES) ++ ++unit1600_SOURCES = unit1600.c $(UNITFILES) ++ ++unit1601_SOURCES = unit1601.c $(UNITFILES) ++ ++unit1602_SOURCES = unit1602.c $(UNITFILES) ++ ++unit1603_SOURCES = unit1603.c $(UNITFILES) ++ ++unit1604_SOURCES = unit1604.c $(UNITFILES) ++ ++unit1605_SOURCES = unit1605.c $(UNITFILES) ++ ++unit1606_SOURCES = unit1606.c $(UNITFILES) ++ ++unit1607_SOURCES = unit1607.c $(UNITFILES) ++ ++unit1608_SOURCES = unit1608.c $(UNITFILES) ++ ++unit1609_SOURCES = unit1609.c $(UNITFILES) ++ ++unit1610_SOURCES = unit1610.c $(UNITFILES) ++ ++unit1611_SOURCES = unit1611.c $(UNITFILES) ++ ++unit1612_SOURCES = unit1612.c $(UNITFILES) ++ ++unit1614_SOURCES = unit1614.c $(UNITFILES) ++ ++unit1620_SOURCES = unit1620.c $(UNITFILES) ++ ++unit1621_SOURCES = unit1621.c $(UNITFILES) ++unit1621_LDADD = $(top_builddir)/src/libcurltool.la $(top_builddir)/lib/libcurl.la @NSS_LIBS@ ++ ++unit1650_SOURCES = unit1650.c $(UNITFILES) ++ ++unit1651_SOURCES = unit1651.c $(UNITFILES) ++ ++unit1652_SOURCES = unit1652.c $(UNITFILES) ++ ++unit1653_SOURCES = unit1653.c $(UNITFILES) ++ ++unit1654_SOURCES = unit1654.c $(UNITFILES) ++ ++unit1655_SOURCES = unit1655.c $(UNITFILES) ++ ++unit1660_SOURCES = unit1660.c $(UNITFILES) ++ ++unit1661_SOURCES = unit1661.c $(UNITFILES) ++ ++unit2600_SOURCES = unit2600.c $(UNITFILES) ++ ++unit2601_SOURCES = unit2601.c $(UNITFILES) ++ ++unit2602_SOURCES = unit2602.c $(UNITFILES) ++ ++unit2603_SOURCES = unit2603.c $(UNITFILES) ++ ++unit3200_SOURCES = unit3200.c $(UNITFILES) +diff --git a/tests/unit/unit1397.c b/tests/unit/unit1397.c +index 2f3d3aa4d..3ae75618d 100644 +--- a/tests/unit/unit1397.c ++++ b/tests/unit/unit1397.c +@@ -23,7 +23,6 @@ + ***************************************************************************/ + #include "curlcheck.h" + +-#include "vtls/hostcheck.h" /* from the lib dir */ + + static CURLcode unit_setup(void) + { +@@ -32,63 +31,94 @@ static CURLcode unit_setup(void) + + static void unit_stop(void) + { +- /* done before shutting down and exiting */ + } + +-UNITTEST_START +- + /* only these backends define the tested functions */ +-#if defined(USE_OPENSSL) || defined(USE_GSKIT) +- +- /* here you start doing things and checking that the results are good */ ++#if defined(USE_OPENSSL) || defined(USE_GSKIT) || defined(USE_SCHANNEL) ++#include "vtls/hostcheck.h" ++struct testcase { ++ const char *host; ++ const char *pattern; ++ bool match; ++}; + +-fail_unless(Curl_cert_hostcheck(STRCONST("www.example.com"), +- STRCONST("www.example.com")), "good 1"); +-fail_unless(Curl_cert_hostcheck(STRCONST("*.example.com"), +- STRCONST("www.example.com")), +- "good 2"); +-fail_unless(Curl_cert_hostcheck(STRCONST("xxx*.example.com"), +- STRCONST("xxxwww.example.com")), "good 3"); +-fail_unless(Curl_cert_hostcheck(STRCONST("f*.example.com"), +- STRCONST("foo.example.com")), "good 4"); +-fail_unless(Curl_cert_hostcheck(STRCONST("192.168.0.0"), +- STRCONST("192.168.0.0")), "good 5"); ++static struct testcase tests[] = { ++ {"", "", FALSE}, ++ {"a", "", FALSE}, ++ {"", "b", FALSE}, ++ {"a", "b", FALSE}, ++ {"aa", "bb", FALSE}, ++ {"\xff", "\xff", TRUE}, ++ {"aa.aa.aa", "aa.aa.bb", FALSE}, ++ {"aa.aa.aa", "aa.aa.aa", TRUE}, ++ {"aa.aa.aa", "*.aa.bb", FALSE}, ++ {"aa.aa.aa", "*.aa.aa", TRUE}, ++ {"192.168.0.1", "192.168.0.1", TRUE}, ++ {"192.168.0.1", "*.168.0.1", FALSE}, ++ {"192.168.0.1", "*.0.1", FALSE}, ++ {"h.ello", "*.ello", FALSE}, ++ {"h.ello.", "*.ello", FALSE}, ++ {"h.ello", "*.ello.", FALSE}, ++ {"h.e.llo", "*.e.llo", TRUE}, ++ {"h.e.llo", " *.e.llo", FALSE}, ++ {" h.e.llo", "*.e.llo", TRUE}, ++ {"h.e.llo.", "*.e.llo", TRUE}, ++ {"*.e.llo.", "*.e.llo", TRUE}, ++ {"************.e.llo.", "*.e.llo", TRUE}, ++ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ++ "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" ++ "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" ++ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" ++ "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" ++ ".e.llo.", "*.e.llo", TRUE}, ++ {"\xfe\xfe.e.llo.", "*.e.llo", TRUE}, ++ {"h.e.llo.", "*.e.llo.", TRUE}, ++ {"h.e.llo", "*.e.llo.", TRUE}, ++ {".h.e.llo", "*.e.llo.", FALSE}, ++ {"h.e.llo", "*.*.llo.", FALSE}, ++ {"h.e.llo", "h.*.llo", FALSE}, ++ {"h.e.llo", "h.e.*", FALSE}, ++ {"hello", "*.ello", FALSE}, ++ {"hello", "**llo", FALSE}, ++ {"bar.foo.example.com", "*.example.com", FALSE}, ++ {"foo.example.com", "*.example.com", TRUE}, ++ {"baz.example.net", "b*z.example.net", FALSE}, ++ {"foobaz.example.net", "*baz.example.net", FALSE}, ++ {"xn--l8j.example.local", "x*.example.local", FALSE}, ++ {"xn--l8j.example.net", "*.example.net", TRUE}, ++ {"xn--l8j.example.net", "*j.example.net", FALSE}, ++ {"xn--l8j.example.net", "xn--l8j.example.net", TRUE}, ++ {"xn--l8j.example.net", "xn--l8j.*.net", FALSE}, ++ {"xl8j.example.net", "*.example.net", TRUE}, ++ {"fe80::3285:a9ff:fe46:b619", "*::3285:a9ff:fe46:b619", FALSE}, ++ {"fe80::3285:a9ff:fe46:b619", "fe80::3285:a9ff:fe46:b619", TRUE}, ++ {NULL, NULL, FALSE} ++}; + +-fail_if(Curl_cert_hostcheck(STRCONST("xxx.example.com"), +- STRCONST("www.example.com")), "bad 1"); +-fail_if(Curl_cert_hostcheck(STRCONST("*"), +- STRCONST("www.example.com")),"bad 2"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.*.com"), +- STRCONST("www.example.com")), "bad 3"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.example.com"), +- STRCONST("baa.foo.example.com")), "bad 4"); +-fail_if(Curl_cert_hostcheck(STRCONST("f*.example.com"), +- STRCONST("baa.example.com")), "bad 5"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.com"), +- STRCONST("example.com")), "bad 6"); +-fail_if(Curl_cert_hostcheck(STRCONST("*fail.com"), +- STRCONST("example.com")), "bad 7"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.example."), +- STRCONST("www.example.")), "bad 8"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.example."), +- STRCONST("www.example")), "bad 9"); +-fail_if(Curl_cert_hostcheck(STRCONST(""), STRCONST("www")), "bad 10"); +-fail_if(Curl_cert_hostcheck(STRCONST("*"), STRCONST("www")), "bad 11"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.168.0.0"), +- STRCONST("192.168.0.0")), "bad 12"); +-fail_if(Curl_cert_hostcheck(STRCONST("www.example.com"), +- STRCONST("192.168.0.0")), "bad 13"); +- +-#ifdef ENABLE_IPV6 +-fail_if(Curl_cert_hostcheck(STRCONST("*::3285:a9ff:fe46:b619"), +- STRCONST("fe80::3285:a9ff:fe46:b619")), "bad 14"); +-fail_unless(Curl_cert_hostcheck(STRCONST("fe80::3285:a9ff:fe46:b619"), +- STRCONST("fe80::3285:a9ff:fe46:b619")), +- "good 6"); +-#endif ++UNITTEST_START ++{ ++ int i; ++ for(i = 0; tests[i].host; i++) { ++ if(tests[i].match != Curl_cert_hostcheck(tests[i].pattern, ++ strlen(tests[i].pattern), ++ tests[i].host, ++ strlen(tests[i].host))) { ++ fprintf(stderr, ++ "HOST: %s\n" ++ "PTRN: %s\n" ++ "did %sMATCH\n", ++ tests[i].host, ++ tests[i].pattern, ++ tests[i].match ? "NOT ": ""); ++ unitfail++; ++ } ++ } ++} + +-#endif ++UNITTEST_STOP ++#else + +- /* you end the test code like this: */ ++UNITTEST_START + + UNITTEST_STOP ++#endif +-- +2.40.1 + diff --git a/curl.spec b/curl.spec index ae2c45c..b243059 100644 --- a/curl.spec +++ b/curl.spec @@ -13,6 +13,9 @@ Source2: mykey.asc # fix more POST-after-PUT confusion (CVE-2023-28322) Patch1: 0001-curl-8.0.1-CVE-2023-28322.patch +# fix IDN wildcard match (CVE-2023-28321) +Patch2: 0002-curl-8.0.1-CVE-2023-28321.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -412,6 +415,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Mon Jun 05 2023 Jan Macku - 8.0.1-2 - fix more POST-after-PUT confusion (CVE-2023-28322) +- fix IDN wildcard match (CVE-2023-28321) * Wed May 03 2023 Kamil Dudka - 8.0.1-1 - tests: re-enable temporarily disabled test-cases From 3eba762b345c65d6fb38818e263eea7eb0bad757 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Thu, 20 Jul 2023 09:44:10 +0200 Subject: [PATCH 22/29] Resolves: CVE-2023-32001 - fix fopen race condition --- 0003-curl-8.0.1-CVE-2023-32001.patch | 40 ++++++++++++++++++++++++++++ curl.spec | 8 +++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 0003-curl-8.0.1-CVE-2023-32001.patch diff --git a/0003-curl-8.0.1-CVE-2023-32001.patch b/0003-curl-8.0.1-CVE-2023-32001.patch new file mode 100644 index 0000000..eaa9d8f --- /dev/null +++ b/0003-curl-8.0.1-CVE-2023-32001.patch @@ -0,0 +1,40 @@ +From 98474a7848e20716935f471f4e48610b00fe9dc0 Mon Sep 17 00:00:00 2001 +From: SaltyMilk +Date: Mon, 10 Jul 2023 21:43:28 +0200 +Subject: [PATCH] fopen: optimize + +Closes #11419 + +(cherry picked from commit 0c667188e0c6cda615a036b8a2b4125f2c404dde) +Signed-off-by: Jan Macku +--- + lib/fopen.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index f710dbf05..8c728f2a8 100644 +--- a/lib/fopen.c ++++ b/lib/fopen.c +@@ -56,13 +56,13 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + int fd = -1; + *tempname = NULL; + +- if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) { +- /* a non-regular file, fallback to direct fopen() */ +- *fh = fopen(filename, FOPEN_WRITETEXT); +- if(*fh) +- return CURLE_OK; ++ *fh = fopen(filename, FOPEN_WRITETEXT); ++ if(!*fh) + goto fail; +- } ++ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) ++ return CURLE_OK; ++ fclose(*fh); ++ *fh = NULL; + + result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix)); + if(result) +-- +2.41.0 + diff --git a/curl.spec b/curl.spec index b243059..50001aa 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.0.1 -Release: 2%{?dist} +Release: 3%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -16,6 +16,9 @@ Patch1: 0001-curl-8.0.1-CVE-2023-28322.patch # fix IDN wildcard match (CVE-2023-28321) Patch2: 0002-curl-8.0.1-CVE-2023-28321.patch +# fix fopen race condition (CVE-2023-32001) +Patch3: 0003-curl-8.0.1-CVE-2023-32001.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -413,6 +416,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Thu Jul 20 2023 Jan Macku - 8.0.1-3 +- fix fopen race condition (CVE-2023-32001) + * Mon Jun 05 2023 Jan Macku - 8.0.1-2 - fix more POST-after-PUT confusion (CVE-2023-28322) - fix IDN wildcard match (CVE-2023-28321) From 640fb40e90094efde318484bc0e77ddff538caea Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Wed, 13 Sep 2023 13:39:44 +0200 Subject: [PATCH 23/29] Resolves: CVE-2023-38039 - fix HTTP headers eat all memory --- 0004-curl-8.0.1-CVE-2023-38039.patch | 201 +++++++++++++++++++++++++++ curl.spec | 8 +- 2 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 0004-curl-8.0.1-CVE-2023-38039.patch diff --git a/0004-curl-8.0.1-CVE-2023-38039.patch b/0004-curl-8.0.1-CVE-2023-38039.patch new file mode 100644 index 0000000..dc63e75 --- /dev/null +++ b/0004-curl-8.0.1-CVE-2023-38039.patch @@ -0,0 +1,201 @@ +From fe13e206a80cee9ffa686ead170980dbdb2cf9e1 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 2 Aug 2023 23:34:48 +0200 +Subject: [PATCH] http: return error when receiving too large header set + +To avoid abuse. The limit is set to 300 KB for the accumulated size of +all received HTTP headers for a single response. Incomplete research +suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to +1MB. + +Closes #11582 + +(cherry picked from commit 3ee79c1674fd6f99e8efca52cd7510e08b766770) +Signed-off-by: Jan Macku +--- + lib/c-hyper.c | 12 +++++++----- + lib/http.c | 34 ++++++++++++++++++++++++++++++---- + lib/http.h | 9 +++++++++ + lib/pingpong.c | 4 +++- + lib/urldata.h | 17 ++++++++--------- + 5 files changed, 57 insertions(+), 19 deletions(-) + +diff --git a/lib/c-hyper.c b/lib/c-hyper.c +index 9c7632d35..28f64ef97 100644 +--- a/lib/c-hyper.c ++++ b/lib/c-hyper.c +@@ -174,8 +174,11 @@ static int hyper_each_header(void *userdata, + } + } + +- data->info.header_size += (curl_off_t)len; +- data->req.headerbytecount += (curl_off_t)len; ++ result = Curl_bump_headersize(data, len, FALSE); ++ if(result) { ++ data->state.hresult = result; ++ return HYPER_ITER_BREAK; ++ } + return HYPER_ITER_CONTINUE; + } + +@@ -305,9 +308,8 @@ static CURLcode status_line(struct Curl_easy *data, + if(result) + return result; + } +- data->info.header_size += (curl_off_t)len; +- data->req.headerbytecount += (curl_off_t)len; +- return CURLE_OK; ++ result = Curl_bump_headersize(data, len, FALSE); ++ return result; + } + + /* +diff --git a/lib/http.c b/lib/http.c +index 400d2b081..d8c3e1eda 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -3760,6 +3760,29 @@ static CURLcode verify_header(struct Curl_easy *data) + return CURLE_OK; + } + ++CURLcode Curl_bump_headersize(struct Curl_easy *data, ++ size_t delta, ++ bool connect_only) ++{ ++ size_t bad = 0; ++ if(delta < MAX_HTTP_RESP_HEADER_SIZE) { ++ if(!connect_only) ++ data->req.headerbytecount += (unsigned int)delta; ++ data->info.header_size += (unsigned int)delta; ++ if(data->info.header_size > MAX_HTTP_RESP_HEADER_SIZE) ++ bad = data->info.header_size; ++ } ++ else ++ bad = data->info.header_size + delta; ++ if(bad) { ++ failf(data, "Too large response headers: %zu > %zu", ++ bad, MAX_HTTP_RESP_HEADER_SIZE); ++ return CURLE_RECV_ERROR; ++ } ++ return CURLE_OK; ++} ++ ++ + /* + * Read any HTTP header lines from the server and pass them to the client app. + */ +@@ -4007,8 +4030,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + if(result) + return result; + +- data->info.header_size += (long)headerlen; +- data->req.headerbytecount += (long)headerlen; ++ result = Curl_bump_headersize(data, headerlen, FALSE); ++ if(result) ++ return result; + + /* + * When all the headers have been parsed, see if we should give +@@ -4330,8 +4354,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + if(result) + return result; + +- data->info.header_size += Curl_dyn_len(&data->state.headerb); +- data->req.headerbytecount += Curl_dyn_len(&data->state.headerb); ++ result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb), ++ FALSE); ++ if(result) ++ return result; + + Curl_dyn_reset(&data->state.headerb); + } +diff --git a/lib/http.h b/lib/http.h +index 444abc0be..b29f3b84f 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -61,6 +61,10 @@ extern const struct Curl_handler Curl_handler_wss; + #endif /* websockets */ + + ++CURLcode Curl_bump_headersize(struct Curl_easy *data, ++ size_t delta, ++ bool connect_only); ++ + /* Header specific functions */ + bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ +@@ -176,6 +180,11 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data); + #define EXPECT_100_THRESHOLD (1024*1024) + #endif + ++/* MAX_HTTP_RESP_HEADER_SIZE is the maximum size of all response headers ++ combined that libcurl allows for a single HTTP response, any HTTP ++ version. This count includes CONNECT response headers. */ ++#define MAX_HTTP_RESP_HEADER_SIZE (300*1024) ++ + #endif /* CURL_DISABLE_HTTP */ + + #ifdef USE_NGHTTP3 +diff --git a/lib/pingpong.c b/lib/pingpong.c +index 2f4aa1c34..189a0b68e 100644 +--- a/lib/pingpong.c ++++ b/lib/pingpong.c +@@ -341,7 +341,9 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data, + ssize_t clipamount = 0; + bool restart = FALSE; + +- data->req.headerbytecount += (long)gotbytes; ++ result = Curl_bump_headersize(data, gotbytes, FALSE); ++ if(result) ++ return result; + + pp->nread_resp += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { +diff --git a/lib/urldata.h b/lib/urldata.h +index f3e782ad3..390c611e2 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -619,17 +619,16 @@ struct SingleRequest { + curl_off_t bytecount; /* total number of bytes read */ + curl_off_t writebytecount; /* number of bytes written */ + +- curl_off_t headerbytecount; /* only count received headers */ +- curl_off_t deductheadercount; /* this amount of bytes doesn't count when we +- check if anything has been transferred at +- the end of a connection. We use this +- counter to make only a 100 reply (without a +- following second response code) result in a +- CURLE_GOT_NOTHING error code */ +- + curl_off_t pendingheader; /* this many bytes left to send is actually + header and not body */ + struct curltime start; /* transfer started at this time */ ++ unsigned int headerbytecount; /* only count received headers */ ++ unsigned int deductheadercount; /* this amount of bytes doesn't count when ++ we check if anything has been transferred ++ at the end of a connection. We use this ++ counter to make only a 100 reply (without ++ a following second response code) result ++ in a CURLE_GOT_NOTHING error code */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest +@@ -1076,7 +1075,6 @@ struct PureInfo { + int httpversion; /* the http version number X.Y = X*10+Y */ + time_t filetime; /* If requested, this is might get set. Set to -1 if the + time was unretrievable. */ +- curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ + unsigned long proxyauthavail; /* what proxy auth types were announced */ + unsigned long httpauthavail; /* what host auth types were announced */ +@@ -1084,6 +1082,7 @@ struct PureInfo { + char *contenttype; /* the content type of the object */ + char *wouldredirect; /* URL this would've been redirected to if asked to */ + curl_off_t retry_after; /* info from Retry-After: header */ ++ unsigned int header_size; /* size of read header(s) in bytes */ + + /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' + and, 'conn_local_port' are copied over from the connectdata struct in +-- +2.41.0 + diff --git a/curl.spec b/curl.spec index 50001aa..730577e 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.0.1 -Release: 3%{?dist} +Release: 4%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -19,6 +19,9 @@ Patch2: 0002-curl-8.0.1-CVE-2023-28321.patch # fix fopen race condition (CVE-2023-32001) Patch3: 0003-curl-8.0.1-CVE-2023-32001.patch +# fix HTTP headers eat all memory (CVE-2023-38039) +Patch4: 0004-curl-8.0.1-CVE-2023-38039.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -416,6 +419,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Sep 13 2023 Jan Macku - 8.0.1-4 +- fix HTTP headers eat all memory (CVE-2023-38039) + * Thu Jul 20 2023 Jan Macku - 8.0.1-3 - fix fopen race condition (CVE-2023-32001) From 8a97eeb08aa1a9f8bec01a548c4993118c80ab8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= Date: Mon, 9 Oct 2023 10:39:43 +0200 Subject: [PATCH 24/29] tests: use newer Fedora URLs for testing ... because F36 URLs are no longer available. --- tests/non-root-user-download/runtest.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/non-root-user-download/runtest.sh b/tests/non-root-user-download/runtest.sh index 0529a12..4d51e62 100755 --- a/tests/non-root-user-download/runtest.sh +++ b/tests/non-root-user-download/runtest.sh @@ -31,9 +31,9 @@ PACKAGE="curl" -FTP_URL=ftp://ftp.fi.muni.cz/pub/linux/fedora/linux/releases/36/Everything/x86_64/iso/Fedora-Everything-36-1.5-x86_64-CHECKSUM -HTTP_URL=https://archives.fedoraproject.org/pub/fedora/linux/releases/36/Everything/x86_64/iso/Fedora-Everything-36-1.5-x86_64-CHECKSUM -CONTENT=85cb450443d68d513b41e57b0bd818a740279dac5dfc09c68e681ff8a3006404 +FTP_URL=ftp://ftp.fi.muni.cz/pub/linux/fedora/linux/releases/38/Everything/x86_64/iso/Fedora-Everything-38-1.6-x86_64-CHECKSUM +HTTP_URL=https://archives.fedoraproject.org/pub/fedora/linux/releases/38/Everything/x86_64/iso/Fedora-Everything-38-1.6-x86_64-CHECKSUM +CONTENT=4d042dedc8886856db10bc882074b84dcce52f829ea7b3f31d8031db8d84df20 PASSWORD=pAssw0rd OPTIONS="" rlIsRHEL 7 && OPTIONS="--insecure" From 4db7b87ac44c6b1988f3fe94ba288c8d2ede1fb4 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Thu, 12 Oct 2023 09:32:40 +0200 Subject: [PATCH 25/29] Resolves: CVE-2023-38545 - SOCKS5 heap buffer overflow --- 0005-curl-8.0.1-CVE-2023-38545.patch | 135 +++++++++++++++++++++++++++ curl.spec | 16 +++- 2 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 0005-curl-8.0.1-CVE-2023-38545.patch diff --git a/0005-curl-8.0.1-CVE-2023-38545.patch b/0005-curl-8.0.1-CVE-2023-38545.patch new file mode 100644 index 0000000..7b06ee4 --- /dev/null +++ b/0005-curl-8.0.1-CVE-2023-38545.patch @@ -0,0 +1,135 @@ +From fa4aed65588db8e7c7e3d98f6c5bcf394f3a515d Mon Sep 17 00:00:00 2001 +From: Jay Satiro +Date: Wed, 11 Oct 2023 07:34:19 +0200 +Subject: [PATCH 1/2] socks: return error if hostname too long for remote + resolve + +Prior to this change the state machine attempted to change the remote +resolve to a local resolve if the hostname was longer than 255 +characters. Unfortunately that did not work as intended and caused a +security issue. + +Bug: https://curl.se/docs/CVE-2023-38545.html + +(cherry picked from commit fb4415d8aee6c1045be932a34fe6107c2f5ed147) + +Signed-off-by: Jan Macku +--- + lib/socks.c | 8 +++--- + tests/data/Makefile.inc | 2 +- + tests/data/test728 | 64 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+), 5 deletions(-) + create mode 100644 tests/data/test728 + +diff --git a/lib/socks.c b/lib/socks.c +index 95c2b004c..8cf694d1d 100644 +--- a/lib/socks.c ++++ b/lib/socks.c +@@ -588,9 +588,9 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, + + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ + if(!socks5_resolve_local && hostname_len > 255) { +- infof(data, "SOCKS5: server resolving disabled for hostnames of " +- "length > 255 [actual len=%zu]", hostname_len); +- socks5_resolve_local = TRUE; ++ failf(data, "SOCKS5: the destination hostname is too long to be " ++ "resolved remotely by the proxy."); ++ return CURLPX_LONG_HOSTNAME; + } + + if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) +@@ -904,7 +904,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, + } + else { + socksreq[len++] = 3; +- socksreq[len++] = (char) hostname_len; /* one byte address length */ ++ socksreq[len++] = (unsigned char) hostname_len; /* one byte length */ + memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */ + len += hostname_len; + } +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 7ed03a247..eb89437ef 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -100,7 +100,7 @@ test679 test680 test681 test682 test683 test684 test685 test686 \ + \ + test700 test701 test702 test703 test704 test705 test706 test707 test708 \ + test709 test710 test711 test712 test713 test714 test715 test716 test717 \ +-test718 test719 test720 test721 \ ++test718 test719 test720 test721 test728 \ + \ + test800 test801 test802 test803 test804 test805 test806 test807 test808 \ + test809 test810 test811 test812 test813 test814 test815 test816 test817 \ +diff --git a/tests/data/test728 b/tests/data/test728 +new file mode 100644 +index 000000000..05bcf2883 +--- /dev/null ++++ b/tests/data/test728 +@@ -0,0 +1,64 @@ ++ ++ ++ ++HTTP ++HTTP GET ++SOCKS5 ++SOCKS5h ++followlocation ++ ++ ++ ++# ++# Server-side ++ ++# The hostname in this redirect is 256 characters and too long (> 255) for ++# SOCKS5 remote resolve. curl must return error CURLE_PROXY in this case. ++ ++HTTP/1.1 301 Moved Permanently ++Location: http://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/ ++Content-Length: 0 ++Connection: close ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++proxy ++ ++ ++http ++socks5 ++ ++ ++SOCKS5h with HTTP redirect to hostname too long ++ ++ ++--no-progress-meter --location --proxy socks5h://%HOSTIP:%SOCKSPORT http://%HOSTIP:%HTTPPORT/%TESTNUMBER ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ ++ ++ ++97 ++ ++# the error message is verified because error code CURLE_PROXY (97) may be ++# returned for any number of reasons and we need to make sure it is ++# specifically for the reason below so that we know the check is working. ++ ++curl: (97) SOCKS5: the destination hostname is too long to be resolved remotely by the proxy. ++ ++ ++ +-- +2.41.0 + diff --git a/curl.spec b/curl.spec index 730577e..c39651e 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.0.1 -Release: 4%{?dist} +Release: 5%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -11,16 +11,19 @@ Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc Source2: mykey.asc # fix more POST-after-PUT confusion (CVE-2023-28322) -Patch1: 0001-curl-8.0.1-CVE-2023-28322.patch +Patch1: 0001-curl-8.0.1-CVE-2023-28322.patch # fix IDN wildcard match (CVE-2023-28321) -Patch2: 0002-curl-8.0.1-CVE-2023-28321.patch +Patch2: 0002-curl-8.0.1-CVE-2023-28321.patch # fix fopen race condition (CVE-2023-32001) -Patch3: 0003-curl-8.0.1-CVE-2023-32001.patch +Patch3: 0003-curl-8.0.1-CVE-2023-32001.patch # fix HTTP headers eat all memory (CVE-2023-38039) -Patch4: 0004-curl-8.0.1-CVE-2023-38039.patch +Patch4: 0004-curl-8.0.1-CVE-2023-38039.patch + +# fix SOCKS5 heap buffer overflow (CVE-2023-38545) +Patch5: 0005-curl-8.0.1-CVE-2023-38545.patch # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -419,6 +422,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Thu Oct 12 2023 Jan Macku - 8.0.1-5 +- fix SOCKS5 heap buffer overflow (CVE-2023-38545) + * Wed Sep 13 2023 Jan Macku - 8.0.1-4 - fix HTTP headers eat all memory (CVE-2023-38039) From e1c9c5d6837c89c294893d32bec3ab0bb5254245 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Thu, 12 Oct 2023 09:35:11 +0200 Subject: [PATCH 26/29] Resolves: CVE-2023-38546 - cookie injection with none file --- 0006-curl-8.0.1-CVE-2023-38546.patch | 136 +++++++++++++++++++++++++++ curl.spec | 4 + 2 files changed, 140 insertions(+) create mode 100644 0006-curl-8.0.1-CVE-2023-38546.patch diff --git a/0006-curl-8.0.1-CVE-2023-38546.patch b/0006-curl-8.0.1-CVE-2023-38546.patch new file mode 100644 index 0000000..111f0d3 --- /dev/null +++ b/0006-curl-8.0.1-CVE-2023-38546.patch @@ -0,0 +1,136 @@ +From a9a3f49fc87d4b64f380e19d69c139e9fba676f2 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 14 Sep 2023 23:28:32 +0200 +Subject: [PATCH 2/2] cookie: remove unnecessary struct fields + +Plus: reduce the hash table size from 256 to 63. It seems unlikely to +make much of a speed difference for most use cases but saves 1.5KB of +data per instance. + +Closes #11862 + +(cherry picked from commit 61275672b46d9abb3285740467b882e22ed75da8) + +Signed-off-by: Jan Macku +--- + lib/cookie.c | 13 +------------ + lib/cookie.h | 14 ++++---------- + lib/easy.c | 4 +--- + 3 files changed, 6 insertions(+), 25 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index 0c6e0f7cd..d34620351 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -119,7 +119,6 @@ static void freecookie(struct Cookie *co) + free(co->name); + free(co->value); + free(co->maxage); +- free(co->version); + free(co); + } + +@@ -726,11 +725,7 @@ Curl_cookie_add(struct Curl_easy *data, + } + } + else if((nlen == 7) && strncasecompare("version", namep, 7)) { +- strstore(&co->version, valuep, vlen); +- if(!co->version) { +- badcookie = TRUE; +- break; +- } ++ /* just ignore */ + } + else if((nlen == 7) && strncasecompare("max-age", namep, 7)) { + /* +@@ -1174,7 +1169,6 @@ Curl_cookie_add(struct Curl_easy *data, + free(clist->path); + free(clist->spath); + free(clist->expirestr); +- free(clist->version); + free(clist->maxage); + + *clist = *co; /* then store all the new data */ +@@ -1238,9 +1232,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + c = calloc(1, sizeof(struct CookieInfo)); + if(!c) + return NULL; /* failed to get memory */ +- c->filename = strdup(file?file:"none"); /* copy the name just in case */ +- if(!c->filename) +- goto fail; /* failed to get memory */ + /* + * Initialize the next_expiration time to signal that we don't have enough + * information yet. +@@ -1394,7 +1385,6 @@ static struct Cookie *dup_cookie(struct Cookie *src) + CLONE(name); + CLONE(value); + CLONE(maxage); +- CLONE(version); + d->expires = src->expires; + d->tailmatch = src->tailmatch; + d->secure = src->secure; +@@ -1611,7 +1601,6 @@ void Curl_cookie_cleanup(struct CookieInfo *c) + { + if(c) { + unsigned int i; +- free(c->filename); + for(i = 0; i < COOKIE_HASH_SIZE; i++) + Curl_cookie_freelist(c->cookies[i]); + free(c); /* free the base struct as well */ +diff --git a/lib/cookie.h b/lib/cookie.h +index 39bb08bc4..3a43bbf33 100644 +--- a/lib/cookie.h ++++ b/lib/cookie.h +@@ -36,11 +36,7 @@ struct Cookie { + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ +- +- /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ +- char *version; /* Version = */ + char *maxage; /* Max-Age = */ +- + bool tailmatch; /* whether we do tail-matching of the domain name */ + bool secure; /* whether the 'secure' keyword was used */ + bool livecookie; /* updated from a server, not a stored file */ +@@ -56,18 +52,16 @@ struct Cookie { + #define COOKIE_PREFIX__SECURE (1<<0) + #define COOKIE_PREFIX__HOST (1<<1) + +-#define COOKIE_HASH_SIZE 256 ++#define COOKIE_HASH_SIZE 63 + + struct CookieInfo { + /* linked list of cookies we know of */ + struct Cookie *cookies[COOKIE_HASH_SIZE]; +- +- char *filename; /* file we read from/write to */ +- long numcookies; /* number of cookies in the "jar" */ ++ curl_off_t next_expiration; /* the next time at which expiration happens */ ++ int numcookies; /* number of cookies in the "jar" */ ++ int lastct; /* last creation-time used in the jar */ + bool running; /* state info, for cookie adding information */ + bool newsession; /* new session, discard session cookies on load */ +- int lastct; /* last creation-time used in the jar */ +- curl_off_t next_expiration; /* the next time at which expiration happens */ + }; + + /* This is the maximum line length we accept for a cookie line. RFC 2109 +diff --git a/lib/easy.c b/lib/easy.c +index 27124a72f..fddf047f2 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -911,9 +911,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ +- outcurl->cookies = Curl_cookie_init(data, +- data->cookies->filename, +- outcurl->cookies, ++ outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; +-- +2.41.0 + diff --git a/curl.spec b/curl.spec index c39651e..fc8fa99 100644 --- a/curl.spec +++ b/curl.spec @@ -25,6 +25,9 @@ Patch4: 0004-curl-8.0.1-CVE-2023-38039.patch # fix SOCKS5 heap buffer overflow (CVE-2023-38545) Patch5: 0005-curl-8.0.1-CVE-2023-38545.patch +# fix cookie injection with none file (CVE-2023-38546) +Patch6: 0006-curl-8.0.1-CVE-2023-38546.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -423,6 +426,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Thu Oct 12 2023 Jan Macku - 8.0.1-5 +- fix cookie injection with none file (CVE-2023-38546) - fix SOCKS5 heap buffer overflow (CVE-2023-38545) * Wed Sep 13 2023 Jan Macku - 8.0.1-4 From eee0c7d606170b4da54b83c8f1e5a96720ba574f Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Wed, 6 Dec 2023 16:06:31 +0100 Subject: [PATCH 27/29] Resolves: CVE-2023-46218 - cookie mixed case PSL bypass --- 0007-curl-8.0.1-CVE-2023-46218.patch | 55 ++++++++++++++++++++++++++++ curl.spec | 8 +++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 0007-curl-8.0.1-CVE-2023-46218.patch diff --git a/0007-curl-8.0.1-CVE-2023-46218.patch b/0007-curl-8.0.1-CVE-2023-46218.patch new file mode 100644 index 0000000..1494a41 --- /dev/null +++ b/0007-curl-8.0.1-CVE-2023-46218.patch @@ -0,0 +1,55 @@ +From ef4abe34b2b704e2a318063b387b628773b78663 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 23 Nov 2023 08:15:47 +0100 +Subject: [PATCH 1/2] cookie: lowercase the domain names before PSL checks + +Reported-by: Harry Sintonen + +Closes #12387 + +(cherry picked from commit 2b0994c29a721c91c572cff7808c572a24d251eb) + +Signed-off-by: Jan Macku +--- + lib/cookie.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index d34620351..730c3c6f4 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -1044,15 +1044,23 @@ Curl_cookie_add(struct Curl_easy *data, + * dereference it. + */ + if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) { +- const psl_ctx_t *psl = Curl_psl_use(data); +- int acceptable; +- +- if(psl) { +- acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); +- Curl_psl_release(data); ++ bool acceptable = FALSE; ++ char lcase[256]; ++ char lcookie[256]; ++ size_t dlen = strlen(domain); ++ size_t clen = strlen(co->domain); ++ if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) { ++ const psl_ctx_t *psl = Curl_psl_use(data); ++ if(psl) { ++ /* the PSL check requires lowercase domain name and pattern */ ++ Curl_strntolower(lcase, domain, dlen + 1); ++ Curl_strntolower(lcookie, co->domain, clen + 1); ++ acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie); ++ Curl_psl_release(data); ++ } ++ else ++ acceptable = !bad_domain(domain, strlen(domain)); + } +- else +- acceptable = !bad_domain(domain, strlen(domain)); + + if(!acceptable) { + infof(data, "cookie '%s' dropped, domain '%s' must not " +-- +2.43.0 + diff --git a/curl.spec b/curl.spec index fc8fa99..b2e85a9 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.0.1 -Release: 5%{?dist} +Release: 6%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -28,6 +28,9 @@ Patch5: 0005-curl-8.0.1-CVE-2023-38545.patch # fix cookie injection with none file (CVE-2023-38546) Patch6: 0006-curl-8.0.1-CVE-2023-38546.patch +# fix cookie mixed case PSL bypass (CVE-2023-46218) +Patch7: 0007-curl-8.0.1-CVE-2023-46218.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -425,6 +428,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Dec 06 2023 Jan Macku - 8.0.1-6 +- fix cookie mixed case PSL bypass (CVE-2023-46218) + * Thu Oct 12 2023 Jan Macku - 8.0.1-5 - fix cookie injection with none file (CVE-2023-38546) - fix SOCKS5 heap buffer overflow (CVE-2023-38545) From 1f7f31bdbf18acf2829aac71f30fc140d4687ced Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Wed, 6 Dec 2023 16:08:39 +0100 Subject: [PATCH 28/29] Resolves: CVE-2023-46219 - HSTS long file name clears contents --- 0008-curl-8.0.1-CVE-2023-46219.patch | 134 +++++++++++++++++++++++++++ curl.spec | 4 + 2 files changed, 138 insertions(+) create mode 100644 0008-curl-8.0.1-CVE-2023-46219.patch diff --git a/0008-curl-8.0.1-CVE-2023-46219.patch b/0008-curl-8.0.1-CVE-2023-46219.patch new file mode 100644 index 0000000..08c4938 --- /dev/null +++ b/0008-curl-8.0.1-CVE-2023-46219.patch @@ -0,0 +1,134 @@ +From 45ed144efd8b194cc7d0acbe00594f730a2ad62d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 23 Nov 2023 08:23:17 +0100 +Subject: [PATCH 2/2] fopen: create short(er) temporary file name + +Only using random letters in the name plus a ".tmp" extension. Not by +appending characters to the final file name. + +Reported-by: Maksymilian Arciemowicz + +Closes #12388 + +(cherry picked from commit 73b65e94f3531179de45c6f3c836a610e3d0a846) + +Signed-off-by: Jan Macku +--- + lib/fopen.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 60 insertions(+), 5 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index 8c728f2a8..7b9d4022e 100644 +--- a/lib/fopen.c ++++ b/lib/fopen.c +@@ -39,6 +39,51 @@ + #include "curl_memory.h" + #include "memdebug.h" + ++/* ++ The dirslash() function breaks a null-terminated pathname string into ++ directory and filename components then returns the directory component up ++ to, *AND INCLUDING*, a final '/'. If there is no directory in the path, ++ this instead returns a "" string. ++ ++ This function returns a pointer to malloc'ed memory. ++ ++ The input path to this function is expected to have a file name part. ++*/ ++ ++#ifdef _WIN32 ++#define PATHSEP "\\" ++#define IS_SEP(x) (((x) == '/') || ((x) == '\\')) ++#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) ++#define PATHSEP "\\" ++#define IS_SEP(x) ((x) == '\\') ++#else ++#define PATHSEP "/" ++#define IS_SEP(x) ((x) == '/') ++#endif ++ ++static char *dirslash(const char *path) ++{ ++ size_t n; ++ struct dynbuf out; ++ DEBUGASSERT(path); ++ Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH); ++ n = strlen(path); ++ if(n) { ++ /* find the rightmost path separator, if any */ ++ while(n && !IS_SEP(path[n-1])) ++ --n; ++ /* skip over all the path separators, if any */ ++ while(n && IS_SEP(path[n-1])) ++ --n; ++ } ++ if(Curl_dyn_addn(&out, path, n)) ++ return NULL; ++ /* if there was a directory, append a single trailing slash */ ++ if(n && Curl_dyn_addn(&out, PATHSEP, 1)) ++ return NULL; ++ return Curl_dyn_ptr(&out); ++} ++ + /* + * Curl_fopen() opens a file for writing with a temp name, to be renamed + * to the final name when completed. If there is an existing file using this +@@ -50,25 +95,34 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + FILE **fh, char **tempname) + { + CURLcode result = CURLE_WRITE_ERROR; +- unsigned char randsuffix[9]; ++ unsigned char randbuf[41]; + char *tempstore = NULL; + struct_stat sb; + int fd = -1; ++ char *dir; + *tempname = NULL; + ++ dir = dirslash(filename); ++ if(!dir) ++ goto fail; ++ + *fh = fopen(filename, FOPEN_WRITETEXT); + if(!*fh) + goto fail; +- if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) ++ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) { ++ free(dir); + return CURLE_OK; ++ } + fclose(*fh); + *fh = NULL; + +- result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix)); ++ result = Curl_rand_hex(data, randbuf, sizeof(randbuf)); + if(result) + goto fail; + +- tempstore = aprintf("%s.%s.tmp", filename, randsuffix); ++ /* The temp file name should not end up too long for the target file ++ system */ ++ tempstore = aprintf("%s%s.tmp", dir, randbuf); + if(!tempstore) { + result = CURLE_OUT_OF_MEMORY; + goto fail; +@@ -95,6 +149,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + if(!*fh) + goto fail; + ++ free(dir); + *tempname = tempstore; + return CURLE_OK; + +@@ -105,7 +160,7 @@ fail: + } + + free(tempstore); +- ++ free(dir); + return result; + } + +-- +2.43.0 + diff --git a/curl.spec b/curl.spec index b2e85a9..bb95483 100644 --- a/curl.spec +++ b/curl.spec @@ -31,6 +31,9 @@ Patch6: 0006-curl-8.0.1-CVE-2023-38546.patch # fix cookie mixed case PSL bypass (CVE-2023-46218) Patch7: 0007-curl-8.0.1-CVE-2023-46218.patch +# fix HSTS long file name clears contents (CVE-2023-46219) +Patch8: 0008-curl-8.0.1-CVE-2023-46219.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -429,6 +432,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * Wed Dec 06 2023 Jan Macku - 8.0.1-6 +- fix HSTS long file name clears contents (CVE-2023-46219) - fix cookie mixed case PSL bypass (CVE-2023-46218) * Thu Oct 12 2023 Jan Macku - 8.0.1-5 From 5bf3c70332c078de6a3652c86ae9f74379ae077f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= Date: Wed, 14 Feb 2024 12:31:44 +0100 Subject: [PATCH 29/29] fix openldap conftest --- 0009-curl-8.0.1-fix-openldap-conftest.patch | 43 +++++++++++++++++++++ curl.spec | 8 +++- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 0009-curl-8.0.1-fix-openldap-conftest.patch diff --git a/0009-curl-8.0.1-fix-openldap-conftest.patch b/0009-curl-8.0.1-fix-openldap-conftest.patch new file mode 100644 index 0000000..c3e2e17 --- /dev/null +++ b/0009-curl-8.0.1-fix-openldap-conftest.patch @@ -0,0 +1,43 @@ +From 0ac6108856b9d500bc376d1d7e0b648d15499837 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 22 Jun 2023 14:34:49 +0200 +Subject: [PATCH] configure: add check for ldap_init_fd + +... as otherwise the configure script will say it is OpenLDAP in the +summary, but not set the USE_OPENLDAP define, therefor not using the +intended OpenLDAP code paths. + +Regression since 4d7385446 (7.85.0) +Fixes #11372 +Closes #11374 +Reported-by: vlkl-sap on github +--- + configure.ac | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 373e2e0cef6862..696a50505f37ab 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1706,16 +1706,19 @@ if test x$CURL_DISABLE_LDAP != x1 ; then + fi + + if test x$CURL_DISABLE_LDAP != x1 ; then +- AC_CHECK_FUNCS([ldap_url_parse]) ++ AC_CHECK_FUNCS([ldap_url_parse \ ++ ldap_init_fd]) + + if test "$LDAPLIBNAME" = "wldap32"; then + curl_ldap_msg="enabled (winldap)" + AC_DEFINE(USE_WIN32_LDAP, 1, [Use Windows LDAP implementation]) + else +- curl_ldap_msg="enabled (OpenLDAP)" + if test "x$ac_cv_func_ldap_init_fd" = "xyes"; then ++ curl_ldap_msg="enabled (OpenLDAP)" + AC_DEFINE(USE_OPENLDAP, 1, [Use OpenLDAP-specific code]) + AC_SUBST(USE_OPENLDAP, [1]) ++ else ++ curl_ldap_msg="enabled (ancient OpenLDAP)" + fi + fi + fi diff --git a/curl.spec b/curl.spec index bb95483..7224088 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.0.1 -Release: 6%{?dist} +Release: 7%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -34,6 +34,9 @@ Patch7: 0007-curl-8.0.1-CVE-2023-46218.patch # fix HSTS long file name clears contents (CVE-2023-46219) Patch8: 0008-curl-8.0.1-CVE-2023-46219.patch +# fix OpenLDAP conftest +Patch9: 0009-curl-8.0.1-fix-openldap-conftest.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -431,6 +434,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Feb 14 2024 Lukáš Zaoral - 8.0.1-7 +- fix openldap conftest + * Wed Dec 06 2023 Jan Macku - 8.0.1-6 - fix HSTS long file name clears contents (CVE-2023-46219) - fix cookie mixed case PSL bypass (CVE-2023-46218)