From e58a7a736904f28acac1ebf936236b5bf5678b52 Mon Sep 17 00:00:00 2001 From: xinghe Date: Sat, 18 Feb 2023 02:16:48 +0000 Subject: [PATCH] fix CVE-2023-23914 CVE-2023-23915 CVE-2023-23916 --- ...t-0001-CVE-2023-23914-CVE-2023-23915.patch | 267 ++++++++++++++ ...t-0002-CVE-2023-23914-CVE-2023-23915.patch | 327 ++++++++++++++++++ ...t-0003-CVE-2023-23914-CVE-2023-23915.patch | 23 ++ ...t-0004-CVE-2023-23914-CVE-2023-23915.patch | 53 +++ ...t-0005-CVE-2023-23914-CVE-2023-23915.patch | 116 +++++++ ...t-0006-CVE-2023-23914-CVE-2023-23915.patch | 43 +++ backport-CVE-2023-23916.patch | 244 +++++++++++++ curl.spec | 15 +- 8 files changed, 1087 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2023-23914-CVE-2023-23915.patch create mode 100644 backport-0002-CVE-2023-23914-CVE-2023-23915.patch create mode 100644 backport-0003-CVE-2023-23914-CVE-2023-23915.patch create mode 100644 backport-0004-CVE-2023-23914-CVE-2023-23915.patch create mode 100644 backport-0005-CVE-2023-23914-CVE-2023-23915.patch create mode 100644 backport-0006-CVE-2023-23914-CVE-2023-23915.patch create mode 100644 backport-CVE-2023-23916.patch diff --git a/backport-0001-CVE-2023-23914-CVE-2023-23915.patch b/backport-0001-CVE-2023-23914-CVE-2023-23915.patch new file mode 100644 index 0000000..0627af2 --- /dev/null +++ b/backport-0001-CVE-2023-23914-CVE-2023-23915.patch @@ -0,0 +1,267 @@ +From 2f34a7347f315513bfda9ef14770d287fb246bcd Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 1 Dec 2022 09:21:04 +0100 +Subject: [PATCH] runtests: do CRLF replacements per section only + +The `crlf="yes"` attribute and "hyper mode" are now only applied on a +subset of dedicated sections: data, datacheck, stdout and protocol. + +Updated test 2500 accordingly. + +Also made test1 use crlf="yes" for , mostly because it is +often used as a template test case. Going forward, using this attribute +we should be able to write test cases using linefeeds only and avoid +mixed line ending encodings. + +Follow-up to ca15b7512e8d11 + +Fixes #10009 +Closes #10010 + +Conflict: remove tests/data/test2500 +Reference: https://github.com/curl/curl/commit/2f34a7347f315513bfda9ef14770d287fb246bcd +--- + tests/FILEFORMAT.md | 22 ++++++++++++++------ + tests/data/test1 | 14 ++++++------- + tests/runtests.pl | 49 +++++++++++++++++++++++++++++++++++++++++---- + 3 files changed, 68 insertions(+), 17 deletions(-) + +diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md +index 464c2eb..70a802c 100644 +--- a/tests/FILEFORMAT.md ++++ b/tests/FILEFORMAT.md +@@ -196,7 +196,7 @@ When using curl built with Hyper, the keywords must include HTTP or HTTPS for + 'hyper mode' to kick in and make line ending checks work for tests. + ## `` + +-### `` ++### `` + + data to be sent to the client on its request and later verified that it + arrived safely. Set `nocheck="yes"` to prevent the test script from verifying +@@ -225,12 +225,16 @@ and used as "raw" data. + `nonewline=yes` means that the last byte (the trailing newline character) + should be cut off from the data before sending or comparing it. + ++`crlf=yes` forces *header* newlines to become CRLF even if not written so in ++the source file. Note that this makes runtests.pl parse and "guess" what is a ++header and what is not in order to apply the CRLF line endings appropriately. ++ + For FTP file listings, the `` section will be used *only* if you make + sure that there has been a CWD done first to a directory named `test-[NUM]` + where `NUM` is the test case number. Otherwise the ftp server can't know from + which test file to load the list content. + +-### `` ++### `` + + Send back this contents instead of the one. The `NUM` is set by: + +@@ -257,7 +261,7 @@ a connect prefix. + ### `` + Address type and address details as logged by the SOCKS proxy. + +-### `` ++### `` + if the data is sent but this is what should be checked afterwards. If + `nonewline=yes` is set, runtests will cut off the trailing newline from the + data before comparing with the one actually received by the client. +@@ -265,7 +269,7 @@ data before comparing with the one actually received by the client. + Use the `mode="text"` attribute if the output is in text mode on platforms + that have a text/binary difference. + +-### `` ++### `` + The contents of numbered `datacheck` sections are appended to the non-numbered + one. + +@@ -561,13 +565,16 @@ 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 + sent by the client The `` and `` rules are applied before + 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 a HTTP proxy (when the http-proxy +@@ -584,7 +591,7 @@ have a text/binary difference. + If `nonewline` is set, we will cut off the trailing newline of this given data + before comparing with the one actually received by the client + +-### `` ++### `` + This verifies that this data was passed to stdout. + + Use the mode="text" attribute if the output is in text mode on platforms that +@@ -593,6 +600,9 @@ have a text/binary difference. + If `nonewline` is set, we will cut off the trailing newline of this given data + before comparing with the one actually received by the client + ++`crlf=yes` forces the newlines to become CRLF even if not written so in the ++test. ++ + ### `` + The file's contents must be identical to this after the test is complete. Use + the mode="text" attribute if the output is in text mode on platforms that have +diff --git a/tests/data/test1 b/tests/data/test1 +index f39a08b..700bed8 100644 +--- a/tests/data/test1 ++++ b/tests/data/test1 +@@ -9,7 +9,7 @@ HTTP GET + # + # Server-side + +- ++ + HTTP/1.1 200 OK + Date: Tue, 09 Nov 2010 14:49:00 GMT + Server: test-server/fake +@@ -42,12 +42,12 @@ 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: */* +- ++ ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ + + + +diff --git a/tests/runtests.pl b/tests/runtests.pl +index 3f61972..dd12c92 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -3501,7 +3501,13 @@ sub subBase64 { + + my $prevupdate; + sub subNewlines { +- my ($thing) = @_; ++ my ($force, $thing) = @_; ++ ++ if($force) { ++ # enforce CRLF newline ++ $$thing =~ s/\x0d*\x0a/\x0d\x0a/; ++ return; ++ } + + # When curl is built with Hyper, it gets all response headers delivered as + # name/value pairs and curl "invents" the newlines when it saves the +@@ -3515,7 +3521,7 @@ sub subNewlines { + # skip curl error messages + ($$thing !~ /^curl: \(\d+\) /))) { + # enforce CRLF newline +- $$thing =~ s/\x0a/\x0d\x0a/; ++ $$thing =~ s/\x0d*\x0a/\x0d\x0a/; + $prevupdate = 1; + } + else { +@@ -3587,6 +3593,7 @@ sub prepro { + my (@entiretest) = @_; + my $show = 1; + my @out; ++ my $data_crlf; + for my $s (@entiretest) { + my $f = $s; + if($s =~ /^ *%if (.*)/) { +@@ -3610,10 +3617,19 @@ sub prepro { + next; + } + if($show) { ++ # The processor does CRLF replacements in the sections if ++ # necessary since those parts might be read by separate servers. ++ if($s =~ /^ */) { ++ if($1 =~ /crlf="yes"/ || $has_hyper) { ++ $data_crlf = 1; ++ } ++ } ++ elsif(($s =~ /^ *<\/data/) && $data_crlf) { ++ $data_crlf = 0; ++ } + subVariables(\$s, $testnum, "%"); + subBase64(\$s); +- subNewlines(\$s) if($has_hyper && ($keywords{"HTTP"} || +- $keywords{"HTTPS"})); ++ subNewlines(0, \$s) if($data_crlf); + push @out, $s; + } + } +@@ -3929,6 +3945,11 @@ sub singletest { + # of the datacheck + chomp($replycheckpart[$#replycheckpart]); + } ++ if($replycheckpartattr{'crlf'} || ++ ($has_hyper && ($keywords{"HTTP"} ++ || $keywords{"HTTPS"}))) { ++ map subNewlines(0, \$_), @replycheckpart; ++ } + push(@reply, @replycheckpart); + } + } +@@ -3950,6 +3971,11 @@ sub singletest { + map s/\r\n/\n/g, @reply; + map s/\n/\r\n/g, @reply; + } ++ if($replyattr{'crlf'} || ++ ($has_hyper && ($keywords{"HTTP"} ++ || $keywords{"HTTPS"}))) { ++ map subNewlines(0, \$_), @reply; ++ } + } + + # this is the valid protocol blurb curl should generate +@@ -4406,6 +4432,12 @@ sub singletest { + chomp($validstdout[$#validstdout]); + } + ++ if($hash{'crlf'} || ++ ($has_hyper && ($keywords{"HTTP"} ++ || $keywords{"HTTPS"}))) { ++ map subNewlines(0, \$_), @validstdout; ++ } ++ + $res = compare($testnum, $testname, "stdout", \@actual, \@validstdout); + if($res) { + return $errorreturncode; +@@ -4506,6 +4538,10 @@ sub singletest { + } + } + ++ if($hash{'crlf'}) { ++ map subNewlines(1, \$_), @protstrip; ++ } ++ + if((!$out[0] || ($out[0] eq "")) && $protstrip[0]) { + logmsg "\n $testnum: protocol FAILED!\n". + " There was no content at all in the file $SERVERIN.\n". +@@ -4637,6 +4673,11 @@ sub singletest { + map s/\r\n/\n/g, @outfile; + map s/\n/\r\n/g, @outfile; + } ++ if($hash{'crlf'} || ++ ($has_hyper && ($keywords{"HTTP"} ++ || $keywords{"HTTPS"}))) { ++ map subNewlines(0, \$_), @outfile; ++ } + + my $strip; + for $strip (@stripfile) { +-- +2.33.0 + diff --git a/backport-0002-CVE-2023-23914-CVE-2023-23915.patch b/backport-0002-CVE-2023-23914-CVE-2023-23915.patch new file mode 100644 index 0000000..6082a20 --- /dev/null +++ b/backport-0002-CVE-2023-23914-CVE-2023-23915.patch @@ -0,0 +1,327 @@ +From 076a2f629119222aeeb50f5a03bf9f9052fabb9a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:20 +0100 +Subject: [PATCH] share: add sharing of HSTS cache among handles + +Closes #10138 + +Conflict: Context adaptation +Reference: https://github.com/curl/curl/commit/076a2f629119222aeeb50f5a03bf9f9052fabb9a +--- + 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 b30cc0f..e7663d1 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 d809940..9558319 100644 +--- a/docs/libcurl/symbols-in-versions ++++ b/docs/libcurl/symbols-in-versions +@@ -71,6 +71,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 e28dd0b..0c50ed7 100644 +--- a/include/curl/curl.h ++++ b/include/curl/curl.h +@@ -2885,6 +2885,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 e3b686e..628d03e 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" + #include "strtoofft.h" + + /* The last 3 #include files should be in this order */ +@@ -552,4 +553,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 5b59754..f7029be 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2251,9 +2251,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; +@@ -2287,10 +2292,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; +@@ -3040,19 +3054,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 441da73..4ab72f4 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1470,6 +1470,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 be5ffca..45cc596 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -445,7 +445,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 1d430b5..8246ee8 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1700,6 +1700,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.33.0 + diff --git a/backport-0003-CVE-2023-23914-CVE-2023-23915.patch b/backport-0003-CVE-2023-23914-CVE-2023-23915.patch new file mode 100644 index 0000000..b7eeb0c --- /dev/null +++ b/backport-0003-CVE-2023-23914-CVE-2023-23915.patch @@ -0,0 +1,23 @@ +From 0bf8b796a0ea98395b390c7807187982215f5c11 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] tool_operate: share HSTS between handles + +Conflict: NA +Reference: https://github.com/curl/curl/commit/0bf8b796a0ea98395b390c7807187982215f5c11 +--- + src/tool_operate.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/tool_operate.c b/src/tool_operate.c +index 616061ee46359..2b0cc083c0cc7 100644 +--- a/src/tool_operate.c ++++ b/src/tool_operate.c +@@ -2721,6 +2721,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 { diff --git a/backport-0004-CVE-2023-23914-CVE-2023-23915.patch b/backport-0004-CVE-2023-23914-CVE-2023-23915.patch new file mode 100644 index 0000000..9ab76ac --- /dev/null +++ b/backport-0004-CVE-2023-23914-CVE-2023-23915.patch @@ -0,0 +1,53 @@ +From dc0725244a3163f1e2d5f51165db3a1a430f3ba0 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] runtests: support crlf="yes" for verify/proxy + +Conflict: Context adaptation +Reference: https://github.com/curl/curl/commit/dc0725244a3163f1e2d5f51165db3a1a430f3ba0 +--- + 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 70a802c..be3bfe2 100644 +--- a/tests/FILEFORMAT.md ++++ b/tests/FILEFORMAT.md +@@ -565,7 +565,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 +@@ -575,7 +575,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 a 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 dd12c92..084f1b5 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -4634,6 +4634,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.33.0 + diff --git a/backport-0005-CVE-2023-23914-CVE-2023-23915.patch b/backport-0005-CVE-2023-23914-CVE-2023-23915.patch new file mode 100644 index 0000000..cb7a039 --- /dev/null +++ b/backport-0005-CVE-2023-23914-CVE-2023-23915.patch @@ -0,0 +1,116 @@ +From ea5aaaa5ede53819f8bc7ae767fc2d13d3704d37 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] test446: verify hsts with two URLs + +Conflict: NA +Reference: https://github.com/curl/curl/commit/ea5aaaa5ede53819f8bc7ae767fc2d13d3704d37 +--- + 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 3a6356bd122bc..fe1bb1c74c2ab 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 0000000000000..0e2dfdcfe33b6 +--- /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" ++ ++ ++ ++ diff --git a/backport-0006-CVE-2023-23914-CVE-2023-23915.patch b/backport-0006-CVE-2023-23914-CVE-2023-23915.patch new file mode 100644 index 0000000..7ad46f0 --- /dev/null +++ b/backport-0006-CVE-2023-23914-CVE-2023-23915.patch @@ -0,0 +1,43 @@ +From ca02a77f05bd5cef20618c8f741aa48b7be0a648 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] hsts: handle adding the same host name again + +It will then use the largest expire time of the two entries. + +Conflict: NA +Reference: https://github.com/curl/curl/commit/ca02a77f05bd5cef20618c8f741aa48b7be0a648 +--- + lib/hsts.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/lib/hsts.c b/lib/hsts.c +index 339237be1c621..8d6723ee587d2 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; + } diff --git a/backport-CVE-2023-23916.patch b/backport-CVE-2023-23916.patch new file mode 100644 index 0000000..4d5616f --- /dev/null +++ b/backport-CVE-2023-23916.patch @@ -0,0 +1,244 @@ +From 119fb187192a9ea13dc90d9d20c215fc82799ab9 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 + +Conflict: Context adaptation +Reference: https://github.com/curl/curl/commit/119fb187192a9ea13dc +--- + lib/content_encoding.c | 7 +- + lib/urldata.h | 1 + + tests/data/Makefile.inc | 2 +- + tests/data/test387 | 2 +- + tests/data/test418 | 152 ++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 158 insertions(+), 6 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 8246ee8..5ef31f5 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -709,6 +709,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 7eb0368..5f128a7 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -68,7 +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 \ +-\ ++ test418 \ + test430 test431 test432 test433 test434 test435 test436 \ + \ + test440 test441 test442 test443 test444 test445 test446 \ +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.33.0 + diff --git a/curl.spec b/curl.spec index acc60ae..a4387ad 100644 --- a/curl.spec +++ b/curl.spec @@ -6,7 +6,7 @@ Name: curl Version: 7.86.0 -Release: 2 +Release: 3 Summary: Curl is used in command lines or scripts to transfer data License: MIT URL: https://curl.haxx.se/ @@ -17,6 +17,13 @@ Patch2: backport-curl-7.84.0-test3026.patch Patch3: backport-curl-7.86.0-noproxy.patch Patch4: backport-CVE-2022-43551-http-use-the-IDN-decoded-name-in-HSTS-checks.patch Patch5: backport-CVE-2022-43552-smb-telnet-do-not-free-the-protocol-struct-in-_done.patch +Patch6: backport-0001-CVE-2023-23914-CVE-2023-23915.patch +Patch7: backport-0002-CVE-2023-23914-CVE-2023-23915.patch +Patch8: backport-0003-CVE-2023-23914-CVE-2023-23915.patch +Patch9: backport-0004-CVE-2023-23914-CVE-2023-23915.patch +Patch10: backport-0005-CVE-2023-23914-CVE-2023-23915.patch +Patch11: backport-0006-CVE-2023-23914-CVE-2023-23915.patch +Patch12: backport-CVE-2023-23916.patch BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel @@ -203,6 +210,12 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_mandir}/man3/* %changelog +* Sat Feb 18 2023 xinghe - 7.86.0-3 +- Type:cves +- ID:CVE-2023-23914 CVE-2023-23915 CVE-2023-23916 +- SUG:NA +- DESC:fix CVE-2023-23914 CVE-2023-23915 CVE-2023-23916 + * Thu Dec 22 2022 zhouyihang - 7.86.0-2 - Type:cves - ID:CVE-2022-43551 CVE-2022-43552