diff --git a/SOURCES/0025-curl-7.61.1-CVE-2020-8284.patch b/SOURCES/0025-curl-7.61.1-CVE-2020-8284.patch new file mode 100644 index 0000000..674753e --- /dev/null +++ b/SOURCES/0025-curl-7.61.1-CVE-2020-8284.patch @@ -0,0 +1,208 @@ +From 2629f42d4cfdd04df0544007b03161e3d5d52d54 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 24 Nov 2020 14:56:57 +0100 +Subject: [PATCH] ftp: CURLOPT_FTP_SKIP_PASV_IP by default + +The command line tool also independently sets --ftp-skip-pasv-ip by +default. + +Ten test cases updated to adapt the modified --libcurl output. + +Bug: https://curl.se/docs/CVE-2020-8284.html +CVE-2020-8284 + +Reported-by: Varnavas Papaioannou + +Upstream-commit: ec9cc725d598ac77de7b6df8afeec292b3c8ad46 +Signed-off-by: Kamil Dudka +--- + docs/cmdline-opts/ftp-skip-pasv-ip.d | 2 ++ + docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | 8 +++++--- + lib/url.c | 1 + + src/tool_cfgable.c | 1 + + tests/data/test1400 | 1 + + tests/data/test1401 | 1 + + tests/data/test1402 | 1 + + tests/data/test1403 | 1 + + tests/data/test1404 | 1 + + tests/data/test1405 | 1 + + tests/data/test1406 | 1 + + tests/data/test1407 | 1 + + tests/data/test1420 | 1 + + 13 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d +index da6ab11..4be8b43 100644 +--- a/docs/cmdline-opts/ftp-skip-pasv-ip.d ++++ b/docs/cmdline-opts/ftp-skip-pasv-ip.d +@@ -9,4 +9,6 @@ to curl's PASV command when curl connects the data connection. Instead curl + will re-use the same IP address it already uses for the control + connection. + ++Since curl 7.74.0 this option is enabled by default. ++ + This option has no effect if PORT, EPRT or EPSV is used instead of PASV. +diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 +index 4d3026a..4227ed6 100644 +--- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 ++++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 +@@ -5,7 +5,7 @@ + .\" * | (__| |_| | _ <| |___ + .\" * \___|\___/|_| \_\_____| + .\" * +-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. ++.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + .\" * + .\" * This software is licensed as described in the file COPYING, which + .\" * you should have received as part of this distribution. The terms +@@ -36,11 +36,13 @@ address it already uses for the control connection. But it will use the port + number from the 227-response. + + This option thus allows libcurl to work around broken server installations +-that due to NATs, firewalls or incompetence report the wrong IP address back. ++that due to NATs, firewalls or incompetence report the wrong IP address ++back. Setting the option also reduces the risk for various sorts of client ++abuse by malicious servers. + + This option has no effect if PORT, EPRT or EPSV is used instead of PASV. + .SH DEFAULT +-0 ++1 since 7.74.0, was 0 before then. + .SH PROTOCOLS + FTP + .SH EXAMPLE +diff --git a/lib/url.c b/lib/url.c +index e77f391..b18db25 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -434,6 +434,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) + set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ + set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ + set->ftp_filemethod = FTPFILE_MULTICWD; ++ set->ftp_skip_ip = TRUE; /* skip PASV IP by default */ + + set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ + +diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c +index 81e16c1..110191e 100644 +--- a/src/tool_cfgable.c ++++ b/src/tool_cfgable.c +@@ -43,6 +43,7 @@ void config_init(struct OperationConfig* config) + config->proto_default = NULL; + config->tcp_nodelay = TRUE; /* enabled by default */ + config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT; ++ config->ftp_skip_ip = TRUE; + } + + static void free_config_fields(struct OperationConfig *config) +diff --git a/tests/data/test1400 b/tests/data/test1400 +index 10faef3..9d18a30 100644 +--- a/tests/data/test1400 ++++ b/tests/data/test1400 +@@ -73,6 +73,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +diff --git a/tests/data/test1401 b/tests/data/test1401 +index f330931..99cb0cb 100644 +--- a/tests/data/test1401 ++++ b/tests/data/test1401 +@@ -89,6 +89,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip"); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE | + (long)CURLPROTO_FTP | +diff --git a/tests/data/test1402 b/tests/data/test1402 +index 9a94283..ef55bd6 100644 +--- a/tests/data/test1402 ++++ b/tests/data/test1402 +@@ -80,6 +80,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +diff --git a/tests/data/test1403 b/tests/data/test1403 +index 79cdf49..78932c2 100644 +--- a/tests/data/test1403 ++++ b/tests/data/test1403 +@@ -75,6 +75,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +diff --git a/tests/data/test1404 b/tests/data/test1404 +index 9c6f2e7..8ea5e04 100644 +--- a/tests/data/test1404 ++++ b/tests/data/test1404 +@@ -144,6 +144,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +diff --git a/tests/data/test1405 b/tests/data/test1405 +index 73769ee..5a83b6e 100644 +--- a/tests/data/test1405 ++++ b/tests/data/test1405 +@@ -89,6 +89,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, slist2); + curl_easy_setopt(hnd, CURLOPT_PREQUOTE, slist3); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +diff --git a/tests/data/test1406 b/tests/data/test1406 +index 796dd22..c941e00 100644 +--- a/tests/data/test1406 ++++ b/tests/data/test1406 +@@ -80,6 +80,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406"); + curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com"); + curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1); +diff --git a/tests/data/test1407 b/tests/data/test1407 +index 9800eee..ddba7b7 100644 +--- a/tests/data/test1407 ++++ b/tests/data/test1407 +@@ -62,6 +62,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 1L); + curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret"); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +diff --git a/tests/data/test1420 b/tests/data/test1420 +index a5e1c52..72fb353 100644 +--- a/tests/data/test1420 ++++ b/tests/data/test1420 +@@ -67,6 +67,7 @@ int main(int argc, char *argv[]) + curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;UID=1"); + curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret"); + curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); ++ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + /* Here is a list of options the curl code used that cannot get generated +-- +2.26.2 + diff --git a/SOURCES/0026-curl-7.61.1-CVE-2020-8285.patch b/SOURCES/0026-curl-7.61.1-CVE-2020-8285.patch new file mode 100644 index 0000000..703287e --- /dev/null +++ b/SOURCES/0026-curl-7.61.1-CVE-2020-8285.patch @@ -0,0 +1,258 @@ +From 22b3d1cf0216f4369f01678c587da265c2e465af Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 28 Nov 2020 00:27:21 +0100 +Subject: [PATCH] ftp: make wc_statemach loop instead of recurse + +CVE-2020-8285 + +Fixes #6255 +Bug: https://curl.se/docs/CVE-2020-8285.html +Reported-by: xnynx on github + +Upstream-commit: 69a358f2186e04cf44698b5100332cbf1ee7f01d +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 204 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 103 insertions(+), 101 deletions(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index 7dbf080..482ab3a 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -3786,130 +3786,132 @@ static CURLcode init_wc_data(struct connectdata *conn) + return result; + } + +-/* This is called recursively */ + static CURLcode wc_statemach(struct connectdata *conn) + { + struct WildcardData * const wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + +- switch(wildcard->state) { +- case CURLWC_INIT: +- result = init_wc_data(conn); +- if(wildcard->state == CURLWC_CLEAN) +- /* only listing! */ +- break; +- wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; +- break; ++ for(;;) { ++ switch(wildcard->state) { ++ case CURLWC_INIT: ++ result = init_wc_data(conn); ++ if(wildcard->state == CURLWC_CLEAN) ++ /* only listing! */ ++ return result; ++ wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; ++ return result; + +- case CURLWC_MATCHING: { +- /* In this state is LIST response successfully parsed, so lets restore +- previous WRITEFUNCTION callback and WRITEDATA pointer */ +- struct ftp_wc *ftpwc = wildcard->protdata; +- conn->data->set.fwrite_func = ftpwc->backup.write_function; +- conn->data->set.out = ftpwc->backup.file_descriptor; +- ftpwc->backup.write_function = ZERO_NULL; +- ftpwc->backup.file_descriptor = NULL; +- wildcard->state = CURLWC_DOWNLOADING; +- +- if(Curl_ftp_parselist_geterror(ftpwc->parser)) { +- /* error found in LIST parsing */ +- wildcard->state = CURLWC_CLEAN; +- return wc_statemach(conn); +- } +- if(wildcard->filelist.size == 0) { +- /* no corresponding file */ +- wildcard->state = CURLWC_CLEAN; +- return CURLE_REMOTE_FILE_NOT_FOUND; ++ case CURLWC_MATCHING: { ++ /* In this state is LIST response successfully parsed, so lets restore ++ previous WRITEFUNCTION callback and WRITEDATA pointer */ ++ struct ftp_wc *ftpwc = wildcard->protdata; ++ conn->data->set.fwrite_func = ftpwc->backup.write_function; ++ conn->data->set.out = ftpwc->backup.file_descriptor; ++ ftpwc->backup.write_function = ZERO_NULL; ++ ftpwc->backup.file_descriptor = NULL; ++ wildcard->state = CURLWC_DOWNLOADING; ++ ++ if(Curl_ftp_parselist_geterror(ftpwc->parser)) { ++ /* error found in LIST parsing */ ++ wildcard->state = CURLWC_CLEAN; ++ continue; ++ } ++ if(wildcard->filelist.size == 0) { ++ /* no corresponding file */ ++ wildcard->state = CURLWC_CLEAN; ++ return CURLE_REMOTE_FILE_NOT_FOUND; ++ } ++ continue; + } +- return wc_statemach(conn); +- } + +- case CURLWC_DOWNLOADING: { +- /* filelist has at least one file, lets get first one */ +- struct ftp_conn *ftpc = &conn->proto.ftpc; +- struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; ++ case CURLWC_DOWNLOADING: { ++ /* filelist has at least one file, lets get first one */ ++ struct ftp_conn *ftpc = &conn->proto.ftpc; ++ struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; + +- char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); +- if(!tmp_path) +- return CURLE_OUT_OF_MEMORY; ++ char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); ++ if(!tmp_path) ++ return CURLE_OUT_OF_MEMORY; + +- /* switch default "state.pathbuffer" and tmp_path, good to see +- ftp_parse_url_path function to understand this trick */ +- Curl_safefree(conn->data->state.pathbuffer); +- conn->data->state.pathbuffer = tmp_path; +- conn->data->state.path = tmp_path; +- +- infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); +- if(conn->data->set.chunk_bgn) { +- long userresponse; +- Curl_set_in_callback(conn->data, true); +- userresponse = conn->data->set.chunk_bgn( +- finfo, wildcard->customptr, (int)wildcard->filelist.size); +- Curl_set_in_callback(conn->data, false); +- switch(userresponse) { +- case CURL_CHUNK_BGN_FUNC_SKIP: +- infof(conn->data, "Wildcard - \"%s\" skipped by user\n", +- finfo->filename); +- wildcard->state = CURLWC_SKIP; +- return wc_statemach(conn); +- case CURL_CHUNK_BGN_FUNC_FAIL: +- return CURLE_CHUNK_FAILED; ++ /* switch default "state.pathbuffer" and tmp_path, good to see ++ ftp_parse_url_path function to understand this trick */ ++ Curl_safefree(conn->data->state.pathbuffer); ++ conn->data->state.pathbuffer = tmp_path; ++ conn->data->state.path = tmp_path; ++ ++ infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); ++ if(conn->data->set.chunk_bgn) { ++ long userresponse; ++ Curl_set_in_callback(conn->data, true); ++ userresponse = conn->data->set.chunk_bgn( ++ finfo, wildcard->customptr, (int)wildcard->filelist.size); ++ Curl_set_in_callback(conn->data, false); ++ switch(userresponse) { ++ case CURL_CHUNK_BGN_FUNC_SKIP: ++ infof(conn->data, "Wildcard - \"%s\" skipped by user\n", ++ finfo->filename); ++ wildcard->state = CURLWC_SKIP; ++ continue; ++ case CURL_CHUNK_BGN_FUNC_FAIL: ++ return CURLE_CHUNK_FAILED; ++ } + } +- } + +- if(finfo->filetype != CURLFILETYPE_FILE) { +- wildcard->state = CURLWC_SKIP; +- return wc_statemach(conn); +- } ++ if(finfo->filetype != CURLFILETYPE_FILE) { ++ wildcard->state = CURLWC_SKIP; ++ continue; ++ } + +- if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) +- ftpc->known_filesize = finfo->size; ++ if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) ++ ftpc->known_filesize = finfo->size; + +- result = ftp_parse_url_path(conn); +- if(result) +- return result; ++ result = ftp_parse_url_path(conn); ++ if(result) ++ return result; + +- /* we don't need the Curl_fileinfo of first file anymore */ +- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); ++ /* we don't need the Curl_fileinfo of first file anymore */ ++ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + +- if(wildcard->filelist.size == 0) { /* remains only one file to down. */ +- wildcard->state = CURLWC_CLEAN; +- /* after that will be ftp_do called once again and no transfer +- will be done because of CURLWC_CLEAN state */ +- return CURLE_OK; ++ if(wildcard->filelist.size == 0) { /* remains only one file to down. */ ++ wildcard->state = CURLWC_CLEAN; ++ /* after that will be ftp_do called once again and no transfer ++ will be done because of CURLWC_CLEAN state */ ++ return CURLE_OK; ++ } ++ return result; + } +- } break; + +- case CURLWC_SKIP: { +- if(conn->data->set.chunk_end) { +- Curl_set_in_callback(conn->data, true); +- conn->data->set.chunk_end(conn->data->wildcard.customptr); +- Curl_set_in_callback(conn->data, false); ++ case CURLWC_SKIP: { ++ if(conn->data->set.chunk_end) { ++ Curl_set_in_callback(conn->data, true); ++ conn->data->set.chunk_end(conn->data->wildcard.customptr); ++ Curl_set_in_callback(conn->data, false); ++ } ++ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); ++ wildcard->state = (wildcard->filelist.size == 0) ? ++ CURLWC_CLEAN : CURLWC_DOWNLOADING; ++ continue; + } +- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); +- wildcard->state = (wildcard->filelist.size == 0) ? +- CURLWC_CLEAN : CURLWC_DOWNLOADING; +- return wc_statemach(conn); +- } + +- case CURLWC_CLEAN: { +- struct ftp_wc *ftpwc = wildcard->protdata; +- result = CURLE_OK; +- if(ftpwc) +- result = Curl_ftp_parselist_geterror(ftpwc->parser); ++ case CURLWC_CLEAN: { ++ struct ftp_wc *ftpwc = wildcard->protdata; ++ result = CURLE_OK; ++ if(ftpwc) ++ result = Curl_ftp_parselist_geterror(ftpwc->parser); + +- wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; +- } break; ++ wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; ++ return result; ++ } + +- case CURLWC_DONE: +- case CURLWC_ERROR: +- case CURLWC_CLEAR: +- if(wildcard->dtor) +- wildcard->dtor(wildcard->protdata); +- break; ++ case CURLWC_DONE: ++ case CURLWC_ERROR: ++ case CURLWC_CLEAR: ++ if(wildcard->dtor) ++ wildcard->dtor(wildcard->protdata); ++ return result; ++ } + } +- +- return result; ++ /* UNREACHABLE */ + } + + /*********************************************************************** +-- +2.26.2 + diff --git a/SOURCES/0027-curl-7.61.1-CVE-2020-8286.patch b/SOURCES/0027-curl-7.61.1-CVE-2020-8286.patch new file mode 100644 index 0000000..5180971 --- /dev/null +++ b/SOURCES/0027-curl-7.61.1-CVE-2020-8286.patch @@ -0,0 +1,129 @@ +From 2470bc91f62cc9b0ab1deac60a67f87b7cc95f6e Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 2 Dec 2020 23:01:11 +0100 +Subject: [PATCH] openssl: make the OCSP verification verify the certificate id + +CVE-2020-8286 + +Reported by anonymous + +Bug: https://curl.se/docs/CVE-2020-8286.html + +Upstream-commit: d9d01672785b8ac04aab1abb6de95fe3072ae199 +Signed-off-by: Kamil Dudka +--- + lib/vtls/openssl.c | 83 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 54 insertions(+), 29 deletions(-) + +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 9476773..35cd652 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -1659,6 +1659,11 @@ static CURLcode verifystatus(struct connectdata *conn, + OCSP_BASICRESP *br = NULL; + X509_STORE *st = NULL; + STACK_OF(X509) *ch = NULL; ++ X509 *cert; ++ OCSP_CERTID *id = NULL; ++ int cert_status, crl_reason; ++ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; ++ int ret; + + long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p); + +@@ -1727,43 +1732,63 @@ static CURLcode verifystatus(struct connectdata *conn, + goto end; + } + +- for(i = 0; i < OCSP_resp_count(br); i++) { +- int cert_status, crl_reason; +- OCSP_SINGLERESP *single = NULL; +- +- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; ++ /* Compute the certificate's ID */ ++ cert = SSL_get_peer_certificate(BACKEND->handle); ++ if(!cert) { ++ failf(data, "Error getting peer certficate"); ++ result = CURLE_SSL_INVALIDCERTSTATUS; ++ goto end; ++ } + +- single = OCSP_resp_get0(br, i); +- if(!single) +- continue; ++ for(i = 0; i < sk_X509_num(ch); i++) { ++ X509 *issuer = sk_X509_value(ch, i); ++ if(X509_check_issued(issuer, cert) == X509_V_OK) { ++ id = OCSP_cert_to_id(EVP_sha1(), cert, issuer); ++ break; ++ } ++ } ++ X509_free(cert); + +- cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, +- &thisupd, &nextupd); ++ if(!id) { ++ failf(data, "Error computing OCSP ID"); ++ result = CURLE_SSL_INVALIDCERTSTATUS; ++ goto end; ++ } + +- if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { +- failf(data, "OCSP response has expired"); +- result = CURLE_SSL_INVALIDCERTSTATUS; +- goto end; +- } ++ /* Find the single OCSP response corresponding to the certificate ID */ ++ ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev, ++ &thisupd, &nextupd); ++ OCSP_CERTID_free(id); ++ if(ret != 1) { ++ failf(data, "Could not find certificate ID in OCSP response"); ++ result = CURLE_SSL_INVALIDCERTSTATUS; ++ goto end; ++ } + +- infof(data, "SSL certificate status: %s (%d)\n", +- OCSP_cert_status_str(cert_status), cert_status); ++ /* Validate the corresponding single OCSP response */ ++ if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { ++ failf(data, "OCSP response has expired"); ++ result = CURLE_SSL_INVALIDCERTSTATUS; ++ goto end; ++ } + +- switch(cert_status) { +- case V_OCSP_CERTSTATUS_GOOD: +- break; ++ infof(data, "SSL certificate status: %s (%d)\n", ++ OCSP_cert_status_str(cert_status), cert_status); + +- case V_OCSP_CERTSTATUS_REVOKED: +- result = CURLE_SSL_INVALIDCERTSTATUS; ++ switch(cert_status) { ++ case V_OCSP_CERTSTATUS_GOOD: ++ break; + +- failf(data, "SSL certificate revocation reason: %s (%d)", +- OCSP_crl_reason_str(crl_reason), crl_reason); +- goto end; ++ case V_OCSP_CERTSTATUS_REVOKED: ++ result = CURLE_SSL_INVALIDCERTSTATUS; ++ failf(data, "SSL certificate revocation reason: %s (%d)", ++ OCSP_crl_reason_str(crl_reason), crl_reason); ++ goto end; + +- case V_OCSP_CERTSTATUS_UNKNOWN: +- result = CURLE_SSL_INVALIDCERTSTATUS; +- goto end; +- } ++ case V_OCSP_CERTSTATUS_UNKNOWN: ++ default: ++ result = CURLE_SSL_INVALIDCERTSTATUS; ++ goto end; + } + + end: +-- +2.26.2 + diff --git a/SOURCES/0028-curl-7.61.1-http-auth-payload.patch b/SOURCES/0028-curl-7.61.1-http-auth-payload.patch new file mode 100644 index 0000000..c4662b4 --- /dev/null +++ b/SOURCES/0028-curl-7.61.1-http-auth-payload.patch @@ -0,0 +1,63 @@ +From 5a51924c2505c1d5616904aa732fdaedd74d3ffe Mon Sep 17 00:00:00 2001 +From: Marc Schlatter +Date: Mon, 11 Mar 2019 17:15:34 +0100 +Subject: [PATCH] http: send payload when (proxy) authentication is done + +The check that prevents payload from sending in case of authentication +doesn't check properly if the authentication is done or not. + +They're cases where the proxy respond "200 OK" before sending +authentication challenge. This change takes care of that. + +Fixes #2431 +Closes #3669 + +Upstream-commit: dd8a19f8a05b59394d1ab33c09497e8db884742a +Signed-off-by: Kamil Dudka +--- + lib/http.c | 3 ++- + tests/data/test1097 | 5 +++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index e727ed8..26eb52d 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1991,7 +1991,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) + if(result) + return result; + +- if((data->state.authhost.multipass || data->state.authproxy.multipass) && ++ if(((data->state.authhost.multipass && !data->state.authhost.done) ++ || (data->state.authproxy.multipass && !data->state.authproxy.done)) && + (httpreq != HTTPREQ_GET) && + (httpreq != HTTPREQ_HEAD)) { + /* Auth is required and we are not authenticated yet. Make a PUT or POST +diff --git a/tests/data/test1097 b/tests/data/test1097 +index 7512a2e..7eb7b5f 100644 +--- a/tests/data/test1097 ++++ b/tests/data/test1097 +@@ -60,7 +60,7 @@ http://test.a.galaxy.far.far.away.1097:%HTTPPORT/1097 --proxy http://%HOSTIP:%HT + + ^User-Agent: curl/.* + +- ++ + CONNECT test.a.galaxy.far.far.away.1097:%HTTPPORT HTTP/1.1 + Host: test.a.galaxy.far.far.away.1097:%HTTPPORT + Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= +@@ -71,9 +71,10 @@ POST /1097 HTTP/1.1 + User-Agent: curl/7.19.5-CVS (i686-pc-linux-gnu) libcurl/7.19.5-CVS OpenSSL/0.9.8g zlib/1.2.3.3 c-ares/1.6.1-CVS libidn/1.12 libssh2/1.0.1_CVS + Host: test.a.galaxy.far.far.away.1097:%HTTPPORT + Accept: */* +-Content-Length: 0 ++Content-Length: 11 + Content-Type: application/x-www-form-urlencoded + ++dummy=value + + + +-- +2.26.2 + diff --git a/SOURCES/0105-curl-7.61.1-test-ports.patch b/SOURCES/0105-curl-7.61.1-test-ports.patch new file mode 100644 index 0000000..e536586 --- /dev/null +++ b/SOURCES/0105-curl-7.61.1-test-ports.patch @@ -0,0 +1,71 @@ +From e6507a9abbfd4ac93ea3053c8f3385a2405f19d8 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 29 Jan 2021 11:34:49 +0100 +Subject: [PATCH] tests: do not hard-wire ports of test servers + +--- + tests/data/test1448 | 4 ++-- + tests/data/test651 | 2 +- + tests/data/test653 | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tests/data/test1448 b/tests/data/test1448 +index e04f47b..5022ef9 100644 +--- a/tests/data/test1448 ++++ b/tests/data/test1448 +@@ -17,7 +17,7 @@ HTTP/1.1 302 OK swsbounce + Date: Thu, 09 Nov 2010 14:49:00 GMT + Content-Length: 9 + Content-Type: text/plain +-Location: http://åäö.se:8990/14480001 ++Location: http://åäö.se:%HTTPPORT/14480001 + + redirect + +@@ -52,7 +52,7 @@ Redirect following to UTF-8 IDN host name + + + +-http://åäö.se:%HTTPPORT/1448 --resolve xn--4cab6c.se:%HTTPPORT:%HOSTIP -L --connect-to %HOSTIP:8990:%HOSTIP:%HTTPPORT ++http://åäö.se:%HTTPPORT/1448 --resolve xn--4cab6c.se:%HTTPPORT:%HOSTIP -L --connect-to %HOSTIP:%HTTPPORT:%HOSTIP:%HTTPPORT + + + +diff --git a/tests/data/test651 b/tests/data/test651 +index b00ca5d..8d47c9f 100644 +--- a/tests/data/test651 ++++ b/tests/data/test651 +@@ -57,7 +57,7 @@ s/boundary=------------------------[a-z0-9]*/boundary=-------------------------- + # (5*12) == 60 bytes less + + POST /651 HTTP/1.1 +-Host: 127.0.0.1:8990 ++Host: 127.0.0.1:%HTTPPORT + Accept: */* + Content-Length: 17139 + Content-Type: multipart/form-data; boundary=---------------------------- +diff --git a/tests/data/test653 b/tests/data/test653 +index d620b57..492d551 100644 +--- a/tests/data/test653 ++++ b/tests/data/test653 +@@ -67,7 +67,7 @@ s/boundary=------------------------[a-z0-9]*/boundary=-------------------------- + # (5*12) == 60 bytes less + + POST /653 HTTP/1.1 +-Host: 127.0.0.1:8990 ++Host: 127.0.0.1:%HTTPPORT + Accept: */* + Content-Length: 150 + Content-Type: multipart/form-data; boundary=---------------------------- +@@ -78,7 +78,7 @@ Content-Disposition: form-data; name="name" + short value + -------------------------------- + POST /653 HTTP/1.1 +-Host: 127.0.0.1:8990 ++Host: 127.0.0.1:%HTTPPORT + Accept: */* + Content-Length: 167 + Content-Type: multipart/form-data; boundary=---------------------------- +-- +2.26.2 + diff --git a/SPECS/curl.spec b/SPECS/curl.spec index 68679a7..8f28ad1 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.61.1 -Release: 17%{?dist} +Release: 18%{?dist} License: MIT Source: https://curl.haxx.se/download/%{name}-%{version}.tar.xz @@ -67,6 +67,18 @@ Patch23: 0023-curl-7.61.1-no-https-proxy-crash.patch # validate an ssl connection using an intermediate certificate (#1895355) Patch24: 0024-curl-7.61.1-openssl-partial-chain.patch +# curl: trusting FTP PASV responses (CVE-2020-8284) +Patch25: 0025-curl-7.61.1-CVE-2020-8284.patch + +# libcurl: FTP wildcard stack overflow (CVE-2020-8285) +Patch26: 0026-curl-7.61.1-CVE-2020-8285.patch + +# curl: Inferior OCSP verification (CVE-2020-8286) +Patch27: 0027-curl-7.61.1-CVE-2020-8286.patch + +# http: send payload when (proxy) authentication is done (#1918692) +Patch28: 0028-curl-7.61.1-http-auth-payload.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -79,6 +91,9 @@ Patch103: 0103-curl-7.59.0-python3.patch # use localhost6 instead of ip6-localhost in the curl test-suite Patch104: 0104-curl-7.19.7-localhost6.patch +# tests: do not hard-wire ports of test servers +Patch105: 0105-curl-7.61.1-test-ports.patch + Provides: curl-full = %{version}-%{release} Provides: webclient URL: https://curl.haxx.se/ @@ -245,6 +260,11 @@ git apply %{PATCH4} %patch103 -p1 %patch104 -p1 +# use different port range for 32bit and 64bit builds, thus make it possible +# to run both the builds in parallel on the same machine +%patch105 -p1 +sed -e 's|%%HTTPPORT|%{?__isa_bits}90|g' -i tests/data/test1448 + # upstream patches %patch17 -p1 %patch18 -p1 @@ -254,6 +274,10 @@ git apply %{PATCH4} %patch22 -p1 %patch23 -p1 %patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 # make tests/*.py use Python 3 sed -e '1 s|^#!/.*python|#!%{__python3}|' -i tests/*.py @@ -346,7 +370,10 @@ export OPENSSL_SYSTEM_CIPHERS_OVERRIDE=XXX export OPENSSL_CONF= # run the upstream test-suite -srcdir=../../tests perl -I../../tests ../../tests/runtests.pl -a -p -v '!flaky' +# use different port range for 32bit and 64bit builds, thus make it possible +# to run both the builds in parallel on the same machine +export srcdir=../../tests +perl -I${srcdir} ${srcdir}/runtests.pl -b%{?__isa_bits}90 -a -p -v '!flaky' %install # install and rename the library that will be packaged as libcurl-minimal @@ -414,6 +441,12 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Thu Jan 28 2021 Kamil Dudka - 7.61.1-18 +- http: send payload when (proxy) authentication is done (#1918692) +- curl: Inferior OCSP verification (CVE-2020-8286) +- libcurl: FTP wildcard stack overflow (CVE-2020-8285) +- curl: trusting FTP PASV responses (CVE-2020-8284) + * Thu Nov 12 2020 Kamil Dudka - 7.61.1-17 - validate an ssl connection using an intermediate certificate (#1895355)