diff --git a/SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch b/SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch new file mode 100644 index 0000000..591c1cd --- /dev/null +++ b/SOURCES/0025-curl-7.76.1-CVE-2023-27533.patch @@ -0,0 +1,59 @@ +From c9828d86040737a47da862197b5def7ff6b0e3c4 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 6 Mar 2023 12:07:33 +0100 +Subject: [PATCH] telnet: only accept option arguments in ascii + +To avoid embedded telnet negotiation commands etc. + +Reported-by: Harry Sintonen +Closes #10728 + +Upstream-commit: 538b1e79a6e7b0bb829ab4cecc828d32105d0684 +Signed-off-by: Kamil Dudka +--- + lib/telnet.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/lib/telnet.c b/lib/telnet.c +index 22bc81e..baea885 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -770,6 +770,17 @@ static void printsub(struct Curl_easy *data, + } + } + ++static bool str_is_nonascii(const char *str) ++{ ++ size_t len = strlen(str); ++ while(len--) { ++ if(*str & 0x80) ++ return TRUE; ++ str++; ++ } ++ return FALSE; ++} ++ + static CURLcode check_telnet_options(struct Curl_easy *data) + { + struct curl_slist *head; +@@ -784,6 +795,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data) + /* Add the user name as an environment variable if it + was given on the command line */ + if(conn->bits.user_passwd) { ++ if(str_is_nonascii(data->conn->user)) ++ return CURLE_BAD_FUNCTION_ARGUMENT; + msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); + beg = curl_slist_append(tn->telnet_vars, option_arg); + if(!beg) { +@@ -798,6 +811,8 @@ static CURLcode check_telnet_options(struct Curl_easy *data) + for(head = data->set.telnet_options; head; head = head->next) { + if(sscanf(head->data, "%127[^= ]%*[ =]%255s", + option_keyword, option_arg) == 2) { ++ if(str_is_nonascii(option_arg)) ++ continue; + + /* Terminal type */ + if(strcasecompare(option_keyword, "TTYPE")) { +-- +2.39.2 + diff --git a/SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch b/SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch new file mode 100644 index 0000000..f9cff95 --- /dev/null +++ b/SOURCES/0026-curl-7.76.1-CVE-2023-27534.patch @@ -0,0 +1,1060 @@ +From 5085070dd92fe08f1de2c751fe54f52203ad3160 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sun, 16 Oct 2022 18:09:14 +0200 +Subject: [PATCH 1/4] curl_path: return error if given a NULL homedir + +Closes #9740 + +Upstream-commit: 025bad1182ff87facbddd280dd07a0fc26b99f45 +Signed-off-by: Kamil Dudka +--- + lib/curl_path.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/curl_path.c b/lib/curl_path.c +index 6100d77..35ea5b3 100644 +--- a/lib/curl_path.c ++++ b/lib/curl_path.c +@@ -120,7 +120,8 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) + bool relativePath = false; + static const char WHITESPACE[] = " \t\r\n"; + +- if(!*cp) { ++ DEBUGASSERT(homedir); ++ if(!*cp || !homedir) { + *cpp = NULL; + *path = NULL; + return CURLE_QUOTE_ERROR; +-- +2.39.2 + + +From 69d0f1ba04c9c57d04f8e546e663ef9e9dba4542 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sun, 30 Oct 2022 17:38:16 +0100 +Subject: [PATCH 2/4] style: use space after comment start and before comment + end + +/* like this */ + +/*not this*/ + +checksrc is updated accordingly + +Closes #9828 + +Upstream-commit: 52cc4a85fd7e5265ba8ff0f08adf4858f6773a11 +Signed-off-by: Kamil Dudka +--- + docs/examples/ephiperfifo.c | 4 +- + docs/examples/usercertinmem.c | 4 +- + include/curl/curl.h | 10 +-- + include/curl/typecheck-gcc.h | 2 +- + lib/curl_path.c | 4 - + lib/curl_rtmp.c | 12 +-- + lib/curl_setup.h | 2 +- + lib/dict.c | 2 +- + lib/file.c | 2 +- + lib/ftp.c | 2 +- + lib/gopher.c | 2 +- + lib/http.c | 4 +- + lib/http_chunks.c | 2 +- + lib/rtsp.c | 4 +- + lib/rtsp.h | 2 +- + lib/telnet.c | 2 +- + lib/urldata.h | 4 +- + lib/vauth/digest.c | 4 +- + lib/vauth/krb5_sspi.c | 2 +- + lib/vssh/libssh2.c | 4 +- + lib/vtls/schannel.c | 4 +- + lib/vtls/sectransp.c | 2 - + src/tool_cfgable.h | 5 +- + src/tool_getparam.c | 4 +- + tests/libtest/lib1525.c | 2 +- + tests/libtest/lib1526.c | 2 +- + tests/libtest/lib1527.c | 2 +- + tests/libtest/lib1528.c | 2 +- + tests/libtest/lib1591.c | 2 +- + tests/libtest/lib506.c | 2 +- + tests/libtest/lib557.c | 2 +- + tests/libtest/lib586.c | 2 +- + tests/libtest/stub_gssapi.h | 160 +++++++++++++++++----------------- + tests/server/tftp.h | 2 +- + tests/server/util.c | 2 +- + tests/unit/unit1300.c | 4 +- + 36 files changed, 132 insertions(+), 141 deletions(-) + +diff --git a/docs/examples/ephiperfifo.c b/docs/examples/ephiperfifo.c +index 11761b9..75336a4 100644 +--- a/docs/examples/ephiperfifo.c ++++ b/docs/examples/ephiperfifo.c +@@ -164,7 +164,7 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g) + memset(&its, 0, sizeof(struct itimerspec)); + } + +- timerfd_settime(g->tfd, /*flags=*/0, &its, NULL); ++ timerfd_settime(g->tfd, /* flags= */0, &its, NULL); + return 0; + } + +@@ -195,7 +195,7 @@ static void check_multi_info(GlobalInfo *g) + } + } + +-/* Called by libevent when we get action on a multi socket filedescriptor*/ ++/* Called by libevent when we get action on a multi socket filedescriptor */ + static void event_cb(GlobalInfo *g, int fd, int revents) + { + CURLMcode rc; +diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c +index 35218bd..79d3aef 100644 +--- a/docs/examples/usercertinmem.c ++++ b/docs/examples/usercertinmem.c +@@ -92,7 +92,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm) + "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\ + "-----END CERTIFICATE-----\n"; + +-/*replace the XXX with the actual RSA key*/ ++/* replace the XXX with the actual RSA key */ + const char *mykey = + "-----BEGIN RSA PRIVATE KEY-----\n"\ + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\ +@@ -190,7 +190,7 @@ int main(void) + curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM"); + + /* both VERIFYPEER and VERIFYHOST are set to 0 in this case because there is +- no CA certificate*/ ++ no CA certificate */ + + curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 0L); +diff --git a/include/curl/curl.h b/include/curl/curl.h +index bed8068..680303b 100644 +--- a/include/curl/curl.h ++++ b/include/curl/curl.h +@@ -371,7 +371,7 @@ typedef int (*curl_seek_callback)(void *instream, + #define CURL_READFUNC_PAUSE 0x10000001 + + /* Return code for when the trailing headers' callback has terminated +- without any errors*/ ++ without any errors */ + #define CURL_TRAILERFUNC_OK 0 + /* Return code for when was an error in the trailing header's list and we + want to abort the request */ +@@ -453,7 +453,7 @@ typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + #define CURL_DID_MEMORY_FUNC_TYPEDEFS + #endif + +-/* the kind of data that is passed to information_callback*/ ++/* the kind of data that is passed to information_callback */ + typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ +@@ -689,7 +689,7 @@ typedef enum { + #define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 + #define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +-#endif /*!CURL_NO_OLDIES*/ ++#endif /* !CURL_NO_OLDIES */ + + /* + * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was +@@ -834,7 +834,7 @@ enum curl_khstat { + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ +- CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/ ++ CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ + }; + +@@ -908,7 +908,7 @@ typedef enum { + #define CURLFTPSSL_ALL CURLUSESSL_ALL + #define CURLFTPSSL_LAST CURLUSESSL_LAST + #define curl_ftpssl curl_usessl +-#endif /*!CURL_NO_OLDIES*/ ++#endif /* !CURL_NO_OLDIES */ + + /* parameter for the CURLOPT_FTP_SSL_CCC option */ + typedef enum { +diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h +index 34d0267..9e6fafd 100644 +--- a/include/curl/typecheck-gcc.h ++++ b/include/curl/typecheck-gcc.h +@@ -429,7 +429,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t, + (CURLINFO_OFF_T < (info)) + + +-/* typecheck helpers -- check whether given expression has requested type*/ ++/* typecheck helpers -- check whether given expression has requested type */ + + /* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p +diff --git a/lib/curl_path.c b/lib/curl_path.c +index 35ea5b3..649da7d 100644 +--- a/lib/curl_path.c ++++ b/lib/curl_path.c +@@ -146,15 +146,12 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) + break; + } + if(cp[i] == '\0') { /* End of string */ +- /*error("Unterminated quote");*/ + goto fail; + } + if(cp[i] == '\\') { /* Escaped characters */ + i++; + if(cp[i] != '\'' && cp[i] != '\"' && + cp[i] != '\\') { +- /*error("Bad escaped character '\\%c'", +- cp[i]);*/ + goto fail; + } + } +@@ -162,7 +159,6 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) + } + + if(j == 0) { +- /*error("Empty quotes");*/ + goto fail; + } + *cpp = cp + i + strspn(cp + i, WHITESPACE); +diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c +index 2fa0267..8caba76 100644 +--- a/lib/curl_rtmp.c ++++ b/lib/curl_rtmp.c +@@ -83,7 +83,7 @@ const struct Curl_handler Curl_handler_rtmp = { + PORT_RTMP, /* defport */ + CURLPROTO_RTMP, /* protocol */ + CURLPROTO_RTMP, /* family */ +- PROTOPT_NONE /* flags*/ ++ PROTOPT_NONE /* flags */ + }; + + const struct Curl_handler Curl_handler_rtmpt = { +@@ -106,7 +106,7 @@ const struct Curl_handler Curl_handler_rtmpt = { + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPT, /* protocol */ + CURLPROTO_RTMPT, /* family */ +- PROTOPT_NONE /* flags*/ ++ PROTOPT_NONE /* flags */ + }; + + const struct Curl_handler Curl_handler_rtmpe = { +@@ -129,7 +129,7 @@ const struct Curl_handler Curl_handler_rtmpe = { + PORT_RTMP, /* defport */ + CURLPROTO_RTMPE, /* protocol */ + CURLPROTO_RTMPE, /* family */ +- PROTOPT_NONE /* flags*/ ++ PROTOPT_NONE /* flags */ + }; + + const struct Curl_handler Curl_handler_rtmpte = { +@@ -152,7 +152,7 @@ const struct Curl_handler Curl_handler_rtmpte = { + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPTE, /* protocol */ + CURLPROTO_RTMPTE, /* family */ +- PROTOPT_NONE /* flags*/ ++ PROTOPT_NONE /* flags */ + }; + + const struct Curl_handler Curl_handler_rtmps = { +@@ -175,7 +175,7 @@ const struct Curl_handler Curl_handler_rtmps = { + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPS, /* protocol */ + CURLPROTO_RTMP, /* family */ +- PROTOPT_NONE /* flags*/ ++ PROTOPT_NONE /* flags */ + }; + + const struct Curl_handler Curl_handler_rtmpts = { +@@ -198,7 +198,7 @@ const struct Curl_handler Curl_handler_rtmpts = { + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPTS, /* protocol */ + CURLPROTO_RTMPT, /* family */ +- PROTOPT_NONE /* flags*/ ++ PROTOPT_NONE /* flags */ + }; + + static CURLcode rtmp_setup_connection(struct Curl_easy *data, +diff --git a/lib/curl_setup.h b/lib/curl_setup.h +index cf1c26a..1d81141 100644 +--- a/lib/curl_setup.h ++++ b/lib/curl_setup.h +@@ -680,7 +680,7 @@ int netware_init(void); + # define UNUSED_PARAM __attribute__((__unused__)) + # define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) + #else +-# define UNUSED_PARAM /*NOTHING*/ ++# define UNUSED_PARAM /* NOTHING */ + # define WARN_UNUSED_RESULT + #endif + +diff --git a/lib/dict.c b/lib/dict.c +index 7b27f79..0ccfc0e 100644 +--- a/lib/dict.c ++++ b/lib/dict.c +@@ -321,4 +321,4 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) + + return CURLE_OK; + } +-#endif /*CURL_DISABLE_DICT*/ ++#endif /* CURL_DISABLE_DICT */ +diff --git a/lib/file.c b/lib/file.c +index 10d8f05..8b67c12 100644 +--- a/lib/file.c ++++ b/lib/file.c +@@ -311,7 +311,7 @@ static CURLcode file_upload(struct Curl_easy *data) + + nread = readcount; + +- /*skip bytes before resume point*/ ++ /* skip bytes before resume point */ + if(data->state.resume_from) { + if((curl_off_t)nread <= data->state.resume_from) { + data->state.resume_from -= nread; +diff --git a/lib/ftp.c b/lib/ftp.c +index e920138..6043dea 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1166,7 +1166,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, + port++; + } + +- /* maybe all ports were in use already*/ ++ /* maybe all ports were in use already */ + if(port > port_max) { + failf(data, "bind() failed, we ran out of ports!"); + Curl_closesocket(data, conn, portsock); +diff --git a/lib/gopher.c b/lib/gopher.c +index f61232f..bdd6420 100644 +--- a/lib/gopher.c ++++ b/lib/gopher.c +@@ -234,4 +234,4 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); + return CURLE_OK; + } +-#endif /*CURL_DISABLE_GOPHER*/ ++#endif /* CURL_DISABLE_GOPHER */ +diff --git a/lib/http.c b/lib/http.c +index 28ef8dd..9a908fe 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -2081,7 +2081,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) + { + const char *ptr; + if(!data->state.this_is_a_follow) { +- /* Free to avoid leaking memory on multiple requests*/ ++ /* Free to avoid leaking memory on multiple requests */ + free(data->state.first_host); + + data->state.first_host = strdup(conn->host.name); +@@ -2999,7 +2999,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) + /* continue with HTTP/1.1 when explicitly requested */ + break; + default: +- /* Check if user wants to use HTTP/2 with clear TCP*/ ++ /* Check if user wants to use HTTP/2 with clear TCP */ + #ifdef USE_NGHTTP2 + if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) { + #ifndef CURL_DISABLE_PROXY +diff --git a/lib/http_chunks.c b/lib/http_chunks.c +index beb9695..2c8b6c0 100644 +--- a/lib/http_chunks.c ++++ b/lib/http_chunks.c +@@ -124,7 +124,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, + *wrote = 0; /* nothing's written yet */ + + /* the original data is written to the client, but we go on with the +- chunk read process, to properly calculate the content length*/ ++ chunk read process, to properly calculate the content length */ + if(data->set.http_te_skip && !k->ignorebody) { + result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen); + if(result) { +diff --git a/lib/rtsp.c b/lib/rtsp.c +index cdd49dc..3391a8e 100644 +--- a/lib/rtsp.c ++++ b/lib/rtsp.c +@@ -309,7 +309,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) + break; + case RTSPREQ_RECEIVE: + p_request = ""; +- /* Treat interleaved RTP as body*/ ++ /* Treat interleaved RTP as body */ + data->set.opt_no_body = FALSE; + break; + case RTSPREQ_LAST: +@@ -645,7 +645,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, + rtp_length = RTP_PKT_LENGTH(rtp); + + if(rtp_dataleft < rtp_length + 4) { +- /* Need more - incomplete payload*/ ++ /* Need more - incomplete payload */ + *readmore = TRUE; + break; + } +diff --git a/lib/rtsp.h b/lib/rtsp.h +index 1e9cb7d..2776359 100644 +--- a/lib/rtsp.h ++++ b/lib/rtsp.h +@@ -60,7 +60,7 @@ struct RTSP { + * HTTP functions can safely treat this as an HTTP struct, but RTSP aware + * functions can also index into the later elements. + */ +- struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */ ++ struct HTTP http_wrapper; /* wrap HTTP to do the heavy lifting */ + + long CSeq_sent; /* CSeq of this request */ + long CSeq_recv; /* CSeq received */ +diff --git a/lib/telnet.c b/lib/telnet.c +index 803d4c5..82fde7d 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -569,7 +569,7 @@ void rec_do(struct Curl_easy *data, int option) + sendsuboption(data, option); + } + else if(tn->subnegotiation[option] == CURL_YES) { +- /* send information to achieve this option*/ ++ /* send information to achieve this option */ + tn->us[option] = CURL_YES; + send_negotiation(data, CURL_WILL, option); + sendsuboption(data, option); +diff --git a/lib/urldata.h b/lib/urldata.h +index 52e4583..c9a52ab 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -243,7 +243,7 @@ struct ssl_connect_data { + + struct ssl_primary_config { + long version; /* what version the client wants to use */ +- long version_max; /* max supported version the client wants to use*/ ++ long version_max; /* max supported version the client wants to use */ + char *CApath; /* certificate dir (doesn't work on windows) */ + char *CAfile; /* certificate to verify peer against */ + char *issuercert; /* optional issuer certificate filename */ +@@ -281,7 +281,7 @@ struct ssl_config_data { + char *key_passwd; /* plain text private key password */ + BIT(certinfo); /* gather lots of certificate info */ + BIT(falsestart); +- BIT(enable_beast); /* allow this flaw for interoperability's sake*/ ++ BIT(enable_beast); /* allow this flaw for interoperability's sake */ + BIT(no_revoke); /* disable SSL certificate revocation checks */ + BIT(no_partialchain); /* don't accept partial certificate chains */ + BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation +diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c +index 559852f..3fc4e50 100644 +--- a/lib/vauth/digest.c ++++ b/lib/vauth/digest.c +@@ -139,7 +139,7 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + } + + #if !defined(USE_WINDOWS_SSPI) +-/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/ ++/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string */ + static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ + unsigned char *dest) /* 33 bytes */ + { +@@ -148,7 +148,7 @@ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ + msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); + } + +-/* Convert sha256 chunk to RFC7616 -suitable ascii string*/ ++/* Convert sha256 chunk to RFC7616 -suitable ascii string */ + static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */ + unsigned char *dest) /* 65 bytes */ + { +diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c +index b2d1635..26bb794 100644 +--- a/lib/vauth/krb5_sspi.c ++++ b/lib/vauth/krb5_sspi.c +@@ -530,4 +530,4 @@ void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) + krb5->token_max = 0; + } + +-#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5*/ ++#endif /* USE_WINDOWS_SSPI && USE_KERBEROS5 */ +diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c +index 0a468dd..e1c55b0 100644 +--- a/lib/vssh/libssh2.c ++++ b/lib/vssh/libssh2.c +@@ -571,9 +571,9 @@ static CURLcode ssh_knownhost(struct Curl_easy *data) + /* remove old host+key that doesn't match */ + if(host) + libssh2_knownhost_del(sshc->kh, host); +- /*FALLTHROUGH*/ ++ /* FALLTHROUGH */ + case CURLKHSTAT_FINE: +- /*FALLTHROUGH*/ ++ /* FALLTHROUGH */ + case CURLKHSTAT_FINE_ADD_TO_FILE: + /* proceed */ + if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) { +diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c +index a80eb50..61f4abf 100644 +--- a/lib/vtls/schannel.c ++++ b/lib/vtls/schannel.c +@@ -195,7 +195,7 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data, + return CURLE_OK; + } + +-/*longest is 26, buffer is slightly bigger*/ ++/* longest is 26, buffer is slightly bigger */ + #define LONGEST_ALG_ID 32 + #define CIPHEROPTION(X) \ + if(strcmp(#X, tmp) == 0) \ +@@ -218,7 +218,7 @@ get_alg_id_by_name(char *name) + CIPHEROPTION(CALG_MAC); + CIPHEROPTION(CALG_RSA_SIGN); + CIPHEROPTION(CALG_DSS_SIGN); +-/*ifdefs for the options that are defined conditionally in wincrypt.h*/ ++/* ifdefs for the options that are defined conditionally in wincrypt.h */ + #ifdef CALG_NO_SIGN + CIPHEROPTION(CALG_NO_SIGN); + #endif +diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c +index f2d7835..febf51a 100644 +--- a/lib/vtls/sectransp.c ++++ b/lib/vtls/sectransp.c +@@ -197,7 +197,6 @@ static OSStatus SocketRead(SSLConnectionRef connection, + size_t bytesToGo = *dataLength; + size_t initLen = bytesToGo; + UInt8 *currData = (UInt8 *)data; +- /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + struct ssl_backend_data *backend = connssl->backend; + int sock = backend->ssl_sockfd; +@@ -258,7 +257,6 @@ static OSStatus SocketWrite(SSLConnectionRef connection, + size_t *dataLength) /* IN/OUT */ + { + size_t bytesSent = 0; +- /*int sock = *(int *)connection;*/ + struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; + struct ssl_backend_data *backend = connssl->backend; + int sock = backend->ssl_sockfd; +diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h +index 95c66d0..5046772 100644 +--- a/src/tool_cfgable.h ++++ b/src/tool_cfgable.h +@@ -258,11 +258,8 @@ struct OperationConfig { + bool xattr; /* store metadata in extended attributes */ + long gssapi_delegation; + bool ssl_allow_beast; /* allow this SSL vulnerability */ +- bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy*/ +- ++ bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy */ + bool ssl_no_revoke; /* disable SSL certificate revocation checks */ +- /*bool proxy_ssl_no_revoke; */ +- + bool ssl_revoke_best_effort; /* ignore SSL revocation offline/missing + revocation list errors */ + +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index f1393c3..51232ba 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -1064,7 +1064,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + /* This specifies the noproxy list */ + GetStr(&config->noproxy, nextarg); + break; +- case '7': /* --socks5-gssapi-nec*/ ++ case '7': /* --socks5-gssapi-nec */ + config->socks5_gssapi_nec = toggle; + break; + case '8': /* --proxy1.0 */ +@@ -1230,7 +1230,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ + config->httpversion = CURL_HTTP_VERSION_2_0; + break; + case '3': /* --http2-prior-knowledge */ +- /* HTTP version 2.0 over clean TCP*/ ++ /* HTTP version 2.0 over clean TCP */ + config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE; + break; + case '4': /* --http3 */ +diff --git a/tests/libtest/lib1525.c b/tests/libtest/lib1525.c +index a2a4db2..912372f 100644 +--- a/tests/libtest/lib1525.c ++++ b/tests/libtest/lib1525.c +@@ -48,7 +48,7 @@ int test(char *URL) + { + CURL *curl = NULL; + CURLcode res = CURLE_FAILED_INIT; +- /* http and proxy header list*/ ++ /* http and proxy header list */ + struct curl_slist *hhl = NULL; + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { +diff --git a/tests/libtest/lib1526.c b/tests/libtest/lib1526.c +index 37abc61..b287277 100644 +--- a/tests/libtest/lib1526.c ++++ b/tests/libtest/lib1526.c +@@ -46,7 +46,7 @@ int test(char *URL) + { + CURL *curl = NULL; + CURLcode res = CURLE_FAILED_INIT; +- /* http and proxy header list*/ ++ /* http and proxy header list */ + struct curl_slist *hhl = NULL, *phl = NULL, *tmp = NULL; + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { +diff --git a/tests/libtest/lib1527.c b/tests/libtest/lib1527.c +index 9e0e452..2f7c91b 100644 +--- a/tests/libtest/lib1527.c ++++ b/tests/libtest/lib1527.c +@@ -47,7 +47,7 @@ int test(char *URL) + { + CURL *curl = NULL; + CURLcode res = CURLE_FAILED_INIT; +- /* http header list*/ ++ /* http header list */ + struct curl_slist *hhl = NULL, *tmp = NULL; + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { +diff --git a/tests/libtest/lib1528.c b/tests/libtest/lib1528.c +index 98a332c..52dc0a0 100644 +--- a/tests/libtest/lib1528.c ++++ b/tests/libtest/lib1528.c +@@ -28,7 +28,7 @@ int test(char *URL) + { + CURL *curl = NULL; + CURLcode res = CURLE_FAILED_INIT; +- /* http header list*/ ++ /* http header list */ + struct curl_slist *hhl = NULL; + struct curl_slist *phl = NULL; + +diff --git a/tests/libtest/lib1591.c b/tests/libtest/lib1591.c +index 8349b1d..f7149cf 100644 +--- a/tests/libtest/lib1591.c ++++ b/tests/libtest/lib1591.c +@@ -75,7 +75,7 @@ int test(char *URL) + { + CURL *curl = NULL; + CURLcode res = CURLE_FAILED_INIT; +- /* http and proxy header list*/ ++ /* http and proxy header list */ + struct curl_slist *hhl = NULL; + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { +diff --git a/tests/libtest/lib506.c b/tests/libtest/lib506.c +index 559e731..acea39a 100644 +--- a/tests/libtest/lib506.c ++++ b/tests/libtest/lib506.c +@@ -347,7 +347,7 @@ int test(char *URL) + printf("-----------------\n"); + curl_slist_free_all(cookies); + +- /* try to free share, expect to fail because share is in use*/ ++ /* try to free share, expect to fail because share is in use */ + printf("try SHARE_CLEANUP...\n"); + scode = curl_share_cleanup(share); + if(scode == CURLSHE_OK) { +diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c +index 00fbca3..4105a76 100644 +--- a/tests/libtest/lib557.c ++++ b/tests/libtest/lib557.c +@@ -1494,7 +1494,7 @@ static int test_weird_arguments(void) + "0123456789" /* 10 7 */ + "0123456789" /* 10 8 */ + "0123456789" /* 10 9 */ +- "0123456789" /* 10 10*/ ++ "0123456789" /* 10 10 */ + "0123456789" /* 10 11 */ + "01234567" /* 8 */ + ); +diff --git a/tests/libtest/lib586.c b/tests/libtest/lib586.c +index da63e7c..8d7822d 100644 +--- a/tests/libtest/lib586.c ++++ b/tests/libtest/lib586.c +@@ -215,7 +215,7 @@ int test(char *URL) + printf("PERFORM\n"); + curl_easy_perform(curl); + +- /* try to free share, expect to fail because share is in use*/ ++ /* try to free share, expect to fail because share is in use */ + printf("try SHARE_CLEANUP...\n"); + scode = curl_share_cleanup(share); + if(scode == CURLSHE_OK) { +diff --git a/tests/libtest/stub_gssapi.h b/tests/libtest/stub_gssapi.h +index 5a89102..735630c 100644 +--- a/tests/libtest/stub_gssapi.h ++++ b/tests/libtest/stub_gssapi.h +@@ -98,85 +98,85 @@ typedef struct gss_channel_bindings_struct { + gss_buffer_desc application_data; + } *gss_channel_bindings_t; + +-OM_uint32 gss_release_buffer(OM_uint32 * /*minor_status*/, +- gss_buffer_t /*buffer*/); +- +-OM_uint32 gss_init_sec_context(OM_uint32 * /*minor_status*/, +- gss_const_cred_id_t /*initiator_cred_handle*/, +- gss_ctx_id_t * /*context_handle*/, +- gss_const_name_t /*target_name*/, +- const gss_OID /*mech_type*/, +- OM_uint32 /*req_flags*/, +- OM_uint32 /*time_req*/, +- const gss_channel_bindings_t /*input_chan_bindings*/, +- const gss_buffer_t /*input_token*/, +- gss_OID * /*actual_mech_type*/, +- gss_buffer_t /*output_token*/, +- OM_uint32 * /*ret_flags*/, +- OM_uint32 * /*time_rec*/); +- +-OM_uint32 gss_delete_sec_context(OM_uint32 * /*minor_status*/, +- gss_ctx_id_t * /*context_handle*/, +- gss_buffer_t /*output_token*/); +- +-OM_uint32 gss_inquire_context(OM_uint32 * /*minor_status*/, +- gss_const_ctx_id_t /*context_handle*/, +- gss_name_t * /*src_name*/, +- gss_name_t * /*targ_name*/, +- OM_uint32 * /*lifetime_rec*/, +- gss_OID * /*mech_type*/, +- OM_uint32 * /*ctx_flags*/, +- int * /*locally_initiated*/, +- int * /*open_context*/); +- +-OM_uint32 gss_wrap(OM_uint32 * /*minor_status*/, +- gss_const_ctx_id_t /*context_handle*/, +- int /*conf_req_flag*/, +- gss_qop_t /*qop_req*/, +- const gss_buffer_t /*input_message_buffer*/, +- int * /*conf_state*/, +- gss_buffer_t /*output_message_buffer*/); +- +-OM_uint32 gss_unwrap(OM_uint32 * /*minor_status*/, +- gss_const_ctx_id_t /*context_handle*/, +- const gss_buffer_t /*input_message_buffer*/, +- gss_buffer_t /*output_message_buffer*/, +- int * /*conf_state*/, +- gss_qop_t * /*qop_state*/); +- +-OM_uint32 gss_seal(OM_uint32 * /*minor_status*/, +- gss_ctx_id_t /*context_handle*/, +- int /*conf_req_flag*/, +- int /*qop_req*/, +- gss_buffer_t /*input_message_buffer*/, +- int * /*conf_state*/, +- gss_buffer_t /*output_message_buffer*/); +- +-OM_uint32 gss_unseal(OM_uint32 * /*minor_status*/, +- gss_ctx_id_t /*context_handle*/, +- gss_buffer_t /*input_message_buffer*/, +- gss_buffer_t /*output_message_buffer*/, +- int * /*conf_state*/, +- int * /*qop_state*/); +- +-OM_uint32 gss_import_name(OM_uint32 * /*minor_status*/, +- const gss_buffer_t /*input_name_buffer*/, +- const gss_OID /*input_name_type*/, +- gss_name_t * /*output_name*/); +- +-OM_uint32 gss_release_name(OM_uint32 * /*minor_status*/, +- gss_name_t * /*input_name*/); +- +-OM_uint32 gss_display_name(OM_uint32 * /*minor_status*/, +- gss_const_name_t /*input_name*/, +- gss_buffer_t /*output_name_buffer*/, +- gss_OID * /*output_name_type*/); +- +-OM_uint32 gss_display_status(OM_uint32 * /*minor_status*/, +- OM_uint32 /*status_value*/, +- int /*status_type*/, +- const gss_OID /*mech_type*/, +- OM_uint32 * /*message_context*/, +- gss_buffer_t /*status_string*/); ++OM_uint32 gss_release_buffer(OM_uint32 * /* minor_status */, ++ gss_buffer_t /* buffer */); ++ ++OM_uint32 gss_init_sec_context(OM_uint32 * /* minor_status */, ++ gss_const_cred_id_t /* initiator_cred_handle */, ++ gss_ctx_id_t * /* context_handle */, ++ gss_const_name_t /* target_name */, ++ const gss_OID /* mech_type */, ++ OM_uint32 /* req_flags */, ++ OM_uint32 /* time_req */, ++ const gss_channel_bindings_t /* input_chan_bindings */, ++ const gss_buffer_t /* input_token */, ++ gss_OID * /* actual_mech_type */, ++ gss_buffer_t /* output_token */, ++ OM_uint32 * /* ret_flags */, ++ OM_uint32 * /* time_rec */); ++ ++OM_uint32 gss_delete_sec_context(OM_uint32 * /* minor_status */, ++ gss_ctx_id_t * /* context_handle */, ++ gss_buffer_t /* output_token */); ++ ++OM_uint32 gss_inquire_context(OM_uint32 * /* minor_status */, ++ gss_const_ctx_id_t /* context_handle */, ++ gss_name_t * /* src_name */, ++ gss_name_t * /* targ_name */, ++ OM_uint32 * /* lifetime_rec */, ++ gss_OID * /* mech_type */, ++ OM_uint32 * /* ctx_flags */, ++ int * /* locally_initiated */, ++ int * /* open_context */); ++ ++OM_uint32 gss_wrap(OM_uint32 * /* minor_status */, ++ gss_const_ctx_id_t /* context_handle */, ++ int /* conf_req_flag */, ++ gss_qop_t /* qop_req */, ++ const gss_buffer_t /* input_message_buffer */, ++ int * /* conf_state */, ++ gss_buffer_t /* output_message_buffer */); ++ ++OM_uint32 gss_unwrap(OM_uint32 * /* minor_status */, ++ gss_const_ctx_id_t /* context_handle */, ++ const gss_buffer_t /* input_message_buffer */, ++ gss_buffer_t /* output_message_buffer */, ++ int * /* conf_state */, ++ gss_qop_t * /* qop_state */); ++ ++OM_uint32 gss_seal(OM_uint32 * /* minor_status */, ++ gss_ctx_id_t /* context_handle n */, ++ int /* conf_req_flag */, ++ int /* qop_req */, ++ gss_buffer_t /* input_message_buffer */, ++ int * /* conf_state */, ++ gss_buffer_t /* output_message_buffer */); ++ ++OM_uint32 gss_unseal(OM_uint32 * /* minor_status */, ++ gss_ctx_id_t /* context_handle */, ++ gss_buffer_t /* input_message_buffer */, ++ gss_buffer_t /* output_message_buffer */, ++ int * /* conf_state */, ++ int * /* qop_state */); ++ ++OM_uint32 gss_import_name(OM_uint32 * /* minor_status */, ++ const gss_buffer_t /* input_name_buffer */, ++ const gss_OID /* input_name_type */, ++ gss_name_t * /* output_name */); ++ ++OM_uint32 gss_release_name(OM_uint32 * /* minor_status */, ++ gss_name_t * /* input_name */); ++ ++OM_uint32 gss_display_name(OM_uint32 * /* minor_status */, ++ gss_const_name_t /* input_name */, ++ gss_buffer_t /* output_name_buffer */, ++ gss_OID * /* output_name_type */); ++ ++OM_uint32 gss_display_status(OM_uint32 * /* minor_status */, ++ OM_uint32 /* status_value */, ++ int /* status_type */, ++ const gss_OID /* mech_type */, ++ OM_uint32 * /* message_context */, ++ gss_buffer_t /* status_string */); + + #endif /* HEADER_CURL_GSSAPI_STUBS_H */ +diff --git a/tests/server/tftp.h b/tests/server/tftp.h +index 5699672..ab59575 100644 +--- a/tests/server/tftp.h ++++ b/tests/server/tftp.h +@@ -32,7 +32,7 @@ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7))) + # define PACKED_STRUCT __attribute__((__packed__)) + #else +-# define PACKED_STRUCT /*NOTHING*/ ++# define PACKED_STRUCT /* NOTHING */ + #endif + + /* Using a packed struct as binary in a program is begging for problems, but +diff --git a/tests/server/util.c b/tests/server/util.c +index c4f16e4..a0dec98 100644 +--- a/tests/server/util.c ++++ b/tests/server/util.c +@@ -65,7 +65,7 @@ + ((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 6)) + const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }}; + #endif /* w32api < 3.6 */ +-#endif /* ENABLE_IPV6 && __MINGW32__*/ ++#endif /* ENABLE_IPV6 && __MINGW32__ */ + + static struct timeval tvnow(void); + +diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c +index aba068a..936c77e 100644 +--- a/tests/unit/unit1300.c ++++ b/tests/unit/unit1300.c +@@ -91,10 +91,10 @@ UNITTEST_START + + fail_unless(Curl_llist_count(&llist) == 1, + "List size should be 1 after adding a new element"); +- /*test that the list head data holds my unusedData */ ++ /* test that the list head data holds my unusedData */ + fail_unless(llist.head->ptr == &unusedData_case1, + "head ptr should be first entry"); +- /*same goes for the list tail */ ++ /* same goes for the list tail */ + fail_unless(llist.tail == llist.head, + "tail and head should be the same"); + +-- +2.39.2 + + +From ab44f4893b87cb3ef567be525a393bc174b031e7 Mon Sep 17 00:00:00 2001 +From: Eric Vigeant +Date: Wed, 2 Nov 2022 11:47:09 -0400 +Subject: [PATCH 3/4] cur_path: do not add '/' if homedir ends with one + +When using SFTP and a path relative to the user home, do not add a +trailing '/' to the user home dir if it already ends with one. + +Closes #9844 + +Upstream-commit: 6c51adeb71da076c5c40a45e339e06bb4394a86b +Signed-off-by: Kamil Dudka +--- + lib/curl_path.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/lib/curl_path.c b/lib/curl_path.c +index 649da7d..5be6637 100644 +--- a/lib/curl_path.c ++++ b/lib/curl_path.c +@@ -69,10 +69,14 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, + /* It is referenced to the home directory, so strip the + leading '/' */ + memcpy(real_path, homedir, homelen); +- real_path[homelen] = '/'; +- real_path[homelen + 1] = '\0'; ++ /* Only add a trailing '/' if homedir does not end with one */ ++ if(homelen == 0 || real_path[homelen - 1] != '/') { ++ real_path[homelen] = '/'; ++ homelen++; ++ real_path[homelen] = '\0'; ++ } + if(working_path_len > 3) { +- memcpy(real_path + homelen + 1, working_path + 3, ++ memcpy(real_path + homelen, working_path + 3, + 1 + working_path_len -3); + } + } +-- +2.39.2 + + +From a0b0e531267239c2beb4aeca15a0581a411d9c7b Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 9 Mar 2023 16:22:11 +0100 +Subject: [PATCH 4/4] curl_path: create the new path with dynbuf + +Closes #10729 + +Upstream-commit: 4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6 +Signed-off-by: Kamil Dudka +--- + lib/curl_path.c | 75 +++++++++++++++++++++++-------------------------- + 1 file changed, 35 insertions(+), 40 deletions(-) + +diff --git a/lib/curl_path.c b/lib/curl_path.c +index 5be6637..b654aff 100644 +--- a/lib/curl_path.c ++++ b/lib/curl_path.c +@@ -30,70 +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, 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 == NULL) { ++ 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 == NULL) { +- free(working_path); +- return CURLE_OUT_OF_MEMORY; +- } +- /* It is referenced to the home directory, so strip the +- leading '/' */ +- memcpy(real_path, homedir, homelen); +- /* Only add a trailing '/' if homedir does not end with one */ +- if(homelen == 0 || real_path[homelen - 1] != '/') { +- real_path[homelen] = '/'; +- homelen++; +- real_path[homelen] = '\0'; +- } +- if(working_path_len > 3) { +- memcpy(real_path + homelen, working_path + 3, +- 1 + working_path_len -3); +- } ++ else if((data->conn->handler->protocol & CURLPROTO_SFTP) && ++ (working_path_len > 2) && !memcmp(working_path, "/~/", 3)) { ++ size_t len; ++ const char *p; ++ int copyfrom = 3; ++ if(Curl_dyn_add(&npath, homedir)) { ++ free(working_path); ++ return CURLE_OUT_OF_MEMORY; + } +- else { +- real_path = malloc(working_path_len + 1); +- if(real_path == NULL) { +- free(working_path); +- return CURLE_OUT_OF_MEMORY; +- } +- memcpy(real_path, working_path, 1 + working_path_len); ++ /* Copy a separating '/' if homedir does not end with one */ ++ len = Curl_dyn_len(&npath); ++ p = Curl_dyn_ptr(&npath); ++ if(len && (p[len-1] != '/')) ++ copyfrom = 2; ++ ++ if(Curl_dyn_addn(&npath, ++ &working_path[copyfrom], working_path_len - copyfrom)) { ++ free(working_path); ++ return CURLE_OUT_OF_MEMORY; + } + } + +- free(working_path); ++ if(Curl_dyn_len(&npath)) { ++ free(working_path); + +- /* store the pointer for the caller to receive */ +- *path = real_path; ++ /* store the pointer for the caller to receive */ ++ *path = Curl_dyn_ptr(&npath); ++ } ++ else ++ *path = working_path; + + return CURLE_OK; + } +-- +2.39.2 + diff --git a/SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch b/SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch new file mode 100644 index 0000000..846a90c --- /dev/null +++ b/SOURCES/0027-curl-7.76.1-CVE-2023-27535.patch @@ -0,0 +1,230 @@ +From e8705acd69383c13191c9dd4867d5118e58c54ba Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 6 Oct 2022 00:49:10 +0200 +Subject: [PATCH 1/2] strcase: add 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-commit: ed5095ed94281989e103c72e032200b83be37878 +Signed-off-by: Kamil Dudka +--- + lib/strcase.c | 22 ++++++++++++++++++++++ + lib/strcase.h | 1 + + 2 files changed, 23 insertions(+) + +diff --git a/lib/strcase.c b/lib/strcase.c +index f932485..c73907d 100644 +--- a/lib/strcase.c ++++ b/lib/strcase.c +@@ -261,6 +261,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 d245929..11a67a1 100644 +--- a/lib/strcase.h ++++ b/lib/strcase.h +@@ -49,5 +49,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 */ +-- +2.39.2 + + +From 9cfaea212ff347937a38f6b5d6b885ed8ba1b931 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 9 Mar 2023 17:47:06 +0100 +Subject: [PATCH 2/2] ftp: add more conditions for connection reuse + +Reported-by: Harry Sintonen +Closes #10730 + +Upstream-commit: 8f4608468b890dce2dad9f91d5607ee7e9c1aba1 +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 28 ++++++++++++++++++++++++++-- + lib/ftp.h | 5 +++++ + lib/setopt.c | 2 +- + lib/url.c | 12 ++++++++++++ + lib/urldata.h | 4 ++-- + 5 files changed, 46 insertions(+), 5 deletions(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index 9442832..df15bc0 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -4086,6 +4086,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); +@@ -4346,11 +4348,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(NULL == ftp) + return CURLE_OUT_OF_MEMORY; + ++ /* clone connection related data that is FTP specific */ ++ if(data->set.str[STRING_FTP_ACCOUNT]) { ++ ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]); ++ if(!ftpc->account) { ++ free(ftp); ++ return CURLE_OUT_OF_MEMORY; ++ } ++ } ++ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) { ++ ftpc->alternative_to_user = ++ strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); ++ if(!ftpc->alternative_to_user) { ++ Curl_safefree(ftpc->account); ++ free(ftp); ++ return CURLE_OUT_OF_MEMORY; ++ } ++ } ++ data->req.p.ftp = ftp; ++ + ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ + + /* FTP URLs support an extension like ";type=" that +@@ -4385,7 +4407,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 7f6f432..3f33e27 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 3339a67..6fc111d 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2264,7 +2264,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 61ba832..4e21838 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1329,6 +1329,18 @@ ConnectionExists(struct Curl_easy *data, + if(!ssh_config_matches(needle, check)) + continue; + } ++#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 9d9ca92..4e2f5b9 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1749,8 +1749,6 @@ struct UserDefined { + void *ssh_keyfunc_userp; /* custom pointer to callback */ + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ +- 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 */ +@@ -1793,6 +1791,8 @@ struct UserDefined { + CURLU *uh; /* URL handle for the current parsed URL */ + void *trailer_data; /* pointer to pass to trailer data callback */ + curl_trailer_callback trailer_callback; /* trailing data callback */ ++ unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or ++ IMAP or POP3 or others! (type: curl_usessl)*/ + BIT(is_fread_set); /* has read callback been set to non-NULL? */ + BIT(is_fwrite_set); /* has write callback been set to non-NULL? */ + BIT(free_referer); /* set TRUE if 'referer' points to a string we +-- +2.39.2 + diff --git a/SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch b/SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch new file mode 100644 index 0000000..7888e19 --- /dev/null +++ b/SOURCES/0028-curl-7.76.1-CVE-2023-27536.patch @@ -0,0 +1,54 @@ +From 9d6dd7bc1dea42ae8e710aeae714e2a2c290de61 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 10 Mar 2023 09:22:43 +0100 +Subject: [PATCH] url: only reuse connections with same GSS delegation + +Reported-by: Harry Sintonen +Closes #10731 + +Upstream-commit: cb49e67303dbafbab1cebf4086e3ec15b7d56ee5 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 6 ++++++ + lib/urldata.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/lib/url.c b/lib/url.c +index 3b11b7e..cbbc7f3 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1325,6 +1325,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(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; +@@ -1785,6 +1790,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) + conn->fclosesocket = data->set.fclosesocket; + conn->closesocket_client = data->set.closesocket_client; + conn->lastused = Curl_now(); /* used now */ ++ conn->gssapi_delegation = data->set.gssapi_delegation; + + return conn; + error: +diff --git a/lib/urldata.h b/lib/urldata.h +index ce90304..9e16f26 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -995,6 +995,7 @@ struct connectdata { + char *sasl_authzid; /* authorisation identity string, allocated */ + char *oauth_bearer; /* OAUTH2 bearer, allocated */ + unsigned char httpversion; /* the HTTP version*10 reported by the server */ ++ unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */ + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ + struct curltime lastused; /* when returned to the connection cache */ +-- +2.39.2 + diff --git a/SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch b/SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch new file mode 100644 index 0000000..030b6bb --- /dev/null +++ b/SOURCES/0029-curl-7.76.1-CVE-2023-27538.patch @@ -0,0 +1,30 @@ +From 133e25afe4b8961b9c12334ee0bd3374db9a1fd4 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 10 Mar 2023 08:22:51 +0100 +Subject: [PATCH] url: fix the SSH connection reuse check + +Reported-by: Harry Sintonen +Closes #10735 + +Upstream-commit: af369db4d3833272b8ed443f7fcc2e757a0872eb +Signed-off-by: Kamil Dudka +--- + lib/url.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/url.c b/lib/url.c +index 0c31486..3b11b7e 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1330,7 +1330,7 @@ ConnectionExists(struct Curl_easy *data, + if(needle->gssapi_delegation != check->gssapi_delegation) + continue; + +- if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { ++ if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) { + if(!ssh_config_matches(needle, check)) + continue; + } +-- +2.39.2 + diff --git a/SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch b/SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch new file mode 100644 index 0000000..0aadf52 --- /dev/null +++ b/SOURCES/0030-curl-7.76.1-CVE-2023-28322.patch @@ -0,0 +1,420 @@ +From 47f0d37bfc008c088416f3dcca802c9e087d9bf1 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 25 Apr 2023 08:28:01 +0200 +Subject: [PATCH] lib: unify the upload/method handling + +By making sure we set state.upload based on the set.method value and not +independently as set.upload, we reduce confusion and mixup risks, both +internally and externally. +--- + 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 +@@ -1381,7 +1381,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 +@@ -3368,7 +3368,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) +@@ -4217,7 +4217,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data) + ftpc->file = NULL; /* instead of point to a zero byte, + we make it a NULL pointer */ + +- if(data->set.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) { ++ if(data->state.upload && !ftpc->file && (ftp->transfer == PPTRANSFER_BODY)) { + /* We need a file name when uploading. Return error! */ + failf(data, "Uploading to a URL without a file name!"); + free(rawPath); +diff --git a/lib/http.c b/lib/http.c +index 80e43f6f361e8..bffdd3468536d 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -2112,7 +2112,7 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, + 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 */ +@@ -628,7 +628,6 @@ 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: +@@ -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); + } +@@ -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); + } + + /* +@@ -1801,7 +1801,6 @@ CURLcode Curl_follow(struct Curl_easy *data, + data->state.httpreq != HTTPREQ_POST_MIME) || + !(data->set.keep_post & CURL_REDIR_POST_303))) { + data->state.httpreq = HTTPREQ_GET; +- data->set.upload = false; + infof(data, "Switch to %s\n", + 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 +@@ -1494,6 +1494,7 @@ struct UrlState { + 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/SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch b/SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch new file mode 100644 index 0000000..b306e91 --- /dev/null +++ b/SOURCES/0031-curl-7.76.1-CVE-2023-28321.patch @@ -0,0 +1,304 @@ +From 199f2d440d8659b42670c1b796220792b01a97bf Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 24 Apr 2023 21:07:02 +0200 +Subject: [PATCH] hostcheck: fix host name wildcard checking + +The leftmost "label" of the host name can now only match against single +'*'. Like the browsers have worked for a long time. + +- extended unit test 1397 for this +- move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc + +Reported-by: Hiroki Kurosawa +Closes #11018 +--- + lib/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/hostcheck.c b/lib/hostcheck.c +index e827dc58f378c..d061c6356f97f 100644 +--- a/lib/hostcheck.c ++++ b/lib/hostcheck.c +@@ -43,6 +43,17 @@ + /* The last #include file should be: */ + #include "memdebug.h" + ++/* check the two input strings with given length, but do not ++ assume they end in nul-bytes */ ++static int pmatch(const char *hostname, size_t hostlen, ++ const char *pattern, size_t patternlen) ++{ ++ if(hostlen != patternlen) ++ return CURL_HOST_NOMATCH; ++ return strncasecompare(hostname, pattern, hostlen) ? ++ CURL_HOST_MATCH : CURL_HOST_NOMATCH; ++} ++ + /* + * Match a hostname against a wildcard pattern. + * E.g. +@@ -65,26 +76,27 @@ + + static int hostmatch(char *hostname, char *pattern) + { +- const char *pattern_label_end, *pattern_wildcard, *hostname_label_end; +- int wildcard_enabled; +- size_t prefixlen, suffixlen; ++ size_t hostlen, patternlen; ++ const char *pattern_label_end; + struct in_addr ignored; + #ifdef ENABLE_IPV6 + struct sockaddr_in6 si6; + #endif + ++ DEBUGASSERT(pattern); ++ DEBUGASSERT(hostname); ++ ++ hostlen = strlen(hostname); ++ patternlen = strlen(pattern); ++ + /* normalize pattern and hostname by stripping off trailing dots */ +- size_t len = strlen(hostname); +- if(hostname[len-1]=='.') +- hostname[len-1] = 0; +- len = strlen(pattern); +- if(pattern[len-1]=='.') +- pattern[len-1] = 0; +- +- pattern_wildcard = strchr(pattern, '*'); +- if(pattern_wildcard == NULL) +- return strcasecompare(pattern, hostname) ? +- CURL_HOST_MATCH : CURL_HOST_NOMATCH; ++ if(hostname[hostlen-1]=='.') ++ hostname[hostlen-1] = 0; ++ if(pattern[patternlen-1]=='.') ++ pattern[patternlen-1] = 0; ++ ++ if(strncmp(pattern, "*.", 2)) ++ return pmatch(hostname, hostlen, pattern, patternlen); + + /* detect IP address as hostname and fail the match if so */ + if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0) +@@ -96,34 +108,20 @@ static int hostmatch(char *hostname, char *pattern) + + /* We require at least 2 dots in pattern to avoid too wide wildcard + match. */ +- wildcard_enabled = 1; + pattern_label_end = strchr(pattern, '.'); +- if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL || +- pattern_wildcard > pattern_label_end || +- strncasecompare(pattern, "xn--", 4)) { +- wildcard_enabled = 0; ++ if(pattern_label_end == NULL || ++ (strrchr(pattern, '.') == pattern_label_end)) ++ return pmatch(pattern, patternlen, hostname, hostlen); ++ ++ const char *hostname_label_end = strchr(hostname, '.'); ++ if(hostname_label_end != NULL) { ++ 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); + } +- if(!wildcard_enabled) +- return strcasecompare(pattern, hostname) ? +- CURL_HOST_MATCH : CURL_HOST_NOMATCH; +- +- hostname_label_end = strchr(hostname, '.'); +- if(hostname_label_end == NULL || +- !strcasecompare(pattern_label_end, hostname_label_end)) +- return CURL_HOST_NOMATCH; + +- /* 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 CURL_HOST_NOMATCH; +- +- prefixlen = pattern_wildcard - pattern; +- suffixlen = pattern_label_end - (pattern_wildcard + 1); +- return strncasecompare(pattern, hostname, prefixlen) && +- strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen, +- suffixlen) ? +- CURL_HOST_MATCH : CURL_HOST_NOMATCH; ++ return CURL_HOST_NOMATCH; + } + + int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) +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 @@ + + + unittest +-ssl +-wildcard ++Curl_cert_hostcheck + + + +@@ -15,9 +14,9 @@ none + + unittest + +- +-Check wildcard certificate matching function Curl_cert_hostcheck +- ++ ++Curl_cert_hostcheck unit tests ++ + + + +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 +@@ -21,8 +21,6 @@ + ***************************************************************************/ + #include "curlcheck.h" + +-#include "hostcheck.h" /* from the lib dir */ +- + static CURLcode unit_setup(void) + { + return CURLE_OK; +@@ -30,50 +28,93 @@ 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 "hostcheck.h" ++struct testcase { ++ const char *host; ++ const char *pattern; ++ bool match; ++}; + +-fail_unless(Curl_cert_hostcheck("www.example.com", "www.example.com"), +- "good 1"); +-fail_unless(Curl_cert_hostcheck("*.example.com", "www.example.com"), +- "good 2"); +-fail_unless(Curl_cert_hostcheck("xxx*.example.com", "xxxwww.example.com"), +- "good 3"); +-fail_unless(Curl_cert_hostcheck("f*.example.com", "foo.example.com"), +- "good 4"); +-fail_unless(Curl_cert_hostcheck("192.168.0.0", "192.168.0.0"), +- "good 5"); +- +-fail_if(Curl_cert_hostcheck("xxx.example.com", "www.example.com"), "bad 1"); +-fail_if(Curl_cert_hostcheck("*", "www.example.com"), "bad 2"); +-fail_if(Curl_cert_hostcheck("*.*.com", "www.example.com"), "bad 3"); +-fail_if(Curl_cert_hostcheck("*.example.com", "baa.foo.example.com"), "bad 4"); +-fail_if(Curl_cert_hostcheck("f*.example.com", "baa.example.com"), "bad 5"); +-fail_if(Curl_cert_hostcheck("*.com", "example.com"), "bad 6"); +-fail_if(Curl_cert_hostcheck("*fail.com", "example.com"), "bad 7"); +-fail_if(Curl_cert_hostcheck("*.example.", "www.example."), "bad 8"); +-fail_if(Curl_cert_hostcheck("*.example.", "www.example"), "bad 9"); +-fail_if(Curl_cert_hostcheck("", "www"), "bad 10"); +-fail_if(Curl_cert_hostcheck("*", "www"), "bad 11"); +-fail_if(Curl_cert_hostcheck("*.168.0.0", "192.168.0.0"), "bad 12"); +-fail_if(Curl_cert_hostcheck("www.example.com", "192.168.0.0"), "bad 13"); +- +-#ifdef ENABLE_IPV6 +-fail_if(Curl_cert_hostcheck("*::3285:a9ff:fe46:b619", +- "fe80::3285:a9ff:fe46:b619"), "bad 14"); +-fail_unless(Curl_cert_hostcheck("fe80::3285:a9ff:fe46:b619", +- "fe80::3285:a9ff:fe46:b619"), "good 6"); +-#endif ++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} ++}; + +-#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++; ++ } ++ } ++} ++UNITTEST_STOP ++#else + +- /* you end the test code like this: */ ++UNITTEST_START + + UNITTEST_STOP ++#endif diff --git a/SPECS/curl.spec b/SPECS/curl.spec index 11b7128..9ec331f 100644 --- a/SPECS/curl.spec +++ b/SPECS/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.76.1 -Release: 23%{?dist} +Release: 26%{?dist} License: MIT Source: https://curl.se/download/%{name}-%{version}.tar.xz @@ -74,6 +74,27 @@ Patch23: 0023-curl-7.76.1-CVE-2022-43552.patch # fix HTTP multi-header compression denial of service (CVE-2023-23916) Patch24: 0024-curl-7.76.1-CVE-2023-23916.patch +# fix TELNET option IAC injection (CVE-2023-27533) +Patch25: 0025-curl-7.76.1-CVE-2023-27533.patch + +# fix SFTP path ~ resolving discrepancy (CVE-2023-27534) +Patch26: 0026-curl-7.76.1-CVE-2023-27534.patch + +# fix FTP too eager connection reuse (CVE-2023-27535) +Patch27: 0027-curl-7.76.1-CVE-2023-27535.patch + +# fix GSS delegation too eager connection re-use (CVE-2023-27536) +Patch28: 0028-curl-7.76.1-CVE-2023-27536.patch + +# fix SSH connection too eager reuse still (CVE-2023-27538) +Patch29: 0029-curl-7.76.1-CVE-2023-27538.patch + +# unify the upload/method handling (CVE-2023-28322) +Patch30: 0030-curl-7.76.1-CVE-2023-28322.patch + +# fix host name wildcard checking +Patch31: 0031-curl-7.76.1-CVE-2023-28321.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -272,6 +293,13 @@ be installed. %patch22 -p1 %patch23 -p1 %patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 # Fedora patches %patch101 -p1 @@ -497,9 +525,23 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog -* Fri Apr 14 2023 MSVSphere Packaging Team - 7.76.1-23 +* Mon Jun 12 2023 Jacek Migacz - 7.76.1-26 +- unify the upload/method handling (CVE-2023-28322) +- fix host name wildcard checking (CVE-2023-28321) + +* Fri Apr 14 2023 MSVSphere Packaging Team - 7.76.1-25 - Rebuilt for MSVSphere 9.2 beta +* Wed Apr 12 2023 Kamil Dudka - 7.76.1-25 +- adapt the fix of CVE-2023-27535 for RHEL 9 curl + +* Fri Mar 24 2023 Kamil Dudka - 7.76.1-24 +- fix SSH connection too eager reuse still (CVE-2023-27538) +- fix GSS delegation too eager connection re-use (CVE-2023-27536) +- fix FTP too eager connection reuse (CVE-2023-27535) +- fix SFTP path ~ resolving discrepancy (CVE-2023-27534) +- fix TELNET option IAC injection (CVE-2023-27533) + * Wed Feb 15 2023 Kamil Dudka - 7.76.1-23 - fix HTTP multi-header compression denial of service (CVE-2023-23916)