diff --git a/backport-001-CVE-2022-27774.patch b/backport-001-CVE-2022-27774.patch new file mode 100644 index 0000000..7c859de --- /dev/null +++ b/backport-001-CVE-2022-27774.patch @@ -0,0 +1,77 @@ +From 620ea21410030a9977396b4661806bc187231b79 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH] transfer: redirects to other protocols or ports clear auth + +... unless explicitly permitted. + +Bug: https://curl.se/docs/CVE-2022-27774.html +Reported-by: Harry Sintonen +Closes #8748 +--- + lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/lib/transfer.c b/lib/transfer.c +index 53ef0b03b8e0..315da876c4a8 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1611,10 +1611,57 @@ CURLcode Curl_follow(struct Curl_easy *data, + return CURLE_OUT_OF_MEMORY; + } + else { +- + uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); + if(uc) + return Curl_uc_to_curlcode(uc); ++ ++ /* Clear auth if this redirects to a different port number or protocol, ++ unless permitted */ ++ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { ++ char *portnum; ++ int port; ++ bool clear = FALSE; ++ ++ if(data->set.use_port && data->state.allow_port) ++ /* a custom port is used */ ++ port = (int)data->set.use_port; ++ else { ++ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, ++ CURLU_DEFAULT_PORT); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ port = atoi(portnum); ++ free(portnum); ++ } ++ if(port != data->info.conn_remote_port) { ++ infof(data, "Clear auth, redirects to port from %u to %u", ++ data->info.conn_remote_port, port); ++ clear = TRUE; ++ } ++ else { ++ char *scheme; ++ const struct Curl_handler *p; ++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ ++ p = Curl_builtin_scheme(scheme); ++ if(p && (p->protocol != data->info.conn_protocol)) { ++ infof(data, "Clear auth, redirects scheme from %s to %s", ++ data->info.conn_scheme, scheme); ++ clear = TRUE; ++ } ++ free(scheme); ++ } ++ if(clear) { ++ Curl_safefree(data->state.aptr.user); ++ Curl_safefree(data->state.aptr.passwd); ++ } ++ } + } + + if(type == FOLLOW_FAKE) { diff --git a/backport-002-CVE-2022-27774.patch b/backport-002-CVE-2022-27774.patch new file mode 100644 index 0000000..4021d7c --- /dev/null +++ b/backport-002-CVE-2022-27774.patch @@ -0,0 +1,80 @@ +From 139a54ed0a172adaaf1a78d6f4fff50b2c3f9e08 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 17:59:15 +0200 +Subject: [PATCH] openssl: don't leak the SRP credentials in redirects either + +Follow-up to 620ea21410030 + +Reported-by: Harry Sintonen +Closes #8751 +--- + lib/http.c | 10 +++++----- + lib/http.h | 6 ++++++ + lib/vtls/openssl.c | 3 ++- + 3 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index f0476f3b9272..0d5c449bc72a 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -776,10 +776,10 @@ output_auth_headers(struct Curl_easy *data, + } + + /* +- * allow_auth_to_host() tells if autentication, cookies or other "sensitive +- * data" can (still) be sent to this host. ++ * Curl_allow_auth_to_host() tells if authentication, cookies or other ++ * "sensitive data" can (still) be sent to this host. + */ +-static bool allow_auth_to_host(struct Curl_easy *data) ++bool Curl_allow_auth_to_host(struct Curl_easy *data) + { + struct connectdata *conn = data->conn; + return (!data->state.this_is_a_follow || +@@ -864,7 +864,7 @@ Curl_http_output_auth(struct Curl_easy *data, + + /* To prevent the user+password to get sent to other than the original host + due to a location-follow */ +- if(allow_auth_to_host(data) ++ if(Curl_allow_auth_to_host(data) + #ifndef CURL_DISABLE_NETRC + || conn->bits.netrc + #endif +@@ -1917,7 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ +- !allow_auth_to_host(data)) ++ !Curl_allow_auth_to_host(data)) + ; + else { + #ifdef USE_HYPER +diff --git a/lib/http.h b/lib/http.h +index 0972261e63bd..c4ab3c22dec9 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -364,4 +364,10 @@ Curl_http_output_auth(struct Curl_easy *data, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + ++/* ++ * Curl_allow_auth_to_host() tells if authentication, cookies or other ++ * "sensitive data" can (still) be sent to this host. ++ */ ++bool Curl_allow_auth_to_host(struct Curl_easy *data); ++ + #endif /* HEADER_CURL_HTTP_H */ +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 5d8e2d39d8e2..3722005d44e9 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -2924,7 +2924,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + #endif + + #ifdef USE_OPENSSL_SRP +- if(ssl_authtype == CURL_TLSAUTH_SRP) { ++ if((ssl_authtype == CURL_TLSAUTH_SRP) && ++ Curl_allow_auth_to_host(data)) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s", ssl_username); diff --git a/backport-CVE-2022-22576.patch b/backport-CVE-2022-22576.patch new file mode 100644 index 0000000..99d1525 --- /dev/null +++ b/backport-CVE-2022-22576.patch @@ -0,0 +1,142 @@ +From 852aa5ad351ea53e5f01d2f44b5b4370c2bf5425 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +Date: Mon, 25 Apr 2022 11:44:05 +0200 +Subject: [PATCH] url: check sasl additional parameters for connection reuse. + +Also move static function safecmp() as non-static Curl_safecmp() since +its purpose is needed at several places. + +Bug: https://curl.se/docs/CVE-2022-22576.html + +CVE-2022-22576 + +Closes #8746 +--- + lib/strcase.c | 10 ++++++++++ + lib/strcase.h | 2 ++ + lib/url.c | 13 ++++++++++++- + lib/urldata.h | 1 + + lib/vtls/vtls.c | 21 ++++++--------------- + 5 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/lib/strcase.c b/lib/strcase.c +index dd46ca1ba0e5..692a3f14aee7 100644 +--- a/lib/strcase.c ++++ b/lib/strcase.c +@@ -131,6 +131,16 @@ void Curl_strntolower(char *dest, const char *src, size_t n) + } while(*src++ && --n); + } + ++/* Compare case-sensitive NUL-terminated strings, taking care of possible ++ * null pointers. Return true if arguments match. ++ */ ++bool Curl_safecmp(char *a, char *b) ++{ ++ if(a && b) ++ return !strcmp(a, b); ++ return !a && !b; ++} ++ + /* --- public functions --- */ + + int curl_strequal(const char *first, const char *second) +diff --git a/lib/strcase.h b/lib/strcase.h +index b234d3815220..2635f5117e99 100644 +--- a/lib/strcase.h ++++ b/lib/strcase.h +@@ -49,4 +49,6 @@ char Curl_raw_toupper(char in); + 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); ++ + #endif /* HEADER_CURL_STRCASE_H */ +diff --git a/lib/url.c b/lib/url.c +index 9a988b4d58d8..e1647b133854 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -781,6 +781,7 @@ static void conn_free(struct connectdata *conn) + Curl_safefree(conn->passwd); + Curl_safefree(conn->sasl_authzid); + Curl_safefree(conn->options); ++ Curl_safefree(conn->oauth_bearer); + Curl_dyn_free(&conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ +@@ -1342,7 +1343,9 @@ ConnectionExists(struct Curl_easy *data, + /* 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)) { ++ strcmp(needle->passwd, check->passwd) || ++ !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) || ++ !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ + continue; + } +@@ -3637,6 +3640,14 @@ static CURLcode create_conn(struct Curl_easy *data, + } + } + ++ if(data->set.str[STRING_BEARER]) { ++ conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); ++ if(!conn->oauth_bearer) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } ++ } ++ + #ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); +diff --git a/lib/urldata.h b/lib/urldata.h +index 07eb19b87034..1d89b8d7fa68 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -984,6 +984,7 @@ struct connectdata { + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + char *sasl_authzid; /* authorisation identity string, allocated */ ++ char *oauth_bearer; /* OAUTH2 bearer, allocated */ + unsigned char httpversion; /* the HTTP version*10 reported by the server */ + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 03b85ba065e5..a40ac06f684f 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -125,15 +125,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second) + return !memcmp(first->data, second->data, first->len); /* same data */ + } + +-static bool safecmp(char *a, char *b) +-{ +- if(a && b) +- return !strcmp(a, b); +- else if(!a && !b) +- return TRUE; /* match */ +- return FALSE; /* no match */ +-} +- + + bool + Curl_ssl_config_matches(struct ssl_primary_config *data, +@@ -147,12 +138,12 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + blobcmp(data->cert_blob, needle->cert_blob) && + blobcmp(data->ca_info_blob, needle->ca_info_blob) && + blobcmp(data->issuercert_blob, needle->issuercert_blob) && +- safecmp(data->CApath, needle->CApath) && +- safecmp(data->CAfile, needle->CAfile) && +- safecmp(data->issuercert, needle->issuercert) && +- safecmp(data->clientcert, needle->clientcert) && +- safecmp(data->random_file, needle->random_file) && +- safecmp(data->egdsocket, needle->egdsocket) && ++ Curl_safecmp(data->CApath, needle->CApath) && ++ Curl_safecmp(data->CAfile, needle->CAfile) && ++ Curl_safecmp(data->issuercert, needle->issuercert) && ++ Curl_safecmp(data->clientcert, needle->clientcert) && ++ Curl_safecmp(data->random_file, needle->random_file) && ++ Curl_safecmp(data->egdsocket, needle->egdsocket) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && + Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) && + Curl_safe_strcasecompare(data->curves, needle->curves) && diff --git a/backport-CVE-2022-27775.patch b/backport-CVE-2022-27775.patch new file mode 100644 index 0000000..606ba9c --- /dev/null +++ b/backport-CVE-2022-27775.patch @@ -0,0 +1,34 @@ +From 058f98dc3fe595f21dc26a5b9b1699e519ba5705 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 11:48:00 +0200 +Subject: [PATCH] conncache: include the zone id in the "bundle" hashkey + +Make connections to two separate IPv6 zone ids create separate +connections. + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27775.html +Closes #8747 +--- + lib/conncache.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/conncache.c b/lib/conncache.c +index ec669b971dc3..8948b53fa500 100644 +--- a/lib/conncache.c ++++ b/lib/conncache.c +@@ -155,8 +155,12 @@ static void hashkey(struct connectdata *conn, char *buf, + /* report back which name we used */ + *hostp = hostname; + +- /* put the number first so that the hostname gets cut off if too long */ +- msnprintf(buf, len, "%ld%s", port, hostname); ++ /* put the numbers first so that the hostname gets cut off if too long */ ++#ifdef ENABLE_IPV6 ++ msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname); ++#else ++ msnprintf(buf, len, "%ld/%s", port, hostname); ++#endif + Curl_strntolower(buf, buf, len); + } + diff --git a/backport-CVE-2022-27776.patch b/backport-CVE-2022-27776.patch new file mode 100644 index 0000000..e1f169e --- /dev/null +++ b/backport-CVE-2022-27776.patch @@ -0,0 +1,112 @@ +From 6e659993952aa5f90f48864be84a1bbb047fc258 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 13:05:40 +0200 +Subject: [PATCH] http: avoid auth/cookie on redirects same host diff port + +CVE-2022-27776 + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27776.html +Closes #8749 +--- + lib/http.c | 34 ++++++++++++++++++++++------------ + lib/urldata.h | 16 +++++++++------- + 2 files changed, 31 insertions(+), 19 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index ce79fc4e31c8..f0476f3b9272 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -775,6 +775,21 @@ output_auth_headers(struct Curl_easy *data, + return CURLE_OK; + } + ++/* ++ * allow_auth_to_host() tells if autentication, cookies or other "sensitive ++ * data" can (still) be sent to this host. ++ */ ++static bool allow_auth_to_host(struct Curl_easy *data) ++{ ++ struct connectdata *conn = data->conn; ++ return (!data->state.this_is_a_follow || ++ data->set.allow_auth_to_other_hosts || ++ (data->state.first_host && ++ strcasecompare(data->state.first_host, conn->host.name) && ++ (data->state.first_remote_port == conn->remote_port) && ++ (data->state.first_remote_protocol == conn->handler->protocol))); ++} ++ + /** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication +@@ -847,17 +862,14 @@ Curl_http_output_auth(struct Curl_easy *data, + with it */ + authproxy->done = TRUE; + +- /* To prevent the user+password to get sent to other than the original +- host due to a location-follow, we do some weirdo checks here */ +- if(!data->state.this_is_a_follow || ++ /* To prevent the user+password to get sent to other than the original host ++ due to a location-follow */ ++ if(allow_auth_to_host(data) + #ifndef CURL_DISABLE_NETRC +- conn->bits.netrc || ++ || conn->bits.netrc + #endif +- !data->state.first_host || +- data->set.allow_auth_to_other_hosts || +- strcasecompare(data->state.first_host, conn->host.name)) { ++ ) + result = output_auth_headers(data, conn, authhost, request, path, FALSE); +- } + else + authhost->done = TRUE; + +@@ -1905,10 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ +- (data->state.this_is_a_follow && +- data->state.first_host && +- !data->set.allow_auth_to_other_hosts && +- !strcasecompare(data->state.first_host, conn->host.name))) ++ !allow_auth_to_host(data)) + ; + else { + #ifdef USE_HYPER +@@ -2084,6 +2093,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) + return CURLE_OUT_OF_MEMORY; + + data->state.first_remote_port = conn->remote_port; ++ data->state.first_remote_protocol = conn->handler->protocol; + } + Curl_safefree(data->state.aptr.host); + +diff --git a/lib/urldata.h b/lib/urldata.h +index 1d89b8d7fa68..ef2174d9e727 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1329,14 +1329,16 @@ struct UrlState { + char *ulbuf; /* allocated upload buffer or NULL */ + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ +- char *first_host; /* host name of the first (not followed) request. +- if set, this should be the host name that we will +- sent authorization to, no else. Used to make Location: +- following not keep sending user+password... This is +- strdup() data. +- */ ++ ++ /* host name, port number and protocol of the first (not followed) request. ++ if set, this should be the host name that we will sent authorization to, ++ no else. Used to make Location: following not keep sending user+password. ++ This is strdup()ed data. */ ++ char *first_host; ++ int first_remote_port; ++ unsigned int first_remote_protocol; ++ + int retrycount; /* number of retries on a new connection */ +- int first_remote_port; /* remote port of the first (not followed) request */ + struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ diff --git a/backport-pre-CVE-2022-27774.patch b/backport-pre-CVE-2022-27774.patch new file mode 100644 index 0000000..cee2c24 --- /dev/null +++ b/backport-pre-CVE-2022-27774.patch @@ -0,0 +1,40 @@ +From 08b8ef4e726ba10f45081ecda5b3cea788d3c839 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH] connect: store "conn_remote_port" in the info struct + +To make it available after the connection ended. +--- + lib/connect.c | 1 + + lib/urldata.h | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lib/connect.c b/lib/connect.c +index e0b740147157..9bcf525ebb39 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -623,6 +623,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, + data->info.conn_scheme = conn->handler->scheme; + data->info.conn_protocol = conn->handler->protocol; + data->info.conn_primary_port = conn->port; ++ data->info.conn_remote_port = conn->remote_port; + data->info.conn_local_port = local_port; + } + +diff --git a/lib/urldata.h b/lib/urldata.h +index ef2174d9e727..9c34ec444c08 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1160,7 +1160,11 @@ struct PureInfo { + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; +- int conn_primary_port; ++ int conn_primary_port; /* this is the destination port to the connection, ++ which might have been a proxy */ ++ int conn_remote_port; /* this is the "remote port", which is the port ++ number of the used URL, independent of proxy or ++ not */ + char conn_local_ip[MAX_IPADR_LEN]; + int conn_local_port; + const char *conn_scheme; diff --git a/curl.spec b/curl.spec index ae52a0b..9fc734e 100644 --- a/curl.spec +++ b/curl.spec @@ -6,13 +6,20 @@ Name: curl Version: 7.79.1 -Release: 2 +Release: 3 Summary: Curl is used in command lines or scripts to transfer data License: MIT URL: https://curl.haxx.se/ Source: https://curl.haxx.se/download/curl-%{version}.tar.xz Patch1: backport-0101-curl-7.32.0-multilib.patch +Patch2: backport-CVE-2022-22576.patch +Patch3: backport-CVE-2022-27775.patch +Patch4: backport-CVE-2022-27776.patch +Patch5: backport-pre-CVE-2022-27774.patch +Patch6: backport-001-CVE-2022-27774.patch +Patch7: backport-002-CVE-2022-27774.patch + BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel BuildRequires: libssh-devel make openldap-devel openssh-clients openssh-server @@ -189,6 +196,12 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_mandir}/man3/* %changelog +* Fri May 06 2022 gaihuiying - 7.79.1-3 +- Type:cves +- CVE:CVE-2022-22576 CVE-2022-27774 CVE-2022-27775 CVE-2022-27776 +- SUG:NA +- DESC:fix CVE-2022-22576 CVE-2022-27774 CVE-2022-27775 CVE-2022-27776 + * Mon Apr 25 2022 gaoxingwang - 7.79.1-2 - Type:bugfix - CVE:NA