diff --git a/backport-CVE-2022-32205.patch b/backport-CVE-2022-32205.patch new file mode 100644 index 0000000..3354a93 --- /dev/null +++ b/backport-CVE-2022-32205.patch @@ -0,0 +1,154 @@ +Backported of: + +From 631f95b7013ba017692d9512093746af93b4e327 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 19 May 2022 12:12:04 +0200 +Subject: [PATCH] cookie: apply limits + +- Send no more than 150 cookies per request +- Cap the max length used for a cookie: header to 8K +- Cap the max number of received Set-Cookie: headers to 50 +diff --git a/lib/cookie.c b/lib/cookie.c +index e88678c..1d1bf9b 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -453,6 +453,10 @@ Curl_cookie_add(struct Curl_easy *data, + (void)data; + #endif + ++ DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */ ++ if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT) ++ return NULL; ++ + /* First, alloc and init a new struct for it */ + co = calloc(1, sizeof(struct Cookie)); + if(!co) +@@ -771,7 +775,7 @@ Curl_cookie_add(struct Curl_easy *data, + freecookie(co); + return NULL; + } +- ++ data->req.setcookies++; + } + else { + /* This line is NOT a HTTP header style line, we do offer support for +@@ -1268,7 +1272,8 @@ static struct Cookie *dup_cookie(struct Cookie *src) + * + ****************************************************************************/ + +-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, ++struct Cookie *Curl_cookie_getlist(struct Curl_easy *data, ++ struct CookieInfo *c, + const char *host, const char *path, + bool secure) + { +@@ -1317,6 +1322,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + mainco = newco; + + matches++; ++ if(matches >= MAX_COOKIE_SEND_AMOUNT) { ++ infof(data, "Included max number of cookies (%u) in request!", ++ matches); ++ break; ++ } + } + else + goto fail; +diff --git a/lib/cookie.h b/lib/cookie.h +index 066396f..200590e 100644 +--- a/lib/cookie.h ++++ b/lib/cookie.h +@@ -80,10 +80,26 @@ struct CookieInfo { + */ + #define MAX_COOKIE_LINE 5000 + +-/* This is the maximum length of a cookie name or content we deal with: */ ++/* Maximum length of an incoming cookie name or content we deal with. Longer ++ cookies are ignored. */ + #define MAX_NAME 4096 + #define MAX_NAME_TXT "4095" + ++/* Maximum size for an outgoing cookie line libcurl will use in an http ++ request. This is the default maximum length used in some versions of Apache ++ httpd. */ ++#define MAX_COOKIE_HEADER_LEN 8190 ++ ++/* Maximum number of cookies libcurl will send in a single request, even if ++ there might be more cookies that match. One reason to cap the number is to ++ keep the maximum HTTP request within the maximum allowed size. */ ++#define MAX_COOKIE_SEND_AMOUNT 150 ++ ++/* Maximum number of Set-Cookie: lines accepted in a single response. If more ++ such header lines are received, they are ignored. This value must be less ++ than 256 since an unsigned char is used to count. */ ++#define MAX_SET_COOKIE_AMOUNT 50 ++ + struct Curl_easy; + /* + * Add a cookie to the internal list of cookies. The domain and path arguments +@@ -96,7 +112,8 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data, + const char *domain, const char *path, + bool secure); + +-struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, ++struct Cookie *Curl_cookie_getlist(struct Curl_easy *, ++ struct CookieInfo *, const char *, + const char *, bool); + void Curl_cookie_freelist(struct Cookie *cookies); + void Curl_cookie_clearall(struct CookieInfo *cookies); +diff --git a/lib/http.c b/lib/http.c +index 7ccc5b5..3726c32 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1930,6 +1930,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) + #if !defined(CURL_DISABLE_COOKIES) + char *addcookies = NULL; + #endif ++ bool linecap = FALSE; + curl_off_t included_body = 0; + const char *httpstring; + struct dynbuf req; +@@ -2610,7 +2611,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) + + if(data->cookies && data->state.cookie_engine) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); +- co = Curl_cookie_getlist(data->cookies, ++ co = Curl_cookie_getlist(data, data->cookies, + data->state.aptr.cookiehost? + data->state.aptr.cookiehost:host, + data->state.up.path, +@@ -2628,6 +2629,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) + if(result) + break; + } ++ if((Curl_dyn_len(&req) + strlen(co->name) + strlen(co->value) + 1) >= ++ MAX_COOKIE_HEADER_LEN) { ++ infof(data, "Restricted outgoing cookies due to header size, " ++ "'%s' not sent", co->name); ++ linecap = TRUE; ++ break; ++ } + result = Curl_dyn_addf(&req, "%s%s=%s", count?"; ":"", + co->name, co->value); + if(result) +@@ -2638,7 +2646,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) + } + Curl_cookie_freelist(store); + } +- if(addcookies && !result) { ++ if(addcookies && !result && !linecap) { + if(!count) + result = Curl_dyn_add(&req, "Cookie: "); + if(!result) { +diff --git a/lib/urldata.h b/lib/urldata.h +index cbe6bf7..25d1445 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -664,6 +664,7 @@ struct SingleRequest { + #ifndef CURL_DISABLE_DOH + struct dohdata doh; /* DoH specific data for this request */ + #endif ++ unsigned char setcookies; + 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/backport-CVE-2022-32206.patch b/backport-CVE-2022-32206.patch new file mode 100644 index 0000000..bc5ac55 --- /dev/null +++ b/backport-CVE-2022-32206.patch @@ -0,0 +1,42 @@ +Backported of: + +From 7035676c3daa4f1c3766095561f12e7a0e82c736 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 16 May 2022 16:28:13 +0200 +Subject: [PATCH] content_encoding: return error on too many compression steps + +The max allowed steps is arbitrarily set to 5. +diff --git a/lib/content_encoding.c b/lib/content_encoding.c +index 82fcc2b..a89bb3e 100644 +--- a/lib/content_encoding.c ++++ b/lib/content_encoding.c +@@ -1027,6 +1027,9 @@ static const struct content_encoding *find_encoding(const char *name, + return NULL; + } + ++/* allow no more than 5 "chained" compression steps */ ++#define MAX_ENCODE_STACK 5 ++ + /* Set-up the unencoding stack from the Content-Encoding header value. + * See RFC 7231 section 3.1.2.2. */ + CURLcode Curl_build_unencoding_stack(struct connectdata *conn, +@@ -1034,6 +1037,7 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + { + struct Curl_easy *data = conn->data; + struct SingleRequest *k = &data->req; ++ int counter = 0; + + do { + const char *name; +@@ -1068,6 +1072,11 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + 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); ++ return CURLE_BAD_CONTENT_ENCODING; ++ } + /* Stack the unencoding stage. */ + writer = new_unencoding_writer(conn, encoding, k->writer_stack); + if(!writer) diff --git a/backport-CVE-2022-32207.patch b/backport-CVE-2022-32207.patch new file mode 100644 index 0000000..e138862 --- /dev/null +++ b/backport-CVE-2022-32207.patch @@ -0,0 +1,286 @@ +Backported of: + +From 3782dfda5fc4f45a19b1ce1b01ecf7206a3d304a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 25 May 2022 10:09:53 +0200 +Subject: [PATCH 1/3] fopen: add Curl_fopen() for better overwriting of files + +--- + lib/Makefile.inc | 4 +- + lib/altsvc.c | 22 +++------- + lib/cookie.c | 16 ++----- + lib/fopen.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++ + lib/fopen.h | 28 +++++++++++++ + + 5 files changed, 152 insertions(+), 46 deletions(-) + create mode 100644 lib/fopen.c + create mode 100644 lib/fopen.h + +diff --git a/lib/Makefile.inc b/lib/Makefile.inc +index 6d35704..7dac605 100644 +--- a/lib/Makefile.inc ++++ b/lib/Makefile.inc +@@ -50,7 +50,7 @@ LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \ + curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c \ + curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c \ + curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c \ +- file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \ ++ file.c fileinfo.c fopen.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \ + gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c \ + hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c \ + http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \ +@@ -70,7 +70,7 @@ LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \ + curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \ + curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_sec.h curl_setup.h \ + curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h \ +- dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h \ ++ dotdot.h easyif.h escape.h file.h fileinfo.h fopen.h formdata.h ftp.h url.h \ + ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h \ + http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \ + http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h \ +diff --git a/lib/altsvc.c b/lib/altsvc.c +index 4ab77fd..97249b2 100644 +--- a/lib/altsvc.c ++++ b/lib/altsvc.c +@@ -34,7 +34,7 @@ + #include "parsedate.h" + #include "sendf.h" + #include "warnless.h" +-#include "rand.h" ++#include "fopen.h" + #include "rename.h" + + /* The last 3 #include files should be in this order */ +@@ -329,8 +329,7 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data, + struct curl_llist_element *n; + CURLcode result = CURLE_OK; + FILE *out; +- char *tempstore; +- unsigned char randsuffix[9]; ++ char *tempstore = NULL; + + if(!altsvc) + /* no cache activated */ +@@ -344,17 +343,8 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data, + /* marked as read-only, no file or zero length file name */ + return CURLE_OK; + +- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix))) +- return CURLE_FAILED_INIT; +- +- tempstore = aprintf("%s.%s.tmp", file, randsuffix); +- if(!tempstore) +- return CURLE_OUT_OF_MEMORY; +- +- out = fopen(tempstore, FOPEN_WRITETEXT); +- if(!out) +- result = CURLE_WRITE_ERROR; +- else { ++ result = Curl_fopen(data, file, &out, &tempstore); ++ if(!result) { + fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n", + out); +@@ -366,10 +356,10 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data, + break; + } + fclose(out); +- if(!result && Curl_rename(tempstore, file)) ++ if(!result && tempstore && Curl_rename(tempstore, file)) + result = CURLE_WRITE_ERROR; + +- if(result) ++ if(result && tempstore) + unlink(tempstore); + } + free(tempstore); +diff --git a/lib/cookie.c b/lib/cookie.c +index 1d1bf9b..2dc6314 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -99,6 +99,7 @@ Example set of cookies: + #include "parsedate.h" + #include "rand.h" + #include "rename.h" ++#include "fopen.h" + + /* The last 3 #include files should be in this order */ + #include "curl_printf.h" +@@ -1534,17 +1535,8 @@ static int cookie_output(struct Curl_easy *data, + use_stdout = TRUE; + } + else { +- unsigned char randsuffix[9]; +- +- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix))) +- return 2; +- +- tempstore = aprintf("%s.%s.tmp", filename, randsuffix); +- if(!tempstore) +- return 1; +- +- out = fopen(tempstore, FOPEN_WRITETEXT); +- if(!out) ++ error = Curl_fopen(data, filename, &out, &tempstore); ++ if(error) + goto error; + } + +@@ -1591,7 +1583,7 @@ static int cookie_output(struct Curl_easy *data, + if(!use_stdout) { + fclose(out); + out = NULL; +- if(Curl_rename(tempstore, filename)) { ++ if(tempstore && Curl_rename(tempstore, filename)) { + unlink(tempstore); + goto error; + } +diff --git a/lib/fopen.c b/lib/fopen.c +new file mode 100644 +index 0000000..92dc31d +--- /dev/null ++++ b/lib/fopen.c +@@ -0,0 +1,106 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. ++ * ++ * This software is licensed as described in the file COPYING, which ++ * you should have received as part of this distribution. The terms ++ * are also available at https://curl.se/docs/copyright.html. ++ * ++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell ++ * copies of the Software, and permit persons to whom the Software is ++ * furnished to do so, under the terms of the COPYING file. ++ * ++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ++ * KIND, either express or implied. ++ * ++ ***************************************************************************/ ++ ++#include "curl_setup.h" ++ ++#if !defined(CURL_DISABLE_COOKIES) && !defined(CURL_DISABLE_ALTSVC) && \ ++ !defined(CURL_DISABLE_HSTS) ++ ++#ifdef HAVE_FCNTL_H ++#include ++#endif ++ ++#include "urldata.h" ++#include "rand.h" ++#include "fopen.h" ++/* The last 3 #include files should be in this order */ ++#include "curl_printf.h" ++#include "curl_memory.h" ++#include "memdebug.h" ++ ++/* ++ * 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 ++ * name at the time of the open, this function will clone the mode from that ++ * file. if 'tempname' is non-NULL, it needs a rename after the file is ++ * written. ++ */ ++CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, ++ FILE **fh, char **tempname) ++{ ++ CURLcode result = CURLE_WRITE_ERROR; ++ unsigned char randsuffix[9]; ++ char *tempstore = NULL; ++ struct_stat sb, nsb; ++ 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; ++ goto fail; ++ } ++ ++ result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix)); ++ if(result) ++ goto fail; ++ ++ tempstore = aprintf("%s.%s.tmp", filename, randsuffix); ++ if(!tempstore) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto fail; ++ } ++ ++ result = CURLE_WRITE_ERROR; ++ fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600); ++ if(fd == -1) ++ goto fail; ++ ++ if((fstat(fd, &nsb) != -1) && ++ (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) { ++ /* if the user and group are the same, clone the original mode */ ++ if(fchmod(fd, sb.st_mode) == -1) ++ goto fail; ++ } ++ ++ *fh = fdopen(fd, FOPEN_WRITETEXT); ++ if(!*fh) ++ goto fail; ++ ++ *tempname = tempstore; ++ return CURLE_OK; ++ ++fail: ++ if(fd != -1) { ++ close(fd); ++ unlink(tempstore); ++ } ++ ++ free(tempstore); ++ ++ *tempname = NULL; ++ return result; ++} ++ ++#endif /* ! disabled */ +diff --git a/lib/fopen.h b/lib/fopen.h +new file mode 100644 +index 0000000..1020f3c +--- /dev/null ++++ b/lib/fopen.h +@@ -0,0 +1,28 @@ ++#ifndef HEADER_CURL_FOPEN_H ++#define HEADER_CURL_FOPEN_H ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. ++ * ++ * This software is licensed as described in the file COPYING, which ++ * you should have received as part of this distribution. The terms ++ * are also available at https://curl.se/docs/copyright.html. ++ * ++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell ++ * copies of the Software, and permit persons to whom the Software is ++ * furnished to do so, under the terms of the COPYING file. ++ * ++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ++ * KIND, either express or implied. ++ * ++ ***************************************************************************/ ++ ++CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, ++ FILE **fh, char **tempname); ++ ++#endif +-- +2.25.1 + diff --git a/backport-CVE-2022-32208.patch b/backport-CVE-2022-32208.patch new file mode 100644 index 0000000..b3aa631 --- /dev/null +++ b/backport-CVE-2022-32208.patch @@ -0,0 +1,63 @@ +From 4c3f77e871820d055a5f6c4cd7a6ac47a7f3877d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 9 Jun 2022 09:27:24 +0200 +Subject: [PATCH] krb5: return error properly on decode errors + +--- + lib/krb5.c | 5 +---- + lib/security.c | 13 ++++++++++--- + 2 file changed, 11 insertions(+), 7 deletions(-) + +Index: curl-7.74.0/lib/krb5.c +=================================================================== +--- curl-7.74.0.orig/lib/krb5.c ++++ curl-7.74.0/lib/krb5.c +@@ -145,11 +145,8 @@ krb5_decode(void *app_data, void *buf, i + enc.value = buf; + enc.length = len; + maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL); +- if(maj != GSS_S_COMPLETE) { +- if(len >= 4) +- strcpy(buf, "599 "); ++ if(maj != GSS_S_COMPLETE) + return -1; +- } + + memcpy(buf, dec.value, dec.length); + len = curlx_uztosi(dec.length); +--- curl-7.74.0.orig/lib/security.c ++++ curl-7.74.0/lib/security.c +@@ -193,6 +190,7 @@ static CURLcode read_data(struct connect + { + int len; + CURLcode result; ++ int nread; + + result = socket_read(fd, &len, sizeof(len)); + if(result) +@@ -200,7 +197,10 @@ static CURLcode read_data(struct connect + if(len) { + /* only realloc if there was a length */ + len = ntohl(len); +- buf->data = Curl_saferealloc(buf->data, len); ++ if(len > CURL_MAX_INPUT_LENGTH) ++ len = 0; ++ else ++ buf->data = Curl_saferealloc(buf->data, len); + } + if(!len || !buf->data) + return CURLE_OUT_OF_MEMORY; +@@ -208,8 +209,11 @@ static CURLcode read_data(struct connect + result = socket_read(fd, buf->data, len); + if(result) + return result; +- buf->size = conn->mech->decode(conn->app_data, buf->data, len, +- conn->data_prot, conn); ++ nread = conn->mech->decode(conn->app_data, buf->data, len, ++ conn->data_prot, conn); ++ if(nread < 0) ++ return CURLE_RECV_ERROR; ++ buf->size = (size_t)nread; + buf->index = 0; + return CURLE_OK; + } diff --git a/curl.spec b/curl.spec index 5c11eda..65a8027 100644 --- a/curl.spec +++ b/curl.spec @@ -6,7 +6,7 @@ Name: curl Version: 7.71.1 -Release: 14 +Release: 15 Summary: Curl is used in command lines or scripts to transfer data License: MIT URL: https://curl.haxx.se/ @@ -42,6 +42,10 @@ Patch128: backport-002-CVE-2022-27774.patch Patch129: backport-CVE-2022-27781.patch Patch130: backport-pre-CVE-2022-27782.patch Patch131: backport-CVE-2022-27782.patch +Patch132: backport-CVE-2022-32205.patch +Patch133: backport-CVE-2022-32206.patch +Patch134: backport-CVE-2022-32207.patch +Patch135: backport-CVE-2022-32208.patch BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel @@ -183,6 +187,12 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_mandir}/man3/* %changelog +* Wed Jun 29 2022 gaihuiying - 7.71.1-15 +- Type:cves +- CVE:CVE-2022-32205 CVE-2022-32206 CVE-2022-32207 CVE-2022-32208 +- SUG:NA +- DESC:fix CVE-2022-32205 CVE-2022-32206 CVE-2022-32207 CVE-2022-32208 + * Tue May 17 2022 gaihuiying - 7.71.1-14 - Type:cves - CVE:CVE-2022-27781 CVE-2022-27782