diff options
Diffstat (limited to 'meta/recipes-support/curl')
35 files changed, 4305 insertions, 5 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2022-32205.patch b/meta/recipes-support/curl/curl/CVE-2022-32205.patch new file mode 100644 index 0000000000..165fd8af47 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-32205.patch @@ -0,0 +1,174 @@ +From a91c22a072cbb32e296f1efba3502f1b7775dfaf Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Sun, 26 Jun 2022 11:00:48 +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 + +Bug: https://curl.se/docs/CVE-2022-32205.html +CVE-2022-32205 +Reported-by: Harry Sintonen +Closes #9048 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/48d7064a49148f0394] +Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> +--- + lib/cookie.c | 14 ++++++++++++-- + lib/cookie.h | 21 +++++++++++++++++++-- + lib/http.c | 13 +++++++++++-- + lib/urldata.h | 1 + + 4 files changed, 43 insertions(+), 6 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index 1b8c8f9..8a6aa1a 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -477,6 +477,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) +@@ -816,7 +820,7 @@ Curl_cookie_add(struct Curl_easy *data, + freecookie(co); + return NULL; + } +- ++ data->req.setcookies++; + } + else { + /* +@@ -1354,7 +1358,8 @@ static struct Cookie *dup_cookie(struct Cookie *src) + * + * It shall only return cookies that haven't expired. + */ +-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) + { +@@ -1409,6 +1414,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 0ffe08e..7411980 100644 +--- a/lib/cookie.h ++++ b/lib/cookie.h +@@ -81,10 +81,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 +@@ -97,7 +113,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 *c, const char *host, ++struct Cookie *Curl_cookie_getlist(struct Curl_easy *data, ++ struct CookieInfo *c, const char *host, + const char *path, bool secure); + 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 4433824..2c8b0c4 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -2709,12 +2709,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, + } + + #if !defined(CURL_DISABLE_COOKIES) ++ + CURLcode Curl_http_cookies(struct Curl_easy *data, + struct connectdata *conn, + struct dynbuf *r) + { + CURLcode result = CURLE_OK; + char *addcookies = NULL; ++ bool linecap = FALSE; + if(data->set.str[STRING_COOKIE] && + !Curl_checkheaders(data, STRCONST("Cookie"))) + addcookies = data->set.str[STRING_COOKIE]; +@@ -2732,7 +2734,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, + !strcmp(host, "127.0.0.1") || + !strcmp(host, "[::1]") ? TRUE : FALSE; + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); +- co = Curl_cookie_getlist(data->cookies, host, data->state.up.path, ++ co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path, + secure_context); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } +@@ -2746,6 +2748,13 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, + if(result) + break; + } ++ if((Curl_dyn_len(r) + 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(r, "%s%s=%s", count?"; ":"", + co->name, co->value); + if(result) +@@ -2756,7 +2765,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, + } + Curl_cookie_freelist(store); + } +- if(addcookies && !result) { ++ if(addcookies && !result && !linecap) { + if(!count) + result = Curl_dyn_addn(r, STRCONST("Cookie: ")); + if(!result) { +diff --git a/lib/urldata.h b/lib/urldata.h +index e006495..54faf7d 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -707,6 +707,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/meta/recipes-support/curl/curl/CVE-2022-32206.patch b/meta/recipes-support/curl/curl/CVE-2022-32206.patch new file mode 100644 index 0000000000..25f5b27cc7 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-32206.patch @@ -0,0 +1,51 @@ +From e12531340b03d242d3f892aa8797faf12b56dddf Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +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. + +Bug: https://curl.se/docs/CVE-2022-32206.html +CVE-2022-32206 +Reported-by: Harry Sintonen +Closes #9049 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/3a09fbb7f264c67c43] +Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> +--- + lib/content_encoding.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/lib/content_encoding.c b/lib/content_encoding.c +index c03637a..6f994b3 100644 +--- a/lib/content_encoding.c ++++ b/lib/content_encoding.c +@@ -1026,12 +1026,16 @@ 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 Curl_easy *data, + const char *enclist, int maybechunked) + { + struct SingleRequest *k = &data->req; ++ int counter = 0; + + do { + const char *name; +@@ -1066,6 +1070,11 @@ 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); ++ return CURLE_BAD_CONTENT_ENCODING; ++ } + /* Stack the unencoding stage. */ + writer = new_unencoding_writer(data, encoding, k->writer_stack); + if(!writer) diff --git a/meta/recipes-support/curl/curl/CVE-2022-32207.patch b/meta/recipes-support/curl/curl/CVE-2022-32207.patch new file mode 100644 index 0000000000..bc16b62f39 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-32207.patch @@ -0,0 +1,283 @@ +From 759088694e2ba68ddc5ffe042b071dadad6ff675 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Wed, 25 May 2022 10:09:53 +0200 +Subject: [PATCH] fopen: add Curl_fopen() for better overwriting of files + +Bug: https://curl.se/docs/CVE-2022-32207.html +CVE-2022-32207 +Reported-by: Harry Sintonen +Closes #9050 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/20f9dd6bae50b] +Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> +--- + CMakeLists.txt | 1 + + configure.ac | 1 + + lib/Makefile.inc | 2 + + lib/cookie.c | 19 ++----- + lib/curl_config.h.cmake | 3 ++ + lib/fopen.c | 113 ++++++++++++++++++++++++++++++++++++++++ + lib/fopen.h | 30 +++++++++++ + 7 files changed, 154 insertions(+), 15 deletions(-) + create mode 100644 lib/fopen.c + create mode 100644 lib/fopen.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b77de6d..a0bfaad 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1027,6 +1027,7 @@ elseif(HAVE_LIBSOCKET) + set(CMAKE_REQUIRED_LIBRARIES socket) + endif() + ++check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD) + check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) + check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) + check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) +diff --git a/configure.ac b/configure.ac +index d431870..7433bb9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3351,6 +3351,7 @@ AC_CHECK_DECLS([getpwuid_r], [], [AC_DEFINE(HAVE_DECL_GETPWUID_R_MISSING, 1, "Se + + + AC_CHECK_FUNCS([fnmatch \ ++ fchmod \ + geteuid \ + getpass_r \ + getppid \ +diff --git a/lib/Makefile.inc b/lib/Makefile.inc +index e8f110f..5139b03 100644 +--- a/lib/Makefile.inc ++++ b/lib/Makefile.inc +@@ -133,6 +133,7 @@ LIB_CFILES = \ + escape.c \ + file.c \ + fileinfo.c \ ++ fopen.c \ + formdata.c \ + ftp.c \ + ftplistparser.c \ +@@ -263,6 +264,7 @@ LIB_HFILES = \ + escape.h \ + file.h \ + fileinfo.h \ ++ fopen.h \ + formdata.h \ + ftp.h \ + ftplistparser.h \ +diff --git a/lib/cookie.c b/lib/cookie.c +index 8a6aa1a..cb0c03b 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -96,8 +96,8 @@ Example set of cookies: + #include "curl_get_line.h" + #include "curl_memrchr.h" + #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" +@@ -1620,20 +1620,9 @@ static CURLcode 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 CURLE_OUT_OF_MEMORY; +- +- out = fopen(tempstore, FOPEN_WRITETEXT); +- if(!out) { +- error = CURLE_WRITE_ERROR; ++ error = Curl_fopen(data, filename, &out, &tempstore); ++ if(error) + goto error; +- } + } + + fputs("# Netscape HTTP Cookie File\n" +@@ -1680,7 +1669,7 @@ static CURLcode 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); + error = CURLE_WRITE_ERROR; + goto error; +diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake +index d2a0f43..c254359 100644 +--- a/lib/curl_config.h.cmake ++++ b/lib/curl_config.h.cmake +@@ -157,6 +157,9 @@ + /* Define to 1 if you have the <assert.h> header file. */ + #cmakedefine HAVE_ASSERT_H 1 + ++/* Define to 1 if you have the `fchmod' function. */ ++#cmakedefine HAVE_FCHMOD 1 ++ + /* Define to 1 if you have the `basename' function. */ + #cmakedefine HAVE_BASENAME 1 + +diff --git a/lib/fopen.c b/lib/fopen.c +new file mode 100644 +index 0000000..ad3691b +--- /dev/null ++++ b/lib/fopen.c +@@ -0,0 +1,113 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, 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. ++ * ++ * SPDX-License-Identifier: curl ++ * ++ ***************************************************************************/ ++ ++#include "curl_setup.h" ++ ++#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \ ++ !defined(CURL_DISABLE_HSTS) ++ ++#ifdef HAVE_FCNTL_H ++#include <fcntl.h> ++#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; ++ 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; ++ ++#ifdef HAVE_FCHMOD ++ { ++ struct_stat nsb; ++ 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; ++ } ++ } ++#endif ++ ++ *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..289e55f +--- /dev/null ++++ b/lib/fopen.h +@@ -0,0 +1,30 @@ ++#ifndef HEADER_CURL_FOPEN_H ++#define HEADER_CURL_FOPEN_H ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, 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. ++ * ++ * SPDX-License-Identifier: curl ++ * ++ ***************************************************************************/ ++ ++CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, ++ FILE **fh, char **tempname); ++ ++#endif diff --git a/meta/recipes-support/curl/curl/CVE-2022-32208.patch b/meta/recipes-support/curl/curl/CVE-2022-32208.patch new file mode 100644 index 0000000000..9a4e398370 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-32208.patch @@ -0,0 +1,67 @@ +From fd2ffddec315c029e923e6e6f2c049809d01a5fc Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 9 Jun 2022 09:27:24 +0200 +Subject: [PATCH] krb5: return error properly on decode errors + +Bug: https://curl.se/docs/CVE-2022-32208.html +CVE-2022-32208 +Reported-by: Harry Sintonen +Closes #9051 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/6ecdf5136b52af7] +Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> +--- + lib/krb5.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/lib/krb5.c b/lib/krb5.c +index 787137c..6f9e1f7 100644 +--- a/lib/krb5.c ++++ b/lib/krb5.c +@@ -140,11 +140,8 @@ krb5_decode(void *app_data, void *buf, int len, + 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); +@@ -506,6 +503,7 @@ static CURLcode read_data(struct connectdata *conn, + { + int len; + CURLcode result; ++ int nread; + + result = socket_read(fd, &len, sizeof(len)); + if(result) +@@ -514,7 +512,10 @@ static CURLcode read_data(struct connectdata *conn, + 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; +@@ -522,8 +523,11 @@ static CURLcode read_data(struct connectdata *conn, + 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/meta/recipes-support/curl/curl/CVE-2022-32221.patch b/meta/recipes-support/curl/curl/CVE-2022-32221.patch new file mode 100644 index 0000000000..b78b2ce1a8 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-32221.patch @@ -0,0 +1,28 @@ +From a64e3e59938abd7d667e4470a18072a24d7e9de9 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 15 Sep 2022 09:22:45 +0200 +Subject: [PATCH] setopt: when POST is set, reset the 'upload' field + +Reported-by: RobBotic1 on github +Fixes #9507 +Closes #9511 + +CVE: CVE-2022-32221 +Upstream-Status: Backport [https://github.com/curl/curl/commit/a64e3e59938abd7d667e4470a18072a24d7e9de9] +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + lib/setopt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/setopt.c b/lib/setopt.c +index 03c4efdbf1e58..7289a4e78bdd0 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -700,6 +700,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + } + else + data->set.method = HTTPREQ_GET; ++ data->set.upload = FALSE; + break; + + case CURLOPT_HTTPPOST: diff --git a/meta/recipes-support/curl/curl/CVE-2022-35252.patch b/meta/recipes-support/curl/curl/CVE-2022-35252.patch new file mode 100644 index 0000000000..7b6f81bd02 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-35252.patch @@ -0,0 +1,72 @@ +From 62c09239ac4e08239c8e363b06901fc80637d8c7 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 29 Aug 2022 00:09:17 +0200 +Subject: [PATCH] cookie: reject cookies with "control bytes" + +Rejects 0x01 - 0x1f (except 0x09) plus 0x7f + +Reported-by: Axel Chong + +Bug: https://curl.se/docs/CVE-2022-35252.html + +CVE-2022-35252 + +Closes #9381 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/8dfc93e573ca740544a2d79ebb] + +Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> +--- + lib/cookie.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/lib/cookie.c b/lib/cookie.c +index cb0c03b..e0470a1 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -438,6 +438,30 @@ static bool bad_domain(const char *domain) + return TRUE; + } + ++/* ++ RFC 6265 section 4.1.1 says a server should accept this range: ++ ++ cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E ++ ++ But Firefox and Chrome as of June 2022 accept space, comma and double-quotes ++ fine. The prime reason for filtering out control bytes is that some HTTP ++ servers return 400 for requests that contain such. ++*/ ++static int invalid_octets(const char *p) ++{ ++ /* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */ ++ static const char badoctets[] = { ++ "\x01\x02\x03\x04\x05\x06\x07\x08\x0a" ++ "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" ++ "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f" ++ }; ++ size_t vlen, len; ++ /* scan for all the octets that are *not* in cookie-octet */ ++ len = strcspn(p, badoctets); ++ vlen = strlen(p); ++ return (len != vlen); ++} ++ + /* + * Curl_cookie_add + * +@@ -590,6 +614,11 @@ Curl_cookie_add(struct Curl_easy *data, + badcookie = TRUE; + break; + } ++ if(invalid_octets(whatptr) || invalid_octets(name)) { ++ infof(data, "invalid octets in name/value, cookie dropped"); ++ badcookie = TRUE; ++ break; ++ } + } + else if(!len) { + /* +-- +2.35.1 + diff --git a/meta/recipes-support/curl/curl/CVE-2022-42915.patch b/meta/recipes-support/curl/curl/CVE-2022-42915.patch new file mode 100644 index 0000000000..0f37a80e09 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-42915.patch @@ -0,0 +1,53 @@ +From 55e1875729f9d9fc7315cec611bffbd2c817ad89 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 6 Oct 2022 14:13:36 +0200 +Subject: [PATCH] http_proxy: restore the protocol pointer on error + +Reported-by: Trail of Bits + +Closes #9790 + +CVE: CVE-2022-42915 +Upstream-Status: Backport [https://github.com/curl/curl/commit/55e1875729f9d9fc7315cec611bffbd2c817ad89] +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + lib/http_proxy.c | 6 ++---- + lib/url.c | 9 --------- + 2 files changed, 2 insertions(+), 13 deletions(-) + +diff --git a/lib/http_proxy.c b/lib/http_proxy.c +index 1f87f6c62aa40..cc20b3a801941 100644 +--- a/lib/http_proxy.c ++++ b/lib/http_proxy.c +@@ -212,10 +212,8 @@ void Curl_connect_done(struct Curl_easy *data) + Curl_dyn_free(&s->rcvbuf); + Curl_dyn_free(&s->req); + +- /* restore the protocol pointer, if not already done */ +- if(s->prot_save) +- data->req.p.http = s->prot_save; +- s->prot_save = NULL; ++ /* restore the protocol pointer */ ++ data->req.p.http = s->prot_save; + data->info.httpcode = 0; /* clear it as it might've been used for the + proxy */ + data->req.ignorebody = FALSE; +diff --git a/lib/url.c b/lib/url.c +index 690c53c81a3c1..be5ffca2d8b20 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -751,15 +751,6 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn) + DEBUGASSERT(data); + infof(data, "Closing connection %ld", conn->connection_id); + +-#ifndef USE_HYPER +- if(conn->connect_state && conn->connect_state->prot_save) { +- /* If this was closed with a CONNECT in progress, cleanup this temporary +- struct arrangement */ +- data->req.p.http = NULL; +- Curl_safefree(conn->connect_state->prot_save); +- } +-#endif +- + /* possible left-overs from the async name resolvers */ + Curl_resolver_cancel(data); diff --git a/meta/recipes-support/curl/curl/CVE-2022-42916.patch b/meta/recipes-support/curl/curl/CVE-2022-42916.patch new file mode 100644 index 0000000000..fbc592280a --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-42916.patch @@ -0,0 +1,136 @@ +From 53bcf55b4538067e6dc36242168866becb987bb7 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Wed, 12 Oct 2022 10:47:59 +0200 +Subject: [PATCH] url: use IDN decoded names for HSTS checks + +Reported-by: Hiroki Kurosawa + +Closes #9791 + +CVE: CVE-2022-42916 +Upstream-Status: Backport [https://github.com/curl/curl/commit/53bcf55b4538067e6dc36242168866becb987bb7] +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +Comments: Refreshed hunk +--- + lib/url.c | 91 ++++++++++++++++++++++++++++--------------------------- + 1 file changed, 47 insertions(+), 44 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index a3be56bced9de..690c53c81a3c1 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -2012,10 +2012,56 @@ + if(!strcasecompare("file", data->state.up.scheme)) + return CURLE_OUT_OF_MEMORY; + } ++ hostname = data->state.up.hostname; ++ ++ if(hostname && hostname[0] == '[') { ++ /* This looks like an IPv6 address literal. See if there is an address ++ scope. */ ++ size_t hlen; ++ conn->bits.ipv6_ip = TRUE; ++ /* cut off the brackets! */ ++ hostname++; ++ hlen = strlen(hostname); ++ hostname[hlen - 1] = 0; ++ ++ zonefrom_url(uh, data, conn); ++ } ++ ++ /* make sure the connect struct gets its own copy of the host name */ ++ conn->host.rawalloc = strdup(hostname ? hostname : ""); ++ if(!conn->host.rawalloc) ++ return CURLE_OUT_OF_MEMORY; ++ conn->host.name = conn->host.rawalloc; ++ ++ /************************************************************* ++ * IDN-convert the hostnames ++ *************************************************************/ ++ result = Curl_idnconvert_hostname(data, &conn->host); ++ if(result) ++ return result; ++ if(conn->bits.conn_to_host) { ++ result = Curl_idnconvert_hostname(data, &conn->conn_to_host); ++ if(result) ++ return result; ++ } ++#ifndef CURL_DISABLE_PROXY ++ if(conn->bits.httpproxy) { ++ result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); ++ if(result) ++ return result; ++ } ++ if(conn->bits.socksproxy) { ++ result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); ++ if(result) ++ return result; ++ } ++#endif + + #ifndef CURL_DISABLE_HSTS ++ /* HSTS upgrade */ + if(data->hsts && strcasecompare("http", data->state.up.scheme)) { +- if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) { ++ /* This MUST use the IDN decoded name */ ++ if(Curl_hsts(data->hsts, conn->host.name, TRUE)) { + char *url; + Curl_safefree(data->state.up.scheme); + uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0); +@@ -2145,26 +2191,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, + + (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); + +- hostname = data->state.up.hostname; +- if(hostname && hostname[0] == '[') { +- /* This looks like an IPv6 address literal. See if there is an address +- scope. */ +- size_t hlen; +- conn->bits.ipv6_ip = TRUE; +- /* cut off the brackets! */ +- hostname++; +- hlen = strlen(hostname); +- hostname[hlen - 1] = 0; +- +- zonefrom_url(uh, data, conn); +- } +- +- /* make sure the connect struct gets its own copy of the host name */ +- conn->host.rawalloc = strdup(hostname ? hostname : ""); +- if(!conn->host.rawalloc) +- return CURLE_OUT_OF_MEMORY; +- conn->host.name = conn->host.rawalloc; +- + #ifdef ENABLE_IPV6 + if(data->set.scope_id) + /* Override any scope that was set above. */ +@@ -3713,29 +3739,6 @@ static CURLcode create_conn(struct Curl_easy *data, + if(result) + goto out; + +- /************************************************************* +- * IDN-convert the hostnames +- *************************************************************/ +- result = Curl_idnconvert_hostname(data, &conn->host); +- if(result) +- goto out; +- if(conn->bits.conn_to_host) { +- result = Curl_idnconvert_hostname(data, &conn->conn_to_host); +- if(result) +- goto out; +- } +-#ifndef CURL_DISABLE_PROXY +- if(conn->bits.httpproxy) { +- result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); +- if(result) +- goto out; +- } +- if(conn->bits.socksproxy) { +- result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); +- if(result) +- goto out; +- } +-#endif + + /************************************************************* + * Check whether the host and the "connect to host" are equal. diff --git a/meta/recipes-support/curl/curl/CVE-2022-43551.patch b/meta/recipes-support/curl/curl/CVE-2022-43551.patch new file mode 100644 index 0000000000..e1ec7bf72e --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-43551.patch @@ -0,0 +1,35 @@ +From 9e71901634e276dd050481c4320f046bebb1bc28 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 19 Dec 2022 08:36:55 +0100 +Subject: [PATCH] http: use the IDN decoded name in HSTS checks + +Otherwise it stores the info HSTS into the persistent cache for the IDN +name which will not match when the HSTS status is later checked for +using the decoded name. + +Reported-by: Hiroki Kurosawa + +Closes #10111 + +CVE: CVE-2022-43551 +Upstream-Status: Backport [https://github.com/curl/curl/commit/9e71901634e276dd050481c4320f046bebb1bc28] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> +Comments: Hunk refresh to remove patch-fuzz warning + +--- + lib/http.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/http.c b/lib/http.c +index 85528a2218eee..a784745a8d505 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -3652,7 +3652,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, + else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) && + (conn->handler->flags & PROTOPT_SSL)) { + CURLcode check = +- Curl_hsts_parse(data->hsts, data->state.up.hostname, ++ Curl_hsts_parse(data->hsts, conn->host.name, + headp + strlen("Strict-Transport-Security:")); + if(check) + infof(data, "Illegal STS header skipped"); diff --git a/meta/recipes-support/curl/curl/CVE-2022-43552.patch b/meta/recipes-support/curl/curl/CVE-2022-43552.patch new file mode 100644 index 0000000000..dfe6d8c6d5 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2022-43552.patch @@ -0,0 +1,80 @@ +From 4f20188ac644afe174be6005ef4f6ffba232b8b2 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 19 Dec 2022 08:38:37 +0100 +Subject: [PATCH] smb/telnet: do not free the protocol struct in *_done() + +It is managed by the generic layer. + +Reported-by: Trail of Bits + +Closes #10112 + +CVE: CVE-2022-43552 +Upstream-Status: Backport [https://github.com/curl/curl/commit/4f20188ac644afe174be6005ef4f6ffba232b8b2] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + lib/smb.c | 14 ++------------ + lib/telnet.c | 3 --- + 2 files changed, 2 insertions(+), 15 deletions(-) + +diff --git a/lib/smb.c b/lib/smb.c +index 2cfe041dff072..48d5a2fe006d5 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -58,8 +58,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done); + static CURLcode smb_connection_state(struct Curl_easy *data, bool *done); + static CURLcode smb_do(struct Curl_easy *data, bool *done); + static CURLcode smb_request_state(struct Curl_easy *data, bool *done); +-static CURLcode smb_done(struct Curl_easy *data, CURLcode status, +- bool premature); + static CURLcode smb_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead); + static int smb_getsock(struct Curl_easy *data, struct connectdata *conn, +@@ -74,7 +72,7 @@ const struct Curl_handler Curl_handler_smb = { + "SMB", /* scheme */ + smb_setup_connection, /* setup_connection */ + smb_do, /* do_it */ +- smb_done, /* done */ ++ ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ +@@ -101,7 +99,7 @@ const struct Curl_handler Curl_handler_smbs = { + "SMBS", /* scheme */ + smb_setup_connection, /* setup_connection */ + smb_do, /* do_it */ +- smb_done, /* done */ ++ ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + smb_connect, /* connect_it */ + smb_connection_state, /* connecting */ +@@ -936,14 +934,6 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) + return CURLE_OK; + } + +-static CURLcode smb_done(struct Curl_easy *data, CURLcode status, +- bool premature) +-{ +- (void) premature; +- Curl_safefree(data->req.p.smb); +- return status; +-} +- + static CURLcode smb_disconnect(struct Curl_easy *data, + struct connectdata *conn, bool dead) + { +diff --git a/lib/telnet.c b/lib/telnet.c +index 24d3f1efb14c8..22bc81e755222 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -1248,9 +1248,6 @@ static CURLcode telnet_done(struct Curl_easy *data, + + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; +- +- Curl_safefree(data->req.p.telnet); +- + return CURLE_OK; + } + diff --git a/meta/recipes-support/curl/curl/CVE-2023-23914_5-1.patch b/meta/recipes-support/curl/curl/CVE-2023-23914_5-1.patch new file mode 100644 index 0000000000..d357cee76c --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-23914_5-1.patch @@ -0,0 +1,280 @@ +From 076a2f629119222aeeb50f5a03bf9f9052fabb9a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Tue, 27 Dec 2022 11:50:20 +0100 +Subject: [PATCH] share: add sharing of HSTS cache among handles + +Closes #10138 + +CVE: CVE-2023-23914 CVE-2023-23915 +Upstream-Status: Backport [https://github.com/curl/curl/commit/076a2f629119222aeeb50f5a03bf9f9052fabb9a] +Comment: Refreshed hunk from hsts.c and urldata.h +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + 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 ++ + 9 files changed, 109 insertions(+), 11 deletions(-) + +--- 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; + +--- a/lib/hsts.c ++++ b/lib/hsts.c +@@ -37,6 +37,7 @@ + #include "parsedate.h" + #include "rand.h" + #include "rename.h" ++#include "share.h" + #include "strtoofft.h" + + /* The last 3 #include files should be in this order */ +@@ -561,4 +562,18 @@ + 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 */ +--- a/lib/hsts.h ++++ b/lib/hsts.h +@@ -59,9 +59,11 @@ CURLcode Curl_hsts_loadfile(struct Curl_ + 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 */ +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2260,9 +2260,14 @@ CURLcode Curl_vsetopt(struct Curl_easy * + 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->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 * + 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) { +--- 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 *sha + #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 *sha + #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 *sh + 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; +--- 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, +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1398,6 +1398,9 @@ CURLcode Curl_pretransfer(struct Curl_ea + 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 +--- a/lib/url.c ++++ b/lib/url.c +@@ -434,7 +434,11 @@ CURLcode Curl_close(struct Curl_easy **d + 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 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1670,6 +1670,8 @@ + + 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; diff --git a/meta/recipes-support/curl/curl/CVE-2023-23914_5-2.patch b/meta/recipes-support/curl/curl/CVE-2023-23914_5-2.patch new file mode 100644 index 0000000000..668972cb3f --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-23914_5-2.patch @@ -0,0 +1,23 @@ +From 0bf8b796a0ea98395b390c7807187982215f5c11 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] tool_operate: share HSTS between handles + +CVE: CVE-2023-23914 CVE-2023-23915 +Upstream-Status: Backport [https://github.com/curl/curl/pull/10138/commits/ca17cfed2df001356cfe2841f166569bac0f5e8c] +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + src/tool_operate.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/src/tool_operate.c ++++ b/src/tool_operate.c +@@ -2722,6 +2722,7 @@ CURLcode operate(struct GlobalConfig *gl + 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/meta/recipes-support/curl/curl/CVE-2023-23914_5-3.patch b/meta/recipes-support/curl/curl/CVE-2023-23914_5-3.patch new file mode 100644 index 0000000000..4422b26834 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-23914_5-3.patch @@ -0,0 +1,45 @@ +From ca02a77f05bd5cef20618c8f741aa48b7be0a648 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +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. + +CVE: CVE-2023-23914 CVE-2023-23915 +Upstream-Status: Backport [https://github.com/curl/curl/pull/10138/commits/e077b30a42272d964d76e5b815a0af7dc65d8360] +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + 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/meta/recipes-support/curl/curl/CVE-2023-23914_5-4.patch b/meta/recipes-support/curl/curl/CVE-2023-23914_5-4.patch new file mode 100644 index 0000000000..865b3f93a5 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-23914_5-4.patch @@ -0,0 +1,48 @@ +From dc0725244a3163f1e2d5f51165db3a1a430f3ba0 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] runtests: support crlf="yes" for verify/proxy + +CVE: CVE-2023-23914 CVE-2023-23915 +Upstream-Status: Backport [https://github.com/curl/curl/pull/10138/commits/fd7e1a557e414dd803c9225e37a2ca84e1df2269] +Comment: Refreshed hunk from FILEFORMAT.md +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + tests/FILEFORMAT.md | 4 ++-- + tests/runtests.pl | 5 +++++ + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/tests/FILEFORMAT.md ++++ b/tests/FILEFORMAT.md +@@ -540,14 +540,14 @@ + One perl op per line that operates on the protocol dump. This is pretty + advanced. Example: `s/^EPRT .*/EPRT stripped/`. + +-### `<protocol [nonewline="yes"]>` ++### `<protocol [nonewline="yes"][crlf="yes"]>` + + 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 `<strip>` and `<strippart>` rules are applied before + comparisons are made. + +-### `<proxy [nonewline="yes"]>` ++### `<proxy [nonewline="yes"][crlf="yes"]>` + + 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 +--- 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; diff --git a/meta/recipes-support/curl/curl/CVE-2023-23914_5-5.patch b/meta/recipes-support/curl/curl/CVE-2023-23914_5-5.patch new file mode 100644 index 0000000000..1a363f0b4b --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-23914_5-5.patch @@ -0,0 +1,118 @@ +From ea5aaaa5ede53819f8bc7ae767fc2d13d3704d37 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Tue, 27 Dec 2022 11:50:23 +0100 +Subject: [PATCH] test446: verify hsts with two URLs + +CVE: CVE-2023-23914 CVE-2023-23915 +Upstream-Status: Backport [https://github.com/curl/curl/pull/10138/commits/7e89dfd463597701dd1defcad7be54f7d3c9d55d] +Comment: Refreshed hunk from Makefile.inc +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + 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 +@@ -72,6 +72,7 @@ + \ + test430 test431 test432 test433 test434 test435 test436 \ + \ ++test446 \ + test490 test491 test492 test493 test494 \ + \ + test500 test501 test502 test503 test504 test505 test506 test507 test508 \ +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 @@ ++<?xml version="1.0" encoding="ISO-8859-1"?> ++<testcase> ++<info> ++<keywords> ++HTTP ++HTTP proxy ++HSTS ++trailing-dot ++</keywords> ++</info> ++ ++<reply> ++ ++# we use this as response to a CONNECT ++<connect nocheck="yes"> ++HTTP/1.1 200 OK ++ ++</connect> ++<data crlf="yes"> ++HTTP/1.1 200 OK ++Content-Length: 6 ++Strict-Transport-Security: max-age=604800 ++ ++-foo- ++</data> ++<data2 crlf="yes"> ++HTTP/1.1 200 OK ++Content-Length: 6 ++Strict-Transport-Security: max-age=6048000 ++ ++-baa- ++</data2> ++</reply> ++ ++<client> ++<server> ++https ++http-proxy ++</server> ++<features> ++HSTS ++proxy ++https ++debug ++</features> ++<setenv> ++CURL_HSTS_HTTP=yes ++CURL_TIME=2000000000 ++</setenv> ++ ++<name> ++HSTS with two URLs ++</name> ++<command> ++-x http://%HOSTIP:%PROXYPORT --hsts log/hsts%TESTNUMBER http://this.hsts.example./%TESTNUMBER http://another.example.com/%TESTNUMBER0002 ++</command> ++</client> ++ ++<verify> ++# we let it CONNECT to the server to confirm HSTS but deny from there ++<proxy crlf="yes"> ++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 ++ ++</proxy> ++ ++<file name="log/hsts%TESTNUMBER" mode="text"> ++# 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" ++</file> ++ ++</verify> ++</testcase> diff --git a/meta/recipes-support/curl/curl/CVE-2023-23916.patch b/meta/recipes-support/curl/curl/CVE-2023-23916.patch new file mode 100644 index 0000000000..a57d275902 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-23916.patch @@ -0,0 +1,219 @@ +From 119fb187192a9ea13dc90d9d20c215fc82799ab9 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat <patrick@monnerat.net> +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 + +CVE: CVE-2023-23916 +Upstream-Status: Backport [https://github.com/curl/curl/commit/119fb187192a9ea13dc.patch] +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +--- + 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 + +--- a/lib/content_encoding.c ++++ b/lib/content_encoding.c +@@ -1037,7 +1037,6 @@ CURLcode Curl_build_unencoding_stack(str + const char *enclist, int maybechunked) + { + struct SingleRequest *k = &data->req; +- int counter = 0; + + do { + const char *name; +@@ -1072,9 +1071,9 @@ CURLcode Curl_build_unencoding_stack(str + 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. */ +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -682,6 +682,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 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -69,6 +69,7 @@ + \ + test400 test401 test402 test403 test404 test405 test406 test407 test408 \ + test409 test410 \ ++test418 \ + \ + test430 test431 test432 test433 test434 test435 test436 \ + \ +--- /dev/null ++++ b/tests/data/test418 +@@ -0,0 +1,152 @@ ++<testcase> ++<info> ++<keywords> ++HTTP ++gzip ++</keywords> ++</info> ++ ++# ++# Server-side ++<reply> ++<data nocheck="yes"> ++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- ++</data> ++</reply> ++ ++# ++# Client-side ++<client> ++<server> ++http ++</server> ++ <name> ++Response with multiple Transfer-Encoding headers ++ </name> ++ <command> ++http://%HOSTIP:%HTTPPORT/%TESTNUMBER -sS ++</command> ++</client> ++ ++# ++# Verify data after the test has been "shot" ++<verify> ++<protocol crlf="yes"> ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ ++</protocol> ++ ++# CURLE_BAD_CONTENT_ENCODING is 61 ++<errorcode> ++61 ++</errorcode> ++<stderr mode="text"> ++curl: (61) Reject response due to more than 5 content encodings ++</stderr> ++</verify> ++</testcase> diff --git a/meta/recipes-support/curl/curl/CVE-2023-27533.patch b/meta/recipes-support/curl/curl/CVE-2023-27533.patch new file mode 100644 index 0000000000..b69b20c85a --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-27533.patch @@ -0,0 +1,208 @@ +From 538b1e79a6e7b0bb829ab4cecc828d32105d0684 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 6 Mar 2023 12:07:33 +0100 +Subject: [PATCH] telnet: parse telnet options without sscanf & only accept option arguments in ascii + +To avoid embedded telnet negotiation commands etc. + +Reported-by: Harry Sintonen +Closes #10728 + +CVE: CVE-2023-27533 +Upstream-Status: Backport [https://github.com/curl/curl/commit/0c28ba2faae2d7da780a66d2446045a560192cdc && https://github.com/curl/curl/commit/538b1e79a6e7b0bb829ab4cecc828d32105d0684] + +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> +--- + lib/telnet.c | 149 +++++++++++++++++++++++++++++++-------------------- + 1 file changed, 91 insertions(+), 58 deletions(-) + +diff --git a/lib/telnet.c b/lib/telnet.c +index e709973..3ecd680 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -768,22 +768,32 @@ 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; + struct curl_slist *beg; +- char option_keyword[128] = ""; +- char option_arg[256] = ""; + struct TELNET *tn = data->req.p.telnet; +- struct connectdata *conn = data->conn; + CURLcode result = CURLE_OK; +- int binary_option; + + /* Add the user name as an environment variable if it + was given on the command line */ + if(data->state.aptr.user) { +- msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); +- beg = curl_slist_append(tn->telnet_vars, option_arg); ++ char buffer[256]; ++ if(str_is_nonascii(data->conn->user)) ++ return CURLE_BAD_FUNCTION_ARGUMENT; ++ msnprintf(buffer, sizeof(buffer), "USER,%s", data->conn->user); ++ beg = curl_slist_append(tn->telnet_vars, buffer); + if(!beg) { + curl_slist_free_all(tn->telnet_vars); + tn->telnet_vars = NULL; +@@ -793,68 +803,91 @@ static CURLcode check_telnet_options(struct Curl_easy *data) + tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + } + +- for(head = data->set.telnet_options; head; head = head->next) { +- if(sscanf(head->data, "%127[^= ]%*[ =]%255s", +- option_keyword, option_arg) == 2) { +- +- /* Terminal type */ +- if(strcasecompare(option_keyword, "TTYPE")) { +- strncpy(tn->subopt_ttype, option_arg, 31); +- tn->subopt_ttype[31] = 0; /* String termination */ +- tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; ++ for(head = data->set.telnet_options; head && !result; head = head->next) { ++ size_t olen; ++ char *option = head->data; ++ char *arg; ++ char *sep = strchr(option, '='); ++ if(sep) { ++ olen = sep - option; ++ arg = ++sep; ++ if(str_is_nonascii(arg)) + continue; +- } ++ switch(olen) { ++ case 5: ++ /* Terminal type */ ++ if(strncasecompare(option, "TTYPE", 5)) { ++ strncpy(tn->subopt_ttype, arg, 31); ++ tn->subopt_ttype[31] = 0; /* String termination */ ++ tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; ++ } ++ else ++ result = CURLE_UNKNOWN_OPTION; ++ break; + +- /* Display variable */ +- if(strcasecompare(option_keyword, "XDISPLOC")) { +- strncpy(tn->subopt_xdisploc, option_arg, 127); +- tn->subopt_xdisploc[127] = 0; /* String termination */ +- tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; +- continue; +- } ++ case 8: ++ /* Display variable */ ++ if(strncasecompare(option, "XDISPLOC", 8)) { ++ strncpy(tn->subopt_xdisploc, arg, 127); ++ tn->subopt_xdisploc[127] = 0; /* String termination */ ++ tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; ++ } ++ else ++ result = CURLE_UNKNOWN_OPTION; ++ break; + +- /* Environment variable */ +- if(strcasecompare(option_keyword, "NEW_ENV")) { +- beg = curl_slist_append(tn->telnet_vars, option_arg); +- if(!beg) { +- result = CURLE_OUT_OF_MEMORY; +- break; ++ case 7: ++ /* Environment variable */ ++ if(strncasecompare(option, "NEW_ENV", 7)) { ++ beg = curl_slist_append(tn->telnet_vars, arg); ++ if(!beg) { ++ result = CURLE_OUT_OF_MEMORY; ++ break; ++ } ++ tn->telnet_vars = beg; ++ tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; + } +- tn->telnet_vars = beg; +- tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; +- continue; +- } ++ else ++ result = CURLE_UNKNOWN_OPTION; ++ break; + +- /* Window Size */ +- if(strcasecompare(option_keyword, "WS")) { +- if(sscanf(option_arg, "%hu%*[xX]%hu", +- &tn->subopt_wsx, &tn->subopt_wsy) == 2) +- tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; +- else { +- failf(data, "Syntax error in telnet option: %s", head->data); +- result = CURLE_SETOPT_OPTION_SYNTAX; +- break; ++ case 2: ++ /* Window Size */ ++ if(strncasecompare(option, "WS", 2)) { ++ if(sscanf(arg, "%hu%*[xX]%hu", ++ &tn->subopt_wsx, &tn->subopt_wsy) == 2) ++ tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; ++ else { ++ failf(data, "Syntax error in telnet option: %s", head->data); ++ result = CURLE_SETOPT_OPTION_SYNTAX; ++ } + } +- continue; +- } ++ else ++ result = CURLE_UNKNOWN_OPTION; ++ break; + +- /* To take care or not of the 8th bit in data exchange */ +- if(strcasecompare(option_keyword, "BINARY")) { +- binary_option = atoi(option_arg); +- if(binary_option != 1) { +- tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; +- tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; ++ case 6: ++ /* To take care or not of the 8th bit in data exchange */ ++ if(strncasecompare(option, "BINARY", 6)) { ++ int binary_option = atoi(arg); ++ if(binary_option != 1) { ++ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; ++ tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; ++ } + } +- continue; ++ else ++ result = CURLE_UNKNOWN_OPTION; ++ break; ++ default: ++ failf(data, "Unknown telnet option %s", head->data); ++ result = CURLE_UNKNOWN_OPTION; ++ break; + } +- +- failf(data, "Unknown telnet option %s", head->data); +- result = CURLE_UNKNOWN_OPTION; +- break; + } +- failf(data, "Syntax error in telnet option: %s", head->data); +- result = CURLE_SETOPT_OPTION_SYNTAX; +- break; ++ else { ++ failf(data, "Syntax error in telnet option: %s", head->data); ++ result = CURLE_SETOPT_OPTION_SYNTAX; ++ } + } + + if(result) { +-- +2.25.1 + diff --git a/meta/recipes-support/curl/curl/CVE-2023-27534.patch b/meta/recipes-support/curl/curl/CVE-2023-27534.patch new file mode 100644 index 0000000000..9109faaf88 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-27534.patch @@ -0,0 +1,122 @@ +From 4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 9 Mar 2023 16:22:11 +0100 +Subject: [PATCH] curl_path: create the new path with dynbuf + +CVE: CVE-2023-27534 +Upstream-Status: Backport [https://github.com/curl/curl/commit/4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6] + +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> +--- + lib/curl_path.c | 71 ++++++++++++++++++++++++------------------------- + 1 file changed, 35 insertions(+), 36 deletions(-) + +diff --git a/lib/curl_path.c b/lib/curl_path.c +index a1669d1..b9c470f 100644 +--- a/lib/curl_path.c ++++ b/lib/curl_path.c +@@ -30,66 +30,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); +- real_path[homelen] = '/'; +- real_path[homelen + 1] = '\0'; +- if(working_path_len > 3) { +- memcpy(real_path + homelen + 1, 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.25.1 + diff --git a/meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch b/meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch new file mode 100644 index 0000000000..57e1cb9e13 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-27535-pre1.patch @@ -0,0 +1,196 @@ +From ed5095ed94281989e103c72e032200b83be37878 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 6 Oct 2022 00:49:10 +0200 +Subject: [PATCH] strcase: add and use Curl_timestrcmp + +This is a strcmp() alternative function for comparing "secrets", +designed to take the same time no matter the content to not leak +match/non-match info to observers based on how fast it is. + +The time this function takes is only a function of the shortest input +string. + +Reported-by: Trail of Bits + +Closes #9658 + +Upstream-Status: Backport from [https://github.com/curl/curl/commit/ed5095ed94281989e103c72e032200b83be37878] +Comment: to backport fix for CVE-2023-27535, add function Curl_timestrcmp. +Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> +--- + lib/netrc.c | 6 +++--- + lib/strcase.c | 22 ++++++++++++++++++++++ + lib/strcase.h | 1 + + lib/url.c | 33 +++++++++++++-------------------- + lib/vauth/digest_sspi.c | 4 ++-- + lib/vtls/vtls.c | 4 ++-- + 6 files changed, 43 insertions(+), 27 deletions(-) + +diff --git a/lib/netrc.c b/lib/netrc.c +index 0a4ae2c..b771b60 100644 +--- a/lib/netrc.c ++++ b/lib/netrc.c +@@ -140,9 +140,9 @@ static int parsenetrc(const char *host, + /* we are now parsing sub-keywords concerning "our" host */ + if(state_login) { + if(specific_login) { +- state_our_login = strcasecompare(login, tok); ++ state_our_login = !Curl_timestrcmp(login, tok); + } +- else if(!login || strcmp(login, tok)) { ++ else if(!login || Curl_timestrcmp(login, tok)) { + if(login_alloc) { + free(login); + login_alloc = FALSE; +@@ -158,7 +158,7 @@ static int parsenetrc(const char *host, + } + else if(state_password) { + if((state_our_login || !specific_login) +- && (!password || strcmp(password, tok))) { ++ && (!password || Curl_timestrcmp(password, tok))) { + if(password_alloc) { + free(password); + password_alloc = FALSE; +diff --git a/lib/strcase.c b/lib/strcase.c +index 692a3f1..be085b3 100644 +--- a/lib/strcase.c ++++ b/lib/strcase.c +@@ -141,6 +141,28 @@ bool Curl_safecmp(char *a, char *b) + return !a && !b; + } + ++/* ++ * Curl_timestrcmp() returns 0 if the two strings are identical. The time this ++ * function spends is a function of the shortest string, not of the contents. ++ */ ++int Curl_timestrcmp(const char *a, const char *b) ++{ ++ int match = 0; ++ int i = 0; ++ ++ if(a && b) { ++ while(1) { ++ match |= a[i]^b[i]; ++ if(!a[i] || !b[i]) ++ break; ++ i++; ++ } ++ } ++ else ++ return a || b; ++ return match; ++} ++ + /* --- public functions --- */ + + int curl_strequal(const char *first, const char *second) +diff --git a/lib/strcase.h b/lib/strcase.h +index 382b80a..c6979da 100644 +--- a/lib/strcase.h ++++ b/lib/strcase.h +@@ -48,5 +48,6 @@ void Curl_strntoupper(char *dest, const char *src, size_t n); + void Curl_strntolower(char *dest, const char *src, size_t n); + + bool Curl_safecmp(char *a, char *b); ++int Curl_timestrcmp(const char *first, const char *second); + + #endif /* HEADER_CURL_STRCASE_H */ +diff --git a/lib/url.c b/lib/url.c +index df4377d..c397b57 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -930,19 +930,10 @@ socks_proxy_info_matches(const struct proxy_info *data, + /* the user information is case-sensitive + or at least it is not defined as case-insensitive + see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */ +- if(!data->user != !needle->user) +- return FALSE; +- /* curl_strequal does a case insentive comparison, so do not use it here! */ +- if(data->user && +- needle->user && +- strcmp(data->user, needle->user) != 0) +- return FALSE; +- if(!data->passwd != !needle->passwd) +- return FALSE; ++ + /* curl_strequal does a case insentive comparison, so do not use it here! */ +- if(data->passwd && +- needle->passwd && +- strcmp(data->passwd, needle->passwd) != 0) ++ if(Curl_timestrcmp(data->user, needle->user) || ++ Curl_timestrcmp(data->passwd, needle->passwd)) + return FALSE; + return TRUE; + } +@@ -1341,10 +1332,10 @@ ConnectionExists(struct Curl_easy *data, + if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) { + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ +- if(strcmp(needle->user, check->user) || +- strcmp(needle->passwd, check->passwd) || +- !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) || +- !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) { ++ if(Curl_timestrcmp(needle->user, check->user) || ++ Curl_timestrcmp(needle->passwd, check->passwd) || ++ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) || ++ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ + continue; + } +@@ -1420,8 +1411,8 @@ ConnectionExists(struct Curl_easy *data, + possible. (Especially we must not reuse the same connection if + partway through a handshake!) */ + if(wantNTLMhttp) { +- if(strcmp(needle->user, check->user) || +- strcmp(needle->passwd, check->passwd)) { ++ if(Curl_timestrcmp(needle->user, check->user) || ++ Curl_timestrcmp(needle->passwd, check->passwd)) { + + /* we prefer a credential match, but this is at least a connection + that can be reused and "upgraded" to NTLM */ +@@ -1443,8 +1434,10 @@ ConnectionExists(struct Curl_easy *data, + if(!check->http_proxy.user || !check->http_proxy.passwd) + continue; + +- if(strcmp(needle->http_proxy.user, check->http_proxy.user) || +- strcmp(needle->http_proxy.passwd, check->http_proxy.passwd)) ++ if(Curl_timestrcmp(needle->http_proxy.user, ++ check->http_proxy.user) || ++ Curl_timestrcmp(needle->http_proxy.passwd, ++ check->http_proxy.passwd)) + continue; + } + else if(check->proxy_ntlm_state != NTLMSTATE_NONE) { +diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c +index 94f8f8c..a413419 100644 +--- a/lib/vauth/digest_sspi.c ++++ b/lib/vauth/digest_sspi.c +@@ -429,8 +429,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + has changed then delete that context. */ + if((userp && !digest->user) || (!userp && digest->user) || + (passwdp && !digest->passwd) || (!passwdp && digest->passwd) || +- (userp && digest->user && strcmp(userp, digest->user)) || +- (passwdp && digest->passwd && strcmp(passwdp, digest->passwd))) { ++ (userp && digest->user && Curl_timestrcmp(userp, digest->user)) || ++ (passwdp && digest->passwd && Curl_timestrcmp(passwdp, digest->passwd))) { + if(digest->http_context) { + s_pSecFn->DeleteSecurityContext(digest->http_context); + Curl_safefree(digest->http_context); +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index e2d3438..881c8d2 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -146,8 +146,8 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + Curl_safecmp(data->random_file, needle->random_file) && + Curl_safecmp(data->egdsocket, needle->egdsocket) && + #ifdef USE_TLS_SRP +- Curl_safecmp(data->username, needle->username) && +- Curl_safecmp(data->password, needle->password) && ++ !Curl_timestrcmp(data->username, needle->username) && ++ !Curl_timestrcmp(data->password, needle->password) && + (data->authtype == needle->authtype) && + #endif + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && +-- +2.35.7 + diff --git a/meta/recipes-support/curl/curl/CVE-2023-27535_and_CVE-2023-27538.patch b/meta/recipes-support/curl/curl/CVE-2023-27535_and_CVE-2023-27538.patch new file mode 100644 index 0000000000..4e701edfff --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-27535_and_CVE-2023-27538.patch @@ -0,0 +1,170 @@ +From 8f4608468b890dce2dad9f91d5607ee7e9c1aba1 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +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-Status: Backport from [https://github.com/curl/curl/commit/8f4608468b890dce2dad9f91d5607ee7e9c1aba1, https://github.com/curl/curl/commit/af369db4d3833272b8ed443f7fcc2e757a0872eb] +Comment: Backport for CVE-2023-27535 also fixes CVE-2023-27538 in the file "lib/url.c". +CVE: CVE-2023-27535, CVE-2023-27538 +Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> +--- + lib/ftp.c | 28 ++++++++++++++++++++++++++-- + lib/ftp.h | 5 +++++ + lib/setopt.c | 2 +- + lib/url.c | 19 ++++++++++++++++--- + lib/urldata.h | 4 ++-- + 5 files changed, 50 insertions(+), 8 deletions(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index c6efaed..93bbaeb 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -4097,6 +4097,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); +@@ -4364,11 +4366,31 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, + { + char *type; + struct FTP *ftp; ++ 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=<typecode>" that +@@ -4403,7 +4425,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 CURLE_OK; + } +diff --git a/lib/ftp.h b/lib/ftp.h +index 1cfdac0..afca25b 100644 +--- a/lib/ftp.h ++++ b/lib/ftp.h +@@ -115,6 +115,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 */ +@@ -144,6 +146,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 29a78a4..89d0150 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2304,7 +2304,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 c397b57..280171c 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1347,11 +1347,24 @@ ConnectionExists(struct Curl_easy *data, + (check->httpversion >= 20) && + (data->state.httpwant < CURL_HTTP_VERSION_2_0)) + continue; +- +- if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { +- if(!ssh_config_matches(needle, check)) ++#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 69eb2ee..6e6122a 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1748,8 +1748,6 @@ struct UserDefined { + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ + #endif +- curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or +- IMAP or POP3 or others! */ + long new_file_perms; /* Permissions to use when creating remote files */ + long new_directory_perms; /* Permissions to use when creating remote dirs */ + long ssh_auth_types; /* allowed SSH auth types */ +@@ -1877,6 +1875,8 @@ struct UserDefined { + BIT(http09_allowed); /* allow HTTP/0.9 responses */ + BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some + recipients */ ++ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or ++ IMAP or POP3 or others! (type: curl_usessl)*/ + }; + + struct Names { +-- +2.35.7 + diff --git a/meta/recipes-support/curl/curl/CVE-2023-27536.patch b/meta/recipes-support/curl/curl/CVE-2023-27536.patch new file mode 100644 index 0000000000..d3d1d2dc2e --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-27536.patch @@ -0,0 +1,53 @@ +From cb49e67303dbafbab1cebf4086e3ec15b7d56ee5 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Fri, 10 Mar 2023 09:22:43 +0100 +Subject: [PATCH] url: only reuse connections with same GSS delegation + +Upstream-Status: Backport from [https://github.com/curl/curl/commit/cb49e67303dbafbab1cebf4086e3ec15b7d56ee5] +CVE: CVE-2023-27536 +Signed-off-by: Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> +Signed-off-by: Sourav Kumar Pramanik <pramanik.souravkumar@gmail.com> +--- + lib/url.c | 6 ++++++ + lib/urldata.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/lib/url.c b/lib/url.c +index 280171c..c6413a1 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1341,6 +1341,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) && +@@ -1813,6 +1818,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 6e6122a..602c735 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1131,6 +1131,7 @@ struct connectdata { + int socks5_gssapi_enctype; + #endif + unsigned short localport; ++ long gssapi_delegation; /* inherited from set.gssapi_delegation */ + }; + + /* The end of connectdata. */ +-- +2.35.7 diff --git a/meta/recipes-support/curl/curl/CVE-2023-28319.patch b/meta/recipes-support/curl/curl/CVE-2023-28319.patch new file mode 100644 index 0000000000..c0bca9a56e --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-28319.patch @@ -0,0 +1,33 @@ +From 8e21b1a05f3c0ee098dbcb6c3d84cb61f102a122 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Mon, 8 May 2023 14:33:54 +0200 +Subject: [PATCH] libssh2: free fingerprint better + +Reported-by: Wei Chong Tan +Closes #11088 + +CVE: CVE-2023-28319 +Upstream-Status: Backport [https://github.com/curl/curl/commit/8e21b1a05f3c0ee098dbcb6c] +Comments: Hunks Refreshed +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + lib/vssh/libssh2.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c +index bfcc94e160178..dd39a844c646b 100644 +--- a/lib/vssh/libssh2.c ++++ b/lib/vssh/libssh2.c +@@ -695,11 +695,10 @@ + */ + if((pub_pos != b64_pos) || + Curl_strncasecompare(fingerprint_b64, pubkey_sha256, pub_pos) != 1) { +- free(fingerprint_b64); +- + failf(data, + "Denied establishing ssh session: mismatch sha256 fingerprint. " + "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256); ++ free(fingerprint_b64); + state(data, SSH_SESSION_FREE); + sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; + return sshc->actualcode; diff --git a/meta/recipes-support/curl/curl/CVE-2023-28320-fol1.patch b/meta/recipes-support/curl/curl/CVE-2023-28320-fol1.patch new file mode 100644 index 0000000000..2ba74aaaa9 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-28320-fol1.patch @@ -0,0 +1,197 @@ +From f446258f0269a62289cca0210157cb8558d0edc3 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Tue, 16 May 2023 23:40:42 +0200 +Subject: [PATCH] hostip: include easy_lock.h before using + GLOBAL_INIT_IS_THREADSAFE + +Since that header file is the only place that define can be defined. + +Reported-by: Marc Deslauriers + +Follow-up to 13718030ad4b3209 + +Closes #11121 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/f446258f0269a62289cca0210157cb8558d0edc3] +CVE: CVE-2023-28320 +Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com> +--- + lib/easy_lock.h | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ + lib/hostip.c | 10 ++--- + lib/hostip.h | 9 ---- + 3 files changed, 113 insertions(+), 15 deletions(-) + create mode 100644 lib/easy_lock.h + +diff --git a/lib/easy_lock.h b/lib/easy_lock.h +new file mode 100644 +index 0000000..6399a39 +--- /dev/null ++++ b/lib/easy_lock.h +@@ -0,0 +1,109 @@ ++#ifndef HEADER_CURL_EASY_LOCK_H ++#define HEADER_CURL_EASY_LOCK_H ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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. ++ * ++ * SPDX-License-Identifier: curl ++ * ++ ***************************************************************************/ ++ ++#include "curl_setup.h" ++ ++#define GLOBAL_INIT_IS_THREADSAFE ++ ++#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 ++ ++#ifdef __MINGW32__ ++#ifndef __MINGW64_VERSION_MAJOR ++#if (__MINGW32_MAJOR_VERSION < 5) || \ ++ (__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0) ++/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */ ++typedef PVOID SRWLOCK, *PSRWLOCK; ++#endif ++#endif ++#ifndef SRWLOCK_INIT ++#define SRWLOCK_INIT NULL ++#endif ++#endif /* __MINGW32__ */ ++ ++#define curl_simple_lock SRWLOCK ++#define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT ++ ++#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m) ++#define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m) ++ ++#elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H) ++#include <stdatomic.h> ++#if defined(HAVE_SCHED_YIELD) ++#include <sched.h> ++#endif ++ ++#define curl_simple_lock atomic_int ++#define CURL_SIMPLE_LOCK_INIT 0 ++ ++/* a clang-thing */ ++#ifndef __has_builtin ++#define __has_builtin(x) 0 ++#endif ++ ++#ifndef __INTEL_COMPILER ++/* The Intel compiler tries to look like GCC *and* clang *and* lies in its ++ __has_builtin() function, so override it. */ ++ ++/* if GCC on i386/x86_64 or if the built-in is present */ ++#if ( (defined(__GNUC__) && !defined(__clang__)) && \ ++ (defined(__i386__) || defined(__x86_64__))) || \ ++ __has_builtin(__builtin_ia32_pause) ++#define HAVE_BUILTIN_IA32_PAUSE ++#endif ++ ++#endif ++ ++static inline void curl_simple_lock_lock(curl_simple_lock *lock) ++{ ++ for(;;) { ++ if(!atomic_exchange_explicit(lock, true, memory_order_acquire)) ++ break; ++ /* Reduce cache coherency traffic */ ++ while(atomic_load_explicit(lock, memory_order_relaxed)) { ++ /* Reduce load (not mandatory) */ ++#ifdef HAVE_BUILTIN_IA32_PAUSE ++ __builtin_ia32_pause(); ++#elif defined(__aarch64__) ++ __asm__ volatile("yield" ::: "memory"); ++#elif defined(HAVE_SCHED_YIELD) ++ sched_yield(); ++#endif ++ } ++ } ++} ++ ++static inline void curl_simple_lock_unlock(curl_simple_lock *lock) ++{ ++ atomic_store_explicit(lock, false, memory_order_release); ++} ++ ++#else ++ ++#undef GLOBAL_INIT_IS_THREADSAFE ++ ++#endif ++ ++#endif /* HEADER_CURL_EASY_LOCK_H */ +diff --git a/lib/hostip.c b/lib/hostip.c +index e15c17a..c2e0962 100644 +--- a/lib/hostip.c ++++ b/lib/hostip.c +@@ -72,6 +72,8 @@ + #include <SystemConfiguration/SCDynamicStoreCopySpecific.h> + #endif + ++#include "easy_lock.h" ++ + #if defined(CURLRES_SYNCH) && \ + defined(HAVE_ALARM) && \ + defined(SIGALRM) && \ +@@ -81,10 +83,6 @@ + #define USE_ALARM_TIMEOUT + #endif + +-#ifdef USE_ALARM_TIMEOUT +-#include "easy_lock.h" +-#endif +- + #define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */ + + /* +@@ -260,8 +258,8 @@ void Curl_hostcache_prune(struct Curl_easy *data) + /* Beware this is a global and unique instance. This is used to store the + return address that we can jump back to from inside a signal handler. This + is not thread-safe stuff. */ +-sigjmp_buf curl_jmpenv; +-curl_simple_lock curl_jmpenv_lock; ++static sigjmp_buf curl_jmpenv; ++static curl_simple_lock curl_jmpenv_lock; + #endif + + /* lookup address, returns entry if found and not stale */ +diff --git a/lib/hostip.h b/lib/hostip.h +index 1db5981..a46bdc6 100644 +--- a/lib/hostip.h ++++ b/lib/hostip.h +@@ -189,15 +189,6 @@ Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr, + #define CURL_INADDR_NONE INADDR_NONE + #endif + +-#ifdef HAVE_SIGSETJMP +-/* Forward-declaration of variable defined in hostip.c. Beware this +- * is a global and unique instance. This is used to store the return +- * address that we can jump back to from inside a signal handler. +- * This is not thread-safe stuff. +- */ +-extern sigjmp_buf curl_jmpenv; +-#endif +- + /* + * Function provided by the resolver backend to set DNS servers to use. + */ +-- +2.25.1 + diff --git a/meta/recipes-support/curl/curl/CVE-2023-28320.patch b/meta/recipes-support/curl/curl/CVE-2023-28320.patch new file mode 100644 index 0000000000..1e0fc7534a --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-28320.patch @@ -0,0 +1,83 @@ +From 13718030ad4b3209a7583b4f27f683cd3a6fa5f2 Mon Sep 17 00:00:00 2001 +From: Harry Sintonen <sintonen@iki.fi> +Date: Tue, 25 Apr 2023 09:22:26 +0200 +Subject: [PATCH] hostip: add locks around use of global buffer for alarm() + +When building with the sync name resolver and timeout ability we now +require thread-safety to be present to enable it. + +Closes #11030 + +CVE: CVE-2023-28320 +Upstream-Status: Backport [https://github.com/curl/curl/commit/13718030ad4b3209a7583b] +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + lib/hostip.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/lib/hostip.c b/lib/hostip.c +index 2381290fdd43e..e410cda69ae6e 100644 +--- a/lib/hostip.c ++++ b/lib/hostip.c +@@ -70,12 +70,19 @@ + #include <SystemConfiguration/SCDynamicStoreCopySpecific.h> + #endif + +-#if defined(CURLRES_SYNCH) && \ +- defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) ++#if defined(CURLRES_SYNCH) && \ ++ defined(HAVE_ALARM) && \ ++ defined(SIGALRM) && \ ++ defined(HAVE_SIGSETJMP) && \ ++ defined(GLOBAL_INIT_IS_THREADSAFE) + /* alarm-based timeouts can only be used with all the dependencies satisfied */ + #define USE_ALARM_TIMEOUT + #endif + ++#ifdef USE_ALARM_TIMEOUT ++#include "easy_lock.h" ++#endif ++ + #define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */ + + /* +@@ -254,11 +261,12 @@ void Curl_hostcache_prune(struct Curl_easy *data) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + } + +-#ifdef HAVE_SIGSETJMP ++#ifdef USE_ALARM_TIMEOUT + /* Beware this is a global and unique instance. This is used to store the + return address that we can jump back to from inside a signal handler. This + is not thread-safe stuff. */ + sigjmp_buf curl_jmpenv; ++curl_simple_lock curl_jmpenv_lock; + #endif + + /* lookup address, returns entry if found and not stale */ +@@ -832,7 +840,6 @@ enum resolve_t Curl_resolv(struct Curl_easy *data, + static + void alarmfunc(int sig) + { +- /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ + (void)sig; + siglongjmp(curl_jmpenv, 1); + } +@@ -912,6 +919,8 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, + This should be the last thing we do before calling Curl_resolv(), + as otherwise we'd have to worry about variables that get modified + before we invoke Curl_resolv() (and thus use "volatile"). */ ++ curl_simple_lock_lock(&curl_jmpenv_lock); ++ + if(sigsetjmp(curl_jmpenv, 1)) { + /* this is coming from a siglongjmp() after an alarm signal */ + failf(data, "name lookup timed out"); +@@ -980,6 +989,8 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data, + #endif + #endif /* HAVE_SIGACTION */ + ++ curl_simple_lock_unlock(&curl_jmpenv_lock); ++ + /* switch back the alarm() to either zero or to what it was before minus + the time we spent until now! */ + if(prev_alarm) { diff --git a/meta/recipes-support/curl/curl/CVE-2023-28321.patch b/meta/recipes-support/curl/curl/CVE-2023-28321.patch new file mode 100644 index 0000000000..bcd8b112db --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-28321.patch @@ -0,0 +1,302 @@ +From 199f2d440d8659b42670c1b796220792b01a97bf Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +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 + +CVE: CVE-2023-28321 +Upstream-Status: Backport [https://github.com/curl/curl/commit/199f2d440d8659b42] +Comments: Hunks removed as changes already exist +Removed hunks from files: +tests/unit/Makefile.am +tests/unit/Makefile.inc +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + lib/vtls/hostcheck.c | 50 +++++++-------- + tests/data/test1397 | 10 ++- + tests/unit/Makefile.am | 94 ---------------------------- + tests/unit/Makefile.inc | 94 ++++++++++++++++++++++++++++ + tests/unit/unit1397.c | 134 ++++++++++++++++++++++++---------------- + 5 files changed, 202 insertions(+), 180 deletions(-) + +diff --git a/lib/vtls/hostcheck.c b/lib/vtls/hostcheck.c +index e827dc58f378c..d061c6356f97f 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 84f962abebee3..f31b2c2a3f330 100644 +--- a/tests/data/test1397 ++++ b/tests/data/test1397 +@@ -2,8 +2,7 @@ + <info> + <keywords> + unittest +-ssl +-wildcard ++Curl_cert_hostcheck + </keywords> + </info> + +@@ -16,9 +15,8 @@ none + <features> + unittest + </features> +- <name> +-Check wildcard certificate matching function Curl_cert_hostcheck +- </name> ++<name> ++Curl_cert_hostcheck unit tests ++</name> + </client> +- + </testcase> +diff --git a/tests/unit/unit1397.c b/tests/unit/unit1397.c +index 2f3d3aa4d09e1..3ae75618d5d10 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 diff --git a/meta/recipes-support/curl/curl/CVE-2023-28322-1.patch b/meta/recipes-support/curl/curl/CVE-2023-28322-1.patch new file mode 100644 index 0000000000..547127001d --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-28322-1.patch @@ -0,0 +1,84 @@ +From efbf02111aa66bda9288506b7d5cc0226bf5453e Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Sun, 12 Feb 2023 13:24:08 +0100 +Subject: [PATCH] smb: return error on upload without size + +The protocol needs to know the size ahead of time, this is now a known +restriction and not a bug. + +Also output a clearer error if the URL path does not contain proper +share. + +Ref: #7896 +Closes #10484 + +CVE: CVE-2023-28322 +Upstream-Status: Backport [https://github.com/curl/curl/commit/efbf02111aa66bda9288506b7d5cc0226bf5453e] +Comments: Hunks refreshed +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + docs/KNOWN_BUGS | 5 ----- + docs/URL-SYNTAX.md | 3 +++ + lib/smb.c | 6 ++++++ + 3 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS +index cbf5be352a279..a515e7a59bdfd 100644 +--- a/docs/KNOWN_BUGS ++++ b/docs/KNOWN_BUGS +@@ -58,7 +58,6 @@ + 5.7 Visual Studio project gaps + 5.8 configure finding libs in wrong directory + 5.9 Utilize Requires.private directives in libcurl.pc +- 5.10 curl hangs on SMB upload over stdin + 5.11 configure --with-gssapi with Heimdal is ignored on macOS + 5.12 flaky Windows CI builds + +@@ -332,10 +331,6 @@ problems may have been fixed or changed somewhat since this was written. + + https://github.com/curl/curl/issues/864 + +-5.10 curl hangs on SMB upload over stdin +- +- See https://github.com/curl/curl/issues/7896 +- + 5.11 configure --with-gssapi with Heimdal is ignored on macOS + + ... unless you also pass --with-gssapi-libs +diff --git a/docs/URL-SYNTAX.md b/docs/URL-SYNTAX.md +index 691fcceacd66c..802bbdef96979 100644 +--- a/docs/URL-SYNTAX.md ++++ b/docs/URL-SYNTAX.md +@@ -360,6 +360,9 @@ share and directory or the share to upload to and as such, may not be omitted. + If the user name is embedded in the URL then it must contain the domain name + and as such, the backslash must be URL encoded as %2f. + ++When uploading to SMB, the size of the file needs to be known ahead of time, ++meaning that you can upload a file passed to curl over a pipe like stdin. ++ + curl supports SMB version 1 (only) + + ## SMTP +diff --git a/lib/smb.c b/lib/smb.c +index 8a76763c157ce..dc0abe784bcee 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -763,6 +763,11 @@ 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)) { ++ failf(data, "SMB upload needs to know the size up front"); ++ return CURLE_SEND_ERROR; ++ } ++ + /* Start the request */ + if(req->state == SMB_REQUESTING) { + result = smb_send_tree_connect(data); +@@ -993,6 +998,7 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data, + /* The share must be present */ + if(!slash) { + Curl_safefree(smbc->share); ++ failf(data, "missing share in URL path for SMB"); + return CURLE_URL_MALFORMAT; + } diff --git a/meta/recipes-support/curl/curl/CVE-2023-28322-2.patch b/meta/recipes-support/curl/curl/CVE-2023-28322-2.patch new file mode 100644 index 0000000000..f2134dd1c3 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-28322-2.patch @@ -0,0 +1,436 @@ +From 7815647d6582c0a4900be2e1de6c5e61272c496b Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +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 + +CVE: CVE-2023-28322 +Upstream-Status: Backport [https://github.com/curl/curl/commit/7815647d6582c0a4900be2e1de] +Comments: Hunks refreshed +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + 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 2679a2cdc1afe..406fb42ac0f44 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 51c5d07ce40ab..c751e8861a99b 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 f50d7baf622f8..4ff68cc454cbc 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1348,7 +1348,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 +@@ -3384,7 +3384,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 && +@@ -3640,7 +3640,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) +@@ -4233,7 +4233,7 @@ + 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 80e43f6f361e8..bffdd3468536d 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -2033,7 +2033,7 @@ + Curl_HttpReq 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 */ +@@ -2423,7 +2423,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 c2f675d4b2618..1952e66a1efcd 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 ea99d720ec4eb..ccd7264b00e74 100644 +--- a/lib/rtsp.c ++++ b/lib/rtsp.c +@@ -493,7 +493,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; + +@@ -512,7 +512,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 38f5711e44191..0c3b9634d1192 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -333,8 +333,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 */ +@@ -625,7 +625,6 @@ + } + else + data->set.method = HTTPREQ_GET; +- data->set.upload = FALSE; + break; + + case CURLOPT_HTTPPOST: +@@ -888,7 +887,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 a1e444ee6b97e..d6822213529bc 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 7a030308d4689..c182cace742d7 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 164d3c723c5b9..8ed1b887b4d21 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 e9ab8fbf09510..cb69f3365855a 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1293,6 +1293,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); + } + + /* +@@ -1767,7 +1767,6 @@ + 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->set.opt_no_body?"HEAD":"GET"); + } +@@ -1770,7 +1770,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 cca992a0295aa..a8580bdb66fe8 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1487,6 +1487,7 @@ + BIT(url_alloc); /* URL string is malloc()'ed */ + BIT(referer_alloc); /* referer string is malloc()ed */ + BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */ ++ BIT(upload); /* upload request */ + }; + + /* +@@ -1838,7 +1839,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 b31f741ba9492..d60edaa303642 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 f1154dc47a74e..f2e5352d1fd3a 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 17d59ecd23bc8..2ca91b7363b1d 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] == '/') diff --git a/meta/recipes-support/curl/curl/CVE-2023-38545.patch b/meta/recipes-support/curl/curl/CVE-2023-38545.patch new file mode 100644 index 0000000000..c198d29c04 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-38545.patch @@ -0,0 +1,133 @@ +From fb4415d8aee6c1045be932a34fe6107c2f5ed147 Mon Sep 17 00:00:00 2001 +From: Jay Satiro <raysatiro@yahoo.com> +Date: Wed, 11 Oct 2023 07:34:19 +0200 +Subject: [PATCH] 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. + +Upstream-Status: Backport [https://github.com/curl/curl/commit/fb4415d8aee6c1045be932a34fe6107c2f5ed147] + +CVE: CVE-2023-38545 + +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> +--- + lib/socks.c | 8 +++--- + tests/data/Makefile.inc | 2 +- + tests/data/test722 | 64 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+), 5 deletions(-) + create mode 100644 tests/data/test722 + +diff --git a/lib/socks.c b/lib/socks.c +index a014aa6..2215c02 100644 +--- a/lib/socks.c ++++ b/lib/socks.c +@@ -536,9 +536,9 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, + + /* 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)) +@@ -879,7 +879,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, + } + 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], hostname, hostname_len); /* address w/o NULL */ + len += hostname_len; + } +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 3064b39..47117b6 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -99,7 +99,7 @@ test670 test671 test672 test673 test674 test675 test676 test677 test678 \ + \ + 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 test722 \ + \ + test800 test801 test802 test803 test804 test805 test806 test807 test808 \ + test809 test810 test811 test812 test813 test814 test815 test816 test817 \ +diff --git a/tests/data/test722 b/tests/data/test722 +new file mode 100644 +index 0000000..05bcf28 +--- /dev/null ++++ b/tests/data/test722 +@@ -0,0 +1,64 @@ ++<testcase> ++<info> ++<keywords> ++HTTP ++HTTP GET ++SOCKS5 ++SOCKS5h ++followlocation ++</keywords> ++</info> ++ ++# ++# Server-side ++<reply> ++# 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. ++<data> ++HTTP/1.1 301 Moved Permanently ++Location: http://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/ ++Content-Length: 0 ++Connection: close ++ ++</data> ++</reply> ++ ++# ++# Client-side ++<client> ++<features> ++proxy ++</features> ++<server> ++http ++socks5 ++</server> ++ <name> ++SOCKS5h with HTTP redirect to hostname too long ++ </name> ++ <command> ++--no-progress-meter --location --proxy socks5h://%HOSTIP:%SOCKSPORT http://%HOSTIP:%HTTPPORT/%TESTNUMBER ++</command> ++</client> ++ ++# ++# Verify data after the test has been "shot" ++<verify> ++<protocol crlf="yes"> ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ ++</protocol> ++<errorcode> ++97 ++</errorcode> ++# 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. ++<stderr mode="text"> ++curl: (97) SOCKS5: the destination hostname is too long to be resolved remotely by the proxy. ++</stderr> ++</verify> ++</testcase> +-- +2.40.0 diff --git a/meta/recipes-support/curl/curl/CVE-2023-38546.patch b/meta/recipes-support/curl/curl/CVE-2023-38546.patch new file mode 100644 index 0000000000..1b2f1e7a7d --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-38546.patch @@ -0,0 +1,137 @@ +From 61275672b46d9abb3285740467b882e22ed75da8 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 14 Sep 2023 23:28:32 +0200 +Subject: [PATCH] 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 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/61275672b46d9abb32857404] + +CVE: CVE-2023-38546 + +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> +--- + lib/cookie.c | 13 +------------ + lib/cookie.h | 13 ++++--------- + lib/easy.c | 4 +--- + 3 files changed, 6 insertions(+), 24 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index e0470a1..38d8d6c 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -115,7 +115,6 @@ static void freecookie(struct Cookie *co) + free(co->name); + free(co->value); + free(co->maxage); +- free(co->version); + free(co); + } + +@@ -707,11 +706,7 @@ Curl_cookie_add(struct Curl_easy *data, + } + } + else if(strcasecompare("version", name)) { +- strstore(&co->version, whatptr); +- if(!co->version) { +- badcookie = TRUE; +- break; +- } ++ /* just ignore */ + } + else if(strcasecompare("max-age", name)) { + /* +@@ -1132,7 +1127,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 */ +@@ -1210,9 +1204,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. +@@ -1363,7 +1354,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; +@@ -1579,7 +1569,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 7411980..645600a 100644 +--- a/lib/cookie.h ++++ b/lib/cookie.h +@@ -34,11 +34,7 @@ struct Cookie { + char *domain; /* domain = <this> */ + curl_off_t expires; /* expires = <this> */ + char *expirestr; /* the plain text version */ +- +- /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ +- char *version; /* Version = <value> */ + char *maxage; /* Max-Age = <value> */ +- + 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 */ +@@ -54,18 +50,17 @@ 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 0e23561..31abf9e 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -841,9 +841,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.40.0 diff --git a/meta/recipes-support/curl/curl/CVE-2023-46218.patch b/meta/recipes-support/curl/curl/CVE-2023-46218.patch new file mode 100644 index 0000000000..d7d7908ea0 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-46218.patch @@ -0,0 +1,52 @@ +Backport of: + +From 2b0994c29a721c91c572cff7808c572a24d251eb Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 23 Nov 2023 08:15:47 +0100 +Subject: [PATCH] cookie: lowercase the domain names before PSL checks + +Reported-by: Harry Sintonen + +Closes #12387 + +CVE: CVE-2023-46218 +Upstream-Status: Backport [https://github.com/curl/curl/commit/2b0994c29a721c91c57] +Signed-off-by: Poonam Jadhav <poonam.jadhav@kpit.com> +--- + lib/cookie.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +--- 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); + } +- else +- acceptable = !bad_domain(domain); + + if(!acceptable) { + infof(data, "cookie '%s' dropped, domain '%s' must not " diff --git a/meta/recipes-support/curl/curl/CVE-2023-46219-0001.patch b/meta/recipes-support/curl/curl/CVE-2023-46219-0001.patch new file mode 100644 index 0000000000..55e8f6fac9 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-46219-0001.patch @@ -0,0 +1,42 @@ +From 0c667188e0c6cda615a036b8a2b4125f2c404dde Mon Sep 17 00:00:00 2001 +From: SaltyMilk <soufiane.elmelcaoui@gmail.com> +Date: Mon, 10 Jul 2023 21:43:28 +0200 +Subject: [PATCH] fopen: optimize + +Closes #11419 + +CVE: CVE-2023-46219 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/0c667188e0c6] + +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> +--- + lib/fopen.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index ad3691b..92f39cf 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.40.0 diff --git a/meta/recipes-support/curl/curl/CVE-2023-46219-0002.patch b/meta/recipes-support/curl/curl/CVE-2023-46219-0002.patch new file mode 100644 index 0000000000..f432fabbb1 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-46219-0002.patch @@ -0,0 +1,133 @@ +From 73b65e94f3531179de45c6f3c836a610e3d0a846 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Thu, 23 Nov 2023 08:23:17 +0100 +Subject: [PATCH] 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 + +CVE: CVE-2023-46219 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/73b65e94f3531179] + +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> +--- + lib/fopen.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 59 insertions(+), 4 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index 92f39cf..1670e32 100644 +--- a/lib/fopen.c ++++ b/lib/fopen.c +@@ -39,6 +39,50 @@ + #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 +94,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 +148,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + if(!*fh) + goto fail; + ++ free(dir); + *tempname = tempstore; + return CURLE_OK; + +@@ -107,6 +161,7 @@ fail: + free(tempstore); + + *tempname = NULL; ++ free(dir); + return result; + } + +-- +2.40.0 diff --git a/meta/recipes-support/curl/curl/CVE-2023-46219-0003.patch b/meta/recipes-support/curl/curl/CVE-2023-46219-0003.patch new file mode 100644 index 0000000000..3b6f756549 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2023-46219-0003.patch @@ -0,0 +1,81 @@ +From f27b8dba73295cb5296a50f2c19c0739b502eb94 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg <daniel@haxx.se> +Date: Fri, 24 Nov 2023 09:46:32 +0100 +Subject: [PATCH] fopen: allocate the dir after fopen + +Move the allocation of the directory name down to after the fopen() call +to allow that shortcut code path to avoid a superfluous malloc+free +cycle. + +Follow-up to 73b65e94f35311 + +Closes #12398 + +CVE: CVE-2023-46219 + +Upstream-Status: Backport [https://github.com/curl/curl/commit/f27b8dba73295cb529] + +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> +--- + lib/fopen.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index 1670e32..b663f8b 100644 +--- a/lib/fopen.c ++++ b/lib/fopen.c +@@ -98,18 +98,13 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + char *tempstore = NULL; + struct_stat sb; + int fd = -1; +- char *dir; ++ char *dir = NULL; + *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)){ +- free(dir); + return CURLE_OK; + } + fclose(*fh); +@@ -119,9 +114,13 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + if(result) + goto fail; + +- /* The temp file name should not end up too long for the target file +- system */ +- tempstore = aprintf("%s%s.tmp", dir, randbuf); ++ dir = dirslash(filename); ++ if(dir) { ++ /* The temp file name should not end up too long for the target file ++ system */ ++ tempstore = aprintf("%s%s.tmp", dir, randbuf); ++ free(dir); ++ } + if(!tempstore) { + result = CURLE_OUT_OF_MEMORY; + goto fail; +@@ -148,7 +147,6 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + if(!*fh) + goto fail; + +- free(dir); + *tempname = tempstore; + return CURLE_OK; + +@@ -161,7 +159,6 @@ fail: + free(tempstore); + + *tempname = NULL; +- free(dir); + return result; + } + +-- +2.40.0 diff --git a/meta/recipes-support/curl/curl/CVE-2024-2398.patch b/meta/recipes-support/curl/curl/CVE-2024-2398.patch new file mode 100644 index 0000000000..ea55117f4d --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2024-2398.patch @@ -0,0 +1,89 @@ +Backport of: + +From deca8039991886a559b67bcd6701db800a5cf764 Mon Sep 17 00:00:00 2001 +From: Stefan Eissing <stefan@eissing.org> +Date: Wed, 6 Mar 2024 09:36:08 +0100 +Subject: [PATCH] http2: push headers better cleanup + +- provide common cleanup method for push headers + +Closes #13054 + +Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/curl/tree/debian/patches/CVE-2024-2398.patch?h=ubuntu/jammy-security +Upstream commit https://github.com/curl/curl/commit/deca8039991886a559b67bcd6701db800a5cf764] +CVE: CVE-2024-2398 +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> +--- + lib/http2.c | 34 +++++++++++++++------------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -555,6 +555,15 @@ static int set_transfer_url(struct Curl_ + return 0; + } + ++static void free_push_headers(struct HTTP *stream) ++{ ++ size_t i; ++ for(i = 0; i<stream->push_headers_used; i++) ++ free(stream->push_headers[i]); ++ Curl_safefree(stream->push_headers); ++ stream->push_headers_used = 0; ++} ++ + static int push_promise(struct Curl_easy *data, + struct connectdata *conn, + const nghttp2_push_promise *frame) +@@ -568,7 +577,6 @@ static int push_promise(struct Curl_easy + struct curl_pushheaders heads; + CURLMcode rc; + struct http_conn *httpc; +- size_t i; + /* clone the parent */ + struct Curl_easy *newhandle = duphandle(data); + if(!newhandle) { +@@ -604,11 +612,7 @@ static int push_promise(struct Curl_easy + Curl_set_in_callback(data, false); + + /* free the headers again */ +- for(i = 0; i<stream->push_headers_used; i++) +- free(stream->push_headers[i]); +- free(stream->push_headers); +- stream->push_headers = NULL; +- stream->push_headers_used = 0; ++ free_push_headers(stream); + + if(rv) { + DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT)); +@@ -1045,10 +1049,10 @@ static int on_header(nghttp2_session *se + stream->push_headers_alloc) { + char **headp; + stream->push_headers_alloc *= 2; +- headp = Curl_saferealloc(stream->push_headers, +- stream->push_headers_alloc * sizeof(char *)); ++ headp = realloc(stream->push_headers, ++ stream->push_headers_alloc * sizeof(char *)); + if(!headp) { +- stream->push_headers = NULL; ++ free_push_headers(stream); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + stream->push_headers = headp; +@@ -1214,15 +1218,7 @@ void Curl_http2_done(struct Curl_easy *d + setup */ + Curl_dyn_free(&http->header_recvbuf); + Curl_dyn_free(&http->trailer_recvbuf); +- if(http->push_headers) { +- /* if they weren't used and then freed before */ +- for(; http->push_headers_used > 0; --http->push_headers_used) { +- free(http->push_headers[http->push_headers_used - 1]); +- } +- free(http->push_headers); +- http->push_headers = NULL; +- } +- ++ free_push_headers(http); + if(!(data->conn->handler->protocol&PROTO_FAMILY_HTTP) || + !httpc->h2) /* not HTTP/2 ? */ + return; diff --git a/meta/recipes-support/curl/curl_7.82.0.bb b/meta/recipes-support/curl/curl_7.82.0.bb index d5dfe62a39..72d8544e08 100644 --- a/meta/recipes-support/curl/curl_7.82.0.bb +++ b/meta/recipes-support/curl/curl_7.82.0.bb @@ -6,7 +6,7 @@ HTTP post, SSL connections, proxy support, FTP uploads, and more!" HOMEPAGE = "https://curl.se/" BUGTRACKER = "https://github.com/curl/curl/issues" SECTION = "console/network" -LICENSE = "MIT-open-group" +LICENSE = "curl" LIC_FILES_CHKSUM = "file://COPYING;md5=190c514872597083303371684954f238" SRC_URI = "https://curl.se/download/${BP}.tar.xz \ @@ -24,12 +24,49 @@ SRC_URI = "https://curl.se/download/${BP}.tar.xz \ file://CVE-2022-27782-1.patch \ file://CVE-2022-27782-2.patch \ file://0001-openssl-fix-CN-check-error-code.patch \ + file://CVE-2022-32205.patch \ + file://CVE-2022-32206.patch \ + file://CVE-2022-32207.patch \ + file://CVE-2022-32208.patch \ + file://CVE-2022-35252.patch \ + file://CVE-2022-32221.patch \ + file://CVE-2022-42916.patch \ + file://CVE-2022-42915.patch \ + file://CVE-2022-43551.patch \ + file://CVE-2022-43552.patch \ + file://CVE-2023-23914_5-1.patch \ + file://CVE-2023-23914_5-2.patch \ + file://CVE-2023-23914_5-3.patch \ + file://CVE-2023-23914_5-4.patch \ + file://CVE-2023-23914_5-5.patch \ + file://CVE-2023-23916.patch \ + file://CVE-2023-27533.patch \ + file://CVE-2023-27534.patch \ + file://CVE-2023-27535-pre1.patch \ + file://CVE-2023-27535_and_CVE-2023-27538.patch \ + file://CVE-2023-27536.patch \ + file://CVE-2023-28319.patch \ + file://CVE-2023-28320.patch \ + file://CVE-2023-28320-fol1.patch \ + file://CVE-2023-28321.patch \ + file://CVE-2023-28322-1.patch \ + file://CVE-2023-28322-2.patch \ + file://CVE-2023-38545.patch \ + file://CVE-2023-38546.patch \ + file://CVE-2023-46218.patch \ + file://CVE-2023-46219-0001.patch \ + file://CVE-2023-46219-0002.patch \ + file://CVE-2023-46219-0003.patch \ + file://CVE-2024-2398.patch \ " SRC_URI[sha256sum] = "0aaa12d7bd04b0966254f2703ce80dd5c38dbbd76af0297d3d690cdce58a583c" # Curl has used many names over the years... CVE_PRODUCT = "haxx:curl haxx:libcurl curl:curl curl:libcurl libcurl:libcurl daniel_stenberg:curl" +# This CVE reports that apple had to upgrade curl because of other already reported CVEs +CVE_CHECK_IGNORE += "CVE-2023-42915" + inherit autotools pkgconfig binconfig multilib_header # Entropy source for random PACKAGECONFIG option @@ -43,14 +80,16 @@ PACKAGECONFIG:class-nativesdk = "ipv6 openssl proxy random threaded-resolver ver PACKAGECONFIG[ares] = "--enable-ares,--disable-ares,c-ares,,,threaded-resolver" PACKAGECONFIG[brotli] = "--with-brotli,--without-brotli,brotli" PACKAGECONFIG[builtinmanual] = "--enable-manual,--disable-manual" +# Don't use this in production +PACKAGECONFIG[debug] = "--enable-debug,--disable-debug" PACKAGECONFIG[dict] = "--enable-dict,--disable-dict," PACKAGECONFIG[gnutls] = "--with-gnutls,--without-gnutls,gnutls" PACKAGECONFIG[gopher] = "--enable-gopher,--disable-gopher," PACKAGECONFIG[imap] = "--enable-imap,--disable-imap," PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," PACKAGECONFIG[krb5] = "--with-gssapi,--without-gssapi,krb5" -PACKAGECONFIG[ldap] = "--enable-ldap,--disable-ldap," -PACKAGECONFIG[ldaps] = "--enable-ldaps,--disable-ldaps," +PACKAGECONFIG[ldap] = "--enable-ldap,--disable-ldap,openldap" +PACKAGECONFIG[ldaps] = "--enable-ldaps,--disable-ldaps,openldap" PACKAGECONFIG[libgsasl] = "--with-libgsasl,--without-libgsasl,libgsasl" PACKAGECONFIG[libidn] = "--with-libidn2,--without-libidn2,libidn2" PACKAGECONFIG[libssh2] = "--with-libssh2,--without-libssh2,libssh2" @@ -79,9 +118,7 @@ EXTRA_OECONF = " \ --enable-crypto-auth \ --with-ca-bundle=${sysconfdir}/ssl/certs/ca-certificates.crt \ --without-libpsl \ - --enable-debug \ --enable-optimize \ - --disable-curldebug \ ${@'--without-ssl' if (bb.utils.filter('PACKAGECONFIG', 'gnutls mbedtls nss openssl', d) == '') else ''} \ " |