diff --git a/0001-curl-7.87.0-header-file-regression.patch b/0001-curl-7.87.0-header-file-regression.patch deleted file mode 100644 index 9c479dc..0000000 --- a/0001-curl-7.87.0-header-file-regression.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 613d3c45879636e88b88fcebee48dc77de345291 Mon Sep 17 00:00:00 2001 -From: Patrick Monnerat -Date: Fri, 23 Dec 2022 15:35:27 +0100 -Subject: [PATCH] typecheck: accept expressions for option/info parameters - -As expressions can have side effects, evaluate only once. - -To enable deprecation reporting only once, get rid of the __typeof__ -use to define the local temporary variable and use the target type -(CURLoption/CURLINFO). This also avoids multiple reports on type -conflicts (if some) by the curlcheck_* macros. - -Note that CURLOPT_* and CURLINFO_* symbols may be deprecated, but not -their values: a curl_easy_setopt call with an integer constant as option -will never report a deprecation. - -Reported-by: Thomas Klausner -Fixes #10148 -Closes #10149 - -Upstream-commit: e2aed004302e51cfa5b6ce8c8ab65ef92aa83196 -Signed-off-by: Kamil Dudka ---- - include/curl/typecheck-gcc.h | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h -index bf655bb..85aa8b7 100644 ---- a/include/curl/typecheck-gcc.h -+++ b/include/curl/typecheck-gcc.h -@@ -42,9 +42,8 @@ - */ - #define curl_easy_setopt(handle, option, value) \ - __extension__({ \ -- CURL_IGNORE_DEPRECATION(__typeof__(option) _curl_opt = option;) \ -+ CURLoption _curl_opt = (option); \ - if(__builtin_constant_p(_curl_opt)) { \ -- (void) option; \ - CURL_IGNORE_DEPRECATION( \ - if(curlcheck_long_option(_curl_opt)) \ - if(!curlcheck_long(value)) \ -@@ -120,9 +119,8 @@ - /* wraps curl_easy_getinfo() with typechecking */ - #define curl_easy_getinfo(handle, info, arg) \ - __extension__({ \ -- CURL_IGNORE_DEPRECATION(__typeof__(info) _curl_info = info;) \ -+ CURLINFO _curl_info = (info); \ - if(__builtin_constant_p(_curl_info)) { \ -- (void) info; \ - CURL_IGNORE_DEPRECATION( \ - if(curlcheck_string_info(_curl_info)) \ - if(!curlcheck_arr((arg), char *)) \ --- -2.39.0 - diff --git a/0001-curl-8.0.1-CVE-2023-28322.patch b/0001-curl-8.0.1-CVE-2023-28322.patch new file mode 100644 index 0000000..133ef63 --- /dev/null +++ b/0001-curl-8.0.1-CVE-2023-28322.patch @@ -0,0 +1,437 @@ +From 074adec63f0dd7a8f0d823ee503dfb0626061505 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. + +Closes #11017 + +(cherry picked from commit 7815647d6582c0a4900be2e1de6c5e61272c496b) +Signed-off-by: Jan Macku +--- + 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 2679a2cdc..406fb42ac 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 51c5d07ce..c751e8861 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 caf33d214..0b6e5cd4f 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1350,7 +1350,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 +@@ -3386,7 +3386,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 && +@@ -3642,7 +3642,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) +@@ -4231,7 +4231,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 faa486cc6..400d2b081 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1960,7 +1960,7 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn, + Curl_HttpReq httpreq = (Curl_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 */ +@@ -2277,7 +2277,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 c2f675d4b..1952e66a1 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 aef3560a9..6df3706b5 100644 +--- a/lib/rtsp.c ++++ b/lib/rtsp.c +@@ -495,7 +495,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; + +@@ -514,7 +514,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 6bb88791c..2cbaf898a 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -329,8 +329,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 */ +@@ -660,7 +660,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + } + else + data->set.method = HTTPREQ_GET; +- data->set.upload = FALSE; + break; + + #ifndef CURL_DISABLE_MIME +@@ -884,7 +883,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 076200472..2baf764fa 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -530,7 +530,7 @@ static CURLcode smb_send_open(struct Curl_easy *data) + byte_count = strlen(req->path); + msg.name_length = smb_swap16((unsigned short)byte_count); + msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); +- if(data->set.upload) { ++ if(data->state.upload) { + msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); + msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); + } +@@ -762,7 +762,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) + void *msg = NULL; + const struct smb_nt_create_response *smb_m; + +- if(data->set.upload && (data->state.infilesize < 0)) { ++ if(data->state.upload && (data->state.infilesize < 0)) { + failf(data, "SMB upload needs to know the size up front"); + return CURLE_SEND_ERROR; + } +@@ -813,7 +813,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) + smb_m = (const struct smb_nt_create_response*) msg; + req->fid = smb_swap16(smb_m->fid); + data->req.offset = 0; +- if(data->set.upload) { ++ if(data->state.upload) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->req.size); + next_state = SMB_UPLOAD; +diff --git a/lib/smtp.c b/lib/smtp.c +index 7a030308d..c182cace7 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 164d3c723..8ed1b887b 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 a28395233..85910455c 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1294,6 +1294,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); + } + + /* +@@ -1728,7 +1729,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", + data->req.no_body?"HEAD":"GET"); + } +@@ -1766,7 +1766,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 8b54518d2..f3e782ad3 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1446,6 +1446,7 @@ struct UrlState { + BIT(rewindbeforesend);/* TRUE when the sending couldn't be stopped even + though it will be discarded. We must call the data + rewind callback before trying to send again. */ ++ BIT(upload); /* upload request */ + }; + + /* +@@ -1822,7 +1823,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 b31f741ba..d60edaa30 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 f1154dc47..f2e5352d1 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 17d59ecd2..2ca91b736 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] == '/') +-- +2.40.1 + diff --git a/0002-curl-8.0.1-CVE-2023-28321.patch b/0002-curl-8.0.1-CVE-2023-28321.patch new file mode 100644 index 0000000..a69fdbd --- /dev/null +++ b/0002-curl-8.0.1-CVE-2023-28321.patch @@ -0,0 +1,498 @@ +From 9cfc8e3107920116ac31ab1fbf6439d38ab2f30e 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 + +(cherry picked from commit 199f2d440d8659b42670c1b796220792b01a97bf) +Signed-off-by: Jan Macku +--- + lib/vtls/hostcheck.c | 50 +++++++-------- + tests/data/test1397 | 10 ++- + tests/unit/Makefile.am | 88 -------------------------- + tests/unit/Makefile.inc | 94 ++++++++++++++++++++++++++++ + tests/unit/unit1397.c | 134 ++++++++++++++++++++++++---------------- + 5 files changed, 202 insertions(+), 174 deletions(-) + +diff --git a/lib/vtls/hostcheck.c b/lib/vtls/hostcheck.c +index e827dc58f..d061c6356 100644 +--- a/lib/vtls/hostcheck.c ++++ b/lib/vtls/hostcheck.c +@@ -71,7 +71,12 @@ static bool pmatch(const char *hostname, size_t hostlen, + * apparent distinction between a name and an IP. We need to detect the use of + * an IP address and not wildcard match on such names. + * ++ * Only match on "*" being used for the leftmost label, not "a*", "a*b" nor ++ * "*b". ++ * + * Return TRUE on a match. FALSE if not. ++ * ++ * @unittest: 1397 + */ + + static bool hostmatch(const char *hostname, +@@ -79,53 +84,42 @@ static bool hostmatch(const char *hostname, + const char *pattern, + size_t patternlen) + { +- const char *pattern_label_end, *wildcard, *hostname_label_end; +- size_t prefixlen, suffixlen; ++ const char *pattern_label_end; + +- /* normalize pattern and hostname by stripping off trailing dots */ ++ DEBUGASSERT(pattern); + DEBUGASSERT(patternlen); ++ DEBUGASSERT(hostname); ++ DEBUGASSERT(hostlen); ++ ++ /* normalize pattern and hostname by stripping off trailing dots */ + if(hostname[hostlen-1]=='.') + hostlen--; + if(pattern[patternlen-1]=='.') + patternlen--; + +- wildcard = memchr(pattern, '*', patternlen); +- if(!wildcard) ++ if(strncmp(pattern, "*.", 2)) + return pmatch(hostname, hostlen, pattern, patternlen); + + /* detect IP address as hostname and fail the match if so */ +- if(Curl_host_is_ipnum(hostname)) ++ else if(Curl_host_is_ipnum(hostname)) + return FALSE; + + /* We require at least 2 dots in the pattern to avoid too wide wildcard + match. */ + pattern_label_end = memchr(pattern, '.', patternlen); + if(!pattern_label_end || +- (memrchr(pattern, '.', patternlen) == pattern_label_end) || +- strncasecompare(pattern, "xn--", 4)) ++ (memrchr(pattern, '.', patternlen) == pattern_label_end)) + return pmatch(hostname, hostlen, pattern, patternlen); +- +- hostname_label_end = memchr(hostname, '.', hostlen); +- if(!hostname_label_end) +- return FALSE; + else { +- size_t skiphost = hostname_label_end - hostname; +- size_t skiplen = pattern_label_end - pattern; +- if(!pmatch(hostname_label_end, hostlen - skiphost, +- pattern_label_end, patternlen - skiplen)) +- return FALSE; ++ const char *hostname_label_end = memchr(hostname, '.', hostlen); ++ if(hostname_label_end) { ++ size_t skiphost = hostname_label_end - hostname; ++ size_t skiplen = pattern_label_end - pattern; ++ return pmatch(hostname_label_end, hostlen - skiphost, ++ pattern_label_end, patternlen - skiplen); ++ } + } +- /* The wildcard must match at least one character, so the left-most +- label of the hostname is at least as large as the left-most label +- of the pattern. */ +- if(hostname_label_end - hostname < pattern_label_end - pattern) +- return FALSE; +- +- prefixlen = wildcard - pattern; +- suffixlen = pattern_label_end - (wildcard + 1); +- return strncasecompare(pattern, hostname, prefixlen) && +- strncasecompare(wildcard + 1, hostname_label_end - suffixlen, +- suffixlen) ? TRUE : FALSE; ++ return FALSE; + } + + /* +diff --git a/tests/data/test1397 b/tests/data/test1397 +index 84f962abe..f31b2c2a3 100644 +--- a/tests/data/test1397 ++++ b/tests/data/test1397 +@@ -2,8 +2,7 @@ + + + unittest +-ssl +-wildcard ++Curl_cert_hostcheck + + + +@@ -16,9 +15,8 @@ none + + unittest + +- +-Check wildcard certificate matching function Curl_cert_hostcheck +- ++ ++Curl_cert_hostcheck unit tests ++ + +- + +diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am +index 4f64ff596..e7a6aa452 100644 +--- a/tests/unit/Makefile.am ++++ b/tests/unit/Makefile.am +@@ -67,91 +67,3 @@ noinst_PROGRAMS = $(UNITPROGS) + else + noinst_PROGRAMS = + endif +- +-unit1300_SOURCES = unit1300.c $(UNITFILES) +- +-unit1302_SOURCES = unit1302.c $(UNITFILES) +- +-unit1303_SOURCES = unit1303.c $(UNITFILES) +- +-unit1304_SOURCES = unit1304.c $(UNITFILES) +- +-unit1305_SOURCES = unit1305.c $(UNITFILES) +- +-unit1307_SOURCES = unit1307.c $(UNITFILES) +- +-unit1308_SOURCES = unit1308.c $(UNITFILES) +- +-unit1309_SOURCES = unit1309.c $(UNITFILES) +- +-unit1323_SOURCES = unit1323.c $(UNITFILES) +- +-unit1330_SOURCES = unit1330.c $(UNITFILES) +- +-unit1394_SOURCES = unit1394.c $(UNITFILES) +-unit1394_LDADD = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ +-unit1394_LDFLAGS = $(top_builddir)/src/libcurltool.la +-unit1394_LIBS = +- +-unit1395_SOURCES = unit1395.c $(UNITFILES) +- +-unit1396_SOURCES = unit1396.c $(UNITFILES) +- +-unit1397_SOURCES = unit1397.c $(UNITFILES) +- +-unit1398_SOURCES = unit1398.c $(UNITFILES) +- +-unit1399_SOURCES = unit1399.c $(UNITFILES) +- +-unit1600_SOURCES = unit1600.c $(UNITFILES) +- +-unit1601_SOURCES = unit1601.c $(UNITFILES) +- +-unit1602_SOURCES = unit1602.c $(UNITFILES) +- +-unit1603_SOURCES = unit1603.c $(UNITFILES) +- +-unit1604_SOURCES = unit1604.c $(UNITFILES) +- +-unit1605_SOURCES = unit1605.c $(UNITFILES) +- +-unit1606_SOURCES = unit1606.c $(UNITFILES) +- +-unit1607_SOURCES = unit1607.c $(UNITFILES) +- +-unit1608_SOURCES = unit1608.c $(UNITFILES) +- +-unit1609_SOURCES = unit1609.c $(UNITFILES) +- +-unit1610_SOURCES = unit1610.c $(UNITFILES) +- +-unit1611_SOURCES = unit1611.c $(UNITFILES) +- +-unit1612_SOURCES = unit1612.c $(UNITFILES) +- +-unit1614_SOURCES = unit1614.c $(UNITFILES) +- +-unit1620_SOURCES = unit1620.c $(UNITFILES) +- +-unit1621_SOURCES = unit1621.c $(UNITFILES) +-unit1621_LDADD = $(top_builddir)/src/libcurltool.la $(top_builddir)/lib/libcurl.la @NSS_LIBS@ +- +-unit1650_SOURCES = unit1650.c $(UNITFILES) +- +-unit1651_SOURCES = unit1651.c $(UNITFILES) +- +-unit1652_SOURCES = unit1652.c $(UNITFILES) +- +-unit1653_SOURCES = unit1653.c $(UNITFILES) +- +-unit1654_SOURCES = unit1654.c $(UNITFILES) +- +-unit1655_SOURCES = unit1655.c $(UNITFILES) +- +-unit1660_SOURCES = unit1660.c $(UNITFILES) +- +-unit1661_SOURCES = unit1661.c $(UNITFILES) +- +-unit2600_SOURCES = unit2600.c $(UNITFILES) +- +-unit3200_SOURCES = unit3200.c $(UNITFILES) +diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc +index 4ab15b5db..20a9963d1 100644 +--- a/tests/unit/Makefile.inc ++++ b/tests/unit/Makefile.inc +@@ -40,3 +40,97 @@ UNITPROGS = unit1300 unit1302 unit1303 unit1304 unit1305 unit1307 \ + unit1660 unit1661 \ + unit2600 \ + unit3200 ++ ++unit1300_SOURCES = unit1300.c $(UNITFILES) ++ ++unit1302_SOURCES = unit1302.c $(UNITFILES) ++ ++unit1303_SOURCES = unit1303.c $(UNITFILES) ++ ++unit1304_SOURCES = unit1304.c $(UNITFILES) ++ ++unit1305_SOURCES = unit1305.c $(UNITFILES) ++ ++unit1307_SOURCES = unit1307.c $(UNITFILES) ++ ++unit1308_SOURCES = unit1308.c $(UNITFILES) ++ ++unit1309_SOURCES = unit1309.c $(UNITFILES) ++ ++unit1323_SOURCES = unit1323.c $(UNITFILES) ++ ++unit1330_SOURCES = unit1330.c $(UNITFILES) ++ ++unit1394_SOURCES = unit1394.c $(UNITFILES) ++unit1394_LDADD = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ ++unit1394_LDFLAGS = $(top_builddir)/src/libcurltool.la ++unit1394_LIBS = ++ ++unit1395_SOURCES = unit1395.c $(UNITFILES) ++ ++unit1396_SOURCES = unit1396.c $(UNITFILES) ++ ++unit1397_SOURCES = unit1397.c $(UNITFILES) ++ ++unit1398_SOURCES = unit1398.c $(UNITFILES) ++ ++unit1399_SOURCES = unit1399.c $(UNITFILES) ++ ++unit1600_SOURCES = unit1600.c $(UNITFILES) ++ ++unit1601_SOURCES = unit1601.c $(UNITFILES) ++ ++unit1602_SOURCES = unit1602.c $(UNITFILES) ++ ++unit1603_SOURCES = unit1603.c $(UNITFILES) ++ ++unit1604_SOURCES = unit1604.c $(UNITFILES) ++ ++unit1605_SOURCES = unit1605.c $(UNITFILES) ++ ++unit1606_SOURCES = unit1606.c $(UNITFILES) ++ ++unit1607_SOURCES = unit1607.c $(UNITFILES) ++ ++unit1608_SOURCES = unit1608.c $(UNITFILES) ++ ++unit1609_SOURCES = unit1609.c $(UNITFILES) ++ ++unit1610_SOURCES = unit1610.c $(UNITFILES) ++ ++unit1611_SOURCES = unit1611.c $(UNITFILES) ++ ++unit1612_SOURCES = unit1612.c $(UNITFILES) ++ ++unit1614_SOURCES = unit1614.c $(UNITFILES) ++ ++unit1620_SOURCES = unit1620.c $(UNITFILES) ++ ++unit1621_SOURCES = unit1621.c $(UNITFILES) ++unit1621_LDADD = $(top_builddir)/src/libcurltool.la $(top_builddir)/lib/libcurl.la @NSS_LIBS@ ++ ++unit1650_SOURCES = unit1650.c $(UNITFILES) ++ ++unit1651_SOURCES = unit1651.c $(UNITFILES) ++ ++unit1652_SOURCES = unit1652.c $(UNITFILES) ++ ++unit1653_SOURCES = unit1653.c $(UNITFILES) ++ ++unit1654_SOURCES = unit1654.c $(UNITFILES) ++ ++unit1655_SOURCES = unit1655.c $(UNITFILES) ++ ++unit1660_SOURCES = unit1660.c $(UNITFILES) ++ ++unit1661_SOURCES = unit1661.c $(UNITFILES) ++ ++unit2600_SOURCES = unit2600.c $(UNITFILES) ++ ++unit2601_SOURCES = unit2601.c $(UNITFILES) ++ ++unit2602_SOURCES = unit2602.c $(UNITFILES) ++ ++unit2603_SOURCES = unit2603.c $(UNITFILES) ++ ++unit3200_SOURCES = unit3200.c $(UNITFILES) +diff --git a/tests/unit/unit1397.c b/tests/unit/unit1397.c +index 2f3d3aa4d..3ae75618d 100644 +--- a/tests/unit/unit1397.c ++++ b/tests/unit/unit1397.c +@@ -23,7 +23,6 @@ + ***************************************************************************/ + #include "curlcheck.h" + +-#include "vtls/hostcheck.h" /* from the lib dir */ + + static CURLcode unit_setup(void) + { +@@ -32,63 +31,94 @@ static CURLcode unit_setup(void) + + static void unit_stop(void) + { +- /* done before shutting down and exiting */ + } + +-UNITTEST_START +- + /* only these backends define the tested functions */ +-#if defined(USE_OPENSSL) || defined(USE_GSKIT) +- +- /* here you start doing things and checking that the results are good */ ++#if defined(USE_OPENSSL) || defined(USE_GSKIT) || defined(USE_SCHANNEL) ++#include "vtls/hostcheck.h" ++struct testcase { ++ const char *host; ++ const char *pattern; ++ bool match; ++}; + +-fail_unless(Curl_cert_hostcheck(STRCONST("www.example.com"), +- STRCONST("www.example.com")), "good 1"); +-fail_unless(Curl_cert_hostcheck(STRCONST("*.example.com"), +- STRCONST("www.example.com")), +- "good 2"); +-fail_unless(Curl_cert_hostcheck(STRCONST("xxx*.example.com"), +- STRCONST("xxxwww.example.com")), "good 3"); +-fail_unless(Curl_cert_hostcheck(STRCONST("f*.example.com"), +- STRCONST("foo.example.com")), "good 4"); +-fail_unless(Curl_cert_hostcheck(STRCONST("192.168.0.0"), +- STRCONST("192.168.0.0")), "good 5"); ++static struct testcase tests[] = { ++ {"", "", FALSE}, ++ {"a", "", FALSE}, ++ {"", "b", FALSE}, ++ {"a", "b", FALSE}, ++ {"aa", "bb", FALSE}, ++ {"\xff", "\xff", TRUE}, ++ {"aa.aa.aa", "aa.aa.bb", FALSE}, ++ {"aa.aa.aa", "aa.aa.aa", TRUE}, ++ {"aa.aa.aa", "*.aa.bb", FALSE}, ++ {"aa.aa.aa", "*.aa.aa", TRUE}, ++ {"192.168.0.1", "192.168.0.1", TRUE}, ++ {"192.168.0.1", "*.168.0.1", FALSE}, ++ {"192.168.0.1", "*.0.1", FALSE}, ++ {"h.ello", "*.ello", FALSE}, ++ {"h.ello.", "*.ello", FALSE}, ++ {"h.ello", "*.ello.", FALSE}, ++ {"h.e.llo", "*.e.llo", TRUE}, ++ {"h.e.llo", " *.e.llo", FALSE}, ++ {" h.e.llo", "*.e.llo", TRUE}, ++ {"h.e.llo.", "*.e.llo", TRUE}, ++ {"*.e.llo.", "*.e.llo", TRUE}, ++ {"************.e.llo.", "*.e.llo", TRUE}, ++ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ++ "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" ++ "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" ++ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" ++ "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" ++ ".e.llo.", "*.e.llo", TRUE}, ++ {"\xfe\xfe.e.llo.", "*.e.llo", TRUE}, ++ {"h.e.llo.", "*.e.llo.", TRUE}, ++ {"h.e.llo", "*.e.llo.", TRUE}, ++ {".h.e.llo", "*.e.llo.", FALSE}, ++ {"h.e.llo", "*.*.llo.", FALSE}, ++ {"h.e.llo", "h.*.llo", FALSE}, ++ {"h.e.llo", "h.e.*", FALSE}, ++ {"hello", "*.ello", FALSE}, ++ {"hello", "**llo", FALSE}, ++ {"bar.foo.example.com", "*.example.com", FALSE}, ++ {"foo.example.com", "*.example.com", TRUE}, ++ {"baz.example.net", "b*z.example.net", FALSE}, ++ {"foobaz.example.net", "*baz.example.net", FALSE}, ++ {"xn--l8j.example.local", "x*.example.local", FALSE}, ++ {"xn--l8j.example.net", "*.example.net", TRUE}, ++ {"xn--l8j.example.net", "*j.example.net", FALSE}, ++ {"xn--l8j.example.net", "xn--l8j.example.net", TRUE}, ++ {"xn--l8j.example.net", "xn--l8j.*.net", FALSE}, ++ {"xl8j.example.net", "*.example.net", TRUE}, ++ {"fe80::3285:a9ff:fe46:b619", "*::3285:a9ff:fe46:b619", FALSE}, ++ {"fe80::3285:a9ff:fe46:b619", "fe80::3285:a9ff:fe46:b619", TRUE}, ++ {NULL, NULL, FALSE} ++}; + +-fail_if(Curl_cert_hostcheck(STRCONST("xxx.example.com"), +- STRCONST("www.example.com")), "bad 1"); +-fail_if(Curl_cert_hostcheck(STRCONST("*"), +- STRCONST("www.example.com")),"bad 2"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.*.com"), +- STRCONST("www.example.com")), "bad 3"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.example.com"), +- STRCONST("baa.foo.example.com")), "bad 4"); +-fail_if(Curl_cert_hostcheck(STRCONST("f*.example.com"), +- STRCONST("baa.example.com")), "bad 5"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.com"), +- STRCONST("example.com")), "bad 6"); +-fail_if(Curl_cert_hostcheck(STRCONST("*fail.com"), +- STRCONST("example.com")), "bad 7"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.example."), +- STRCONST("www.example.")), "bad 8"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.example."), +- STRCONST("www.example")), "bad 9"); +-fail_if(Curl_cert_hostcheck(STRCONST(""), STRCONST("www")), "bad 10"); +-fail_if(Curl_cert_hostcheck(STRCONST("*"), STRCONST("www")), "bad 11"); +-fail_if(Curl_cert_hostcheck(STRCONST("*.168.0.0"), +- STRCONST("192.168.0.0")), "bad 12"); +-fail_if(Curl_cert_hostcheck(STRCONST("www.example.com"), +- STRCONST("192.168.0.0")), "bad 13"); +- +-#ifdef ENABLE_IPV6 +-fail_if(Curl_cert_hostcheck(STRCONST("*::3285:a9ff:fe46:b619"), +- STRCONST("fe80::3285:a9ff:fe46:b619")), "bad 14"); +-fail_unless(Curl_cert_hostcheck(STRCONST("fe80::3285:a9ff:fe46:b619"), +- STRCONST("fe80::3285:a9ff:fe46:b619")), +- "good 6"); +-#endif ++UNITTEST_START ++{ ++ int i; ++ for(i = 0; tests[i].host; i++) { ++ if(tests[i].match != Curl_cert_hostcheck(tests[i].pattern, ++ strlen(tests[i].pattern), ++ tests[i].host, ++ strlen(tests[i].host))) { ++ fprintf(stderr, ++ "HOST: %s\n" ++ "PTRN: %s\n" ++ "did %sMATCH\n", ++ tests[i].host, ++ tests[i].pattern, ++ tests[i].match ? "NOT ": ""); ++ unitfail++; ++ } ++ } ++} + +-#endif ++UNITTEST_STOP ++#else + +- /* you end the test code like this: */ ++UNITTEST_START + + UNITTEST_STOP ++#endif +-- +2.40.1 + diff --git a/0003-curl-8.0.1-CVE-2023-32001.patch b/0003-curl-8.0.1-CVE-2023-32001.patch new file mode 100644 index 0000000..eaa9d8f --- /dev/null +++ b/0003-curl-8.0.1-CVE-2023-32001.patch @@ -0,0 +1,40 @@ +From 98474a7848e20716935f471f4e48610b00fe9dc0 Mon Sep 17 00:00:00 2001 +From: SaltyMilk +Date: Mon, 10 Jul 2023 21:43:28 +0200 +Subject: [PATCH] fopen: optimize + +Closes #11419 + +(cherry picked from commit 0c667188e0c6cda615a036b8a2b4125f2c404dde) +Signed-off-by: Jan Macku +--- + lib/fopen.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index f710dbf05..8c728f2a8 100644 +--- a/lib/fopen.c ++++ b/lib/fopen.c +@@ -56,13 +56,13 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + int fd = -1; + *tempname = NULL; + +- if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) { +- /* a non-regular file, fallback to direct fopen() */ +- *fh = fopen(filename, FOPEN_WRITETEXT); +- if(*fh) +- return CURLE_OK; ++ *fh = fopen(filename, FOPEN_WRITETEXT); ++ if(!*fh) + goto fail; +- } ++ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) ++ return CURLE_OK; ++ fclose(*fh); ++ *fh = NULL; + + result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix)); + if(result) +-- +2.41.0 + diff --git a/0004-curl-8.0.1-CVE-2023-38039.patch b/0004-curl-8.0.1-CVE-2023-38039.patch new file mode 100644 index 0000000..dc63e75 --- /dev/null +++ b/0004-curl-8.0.1-CVE-2023-38039.patch @@ -0,0 +1,201 @@ +From fe13e206a80cee9ffa686ead170980dbdb2cf9e1 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 2 Aug 2023 23:34:48 +0200 +Subject: [PATCH] http: return error when receiving too large header set + +To avoid abuse. The limit is set to 300 KB for the accumulated size of +all received HTTP headers for a single response. Incomplete research +suggests that Chrome uses a 256-300 KB limit, while Firefox allows up to +1MB. + +Closes #11582 + +(cherry picked from commit 3ee79c1674fd6f99e8efca52cd7510e08b766770) +Signed-off-by: Jan Macku +--- + lib/c-hyper.c | 12 +++++++----- + lib/http.c | 34 ++++++++++++++++++++++++++++++---- + lib/http.h | 9 +++++++++ + lib/pingpong.c | 4 +++- + lib/urldata.h | 17 ++++++++--------- + 5 files changed, 57 insertions(+), 19 deletions(-) + +diff --git a/lib/c-hyper.c b/lib/c-hyper.c +index 9c7632d35..28f64ef97 100644 +--- a/lib/c-hyper.c ++++ b/lib/c-hyper.c +@@ -174,8 +174,11 @@ static int hyper_each_header(void *userdata, + } + } + +- data->info.header_size += (curl_off_t)len; +- data->req.headerbytecount += (curl_off_t)len; ++ result = Curl_bump_headersize(data, len, FALSE); ++ if(result) { ++ data->state.hresult = result; ++ return HYPER_ITER_BREAK; ++ } + return HYPER_ITER_CONTINUE; + } + +@@ -305,9 +308,8 @@ static CURLcode status_line(struct Curl_easy *data, + if(result) + return result; + } +- data->info.header_size += (curl_off_t)len; +- data->req.headerbytecount += (curl_off_t)len; +- return CURLE_OK; ++ result = Curl_bump_headersize(data, len, FALSE); ++ return result; + } + + /* +diff --git a/lib/http.c b/lib/http.c +index 400d2b081..d8c3e1eda 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -3760,6 +3760,29 @@ static CURLcode verify_header(struct Curl_easy *data) + return CURLE_OK; + } + ++CURLcode Curl_bump_headersize(struct Curl_easy *data, ++ size_t delta, ++ bool connect_only) ++{ ++ size_t bad = 0; ++ if(delta < MAX_HTTP_RESP_HEADER_SIZE) { ++ if(!connect_only) ++ data->req.headerbytecount += (unsigned int)delta; ++ data->info.header_size += (unsigned int)delta; ++ if(data->info.header_size > MAX_HTTP_RESP_HEADER_SIZE) ++ bad = data->info.header_size; ++ } ++ else ++ bad = data->info.header_size + delta; ++ if(bad) { ++ failf(data, "Too large response headers: %zu > %zu", ++ bad, MAX_HTTP_RESP_HEADER_SIZE); ++ return CURLE_RECV_ERROR; ++ } ++ return CURLE_OK; ++} ++ ++ + /* + * Read any HTTP header lines from the server and pass them to the client app. + */ +@@ -4007,8 +4030,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + if(result) + return result; + +- data->info.header_size += (long)headerlen; +- data->req.headerbytecount += (long)headerlen; ++ result = Curl_bump_headersize(data, headerlen, FALSE); ++ if(result) ++ return result; + + /* + * When all the headers have been parsed, see if we should give +@@ -4330,8 +4354,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + if(result) + return result; + +- data->info.header_size += Curl_dyn_len(&data->state.headerb); +- data->req.headerbytecount += Curl_dyn_len(&data->state.headerb); ++ result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb), ++ FALSE); ++ if(result) ++ return result; + + Curl_dyn_reset(&data->state.headerb); + } +diff --git a/lib/http.h b/lib/http.h +index 444abc0be..b29f3b84f 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -61,6 +61,10 @@ extern const struct Curl_handler Curl_handler_wss; + #endif /* websockets */ + + ++CURLcode Curl_bump_headersize(struct Curl_easy *data, ++ size_t delta, ++ bool connect_only); ++ + /* Header specific functions */ + bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ +@@ -176,6 +180,11 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data); + #define EXPECT_100_THRESHOLD (1024*1024) + #endif + ++/* MAX_HTTP_RESP_HEADER_SIZE is the maximum size of all response headers ++ combined that libcurl allows for a single HTTP response, any HTTP ++ version. This count includes CONNECT response headers. */ ++#define MAX_HTTP_RESP_HEADER_SIZE (300*1024) ++ + #endif /* CURL_DISABLE_HTTP */ + + #ifdef USE_NGHTTP3 +diff --git a/lib/pingpong.c b/lib/pingpong.c +index 2f4aa1c34..189a0b68e 100644 +--- a/lib/pingpong.c ++++ b/lib/pingpong.c +@@ -341,7 +341,9 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data, + ssize_t clipamount = 0; + bool restart = FALSE; + +- data->req.headerbytecount += (long)gotbytes; ++ result = Curl_bump_headersize(data, gotbytes, FALSE); ++ if(result) ++ return result; + + pp->nread_resp += gotbytes; + for(i = 0; i < gotbytes; ptr++, i++) { +diff --git a/lib/urldata.h b/lib/urldata.h +index f3e782ad3..390c611e2 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -619,17 +619,16 @@ struct SingleRequest { + curl_off_t bytecount; /* total number of bytes read */ + curl_off_t writebytecount; /* number of bytes written */ + +- curl_off_t headerbytecount; /* only count received headers */ +- curl_off_t deductheadercount; /* this amount of bytes doesn't count when we +- check if anything has been transferred at +- the end of a connection. We use this +- counter to make only a 100 reply (without a +- following second response code) result in a +- CURLE_GOT_NOTHING error code */ +- + curl_off_t pendingheader; /* this many bytes left to send is actually + header and not body */ + struct curltime start; /* transfer started at this time */ ++ unsigned int headerbytecount; /* only count received headers */ ++ unsigned int deductheadercount; /* this amount of bytes doesn't count when ++ we check if anything has been transferred ++ at the end of a connection. We use this ++ counter to make only a 100 reply (without ++ a following second response code) result ++ in a CURLE_GOT_NOTHING error code */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest +@@ -1076,7 +1075,6 @@ struct PureInfo { + int httpversion; /* the http version number X.Y = X*10+Y */ + time_t filetime; /* If requested, this is might get set. Set to -1 if the + time was unretrievable. */ +- curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ + unsigned long proxyauthavail; /* what proxy auth types were announced */ + unsigned long httpauthavail; /* what host auth types were announced */ +@@ -1084,6 +1082,7 @@ struct PureInfo { + char *contenttype; /* the content type of the object */ + char *wouldredirect; /* URL this would've been redirected to if asked to */ + curl_off_t retry_after; /* info from Retry-After: header */ ++ unsigned int header_size; /* size of read header(s) in bytes */ + + /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' + and, 'conn_local_port' are copied over from the connectdata struct in +-- +2.41.0 + diff --git a/0005-curl-8.0.1-CVE-2023-38545.patch b/0005-curl-8.0.1-CVE-2023-38545.patch new file mode 100644 index 0000000..7b06ee4 --- /dev/null +++ b/0005-curl-8.0.1-CVE-2023-38545.patch @@ -0,0 +1,135 @@ +From fa4aed65588db8e7c7e3d98f6c5bcf394f3a515d Mon Sep 17 00:00:00 2001 +From: Jay Satiro +Date: Wed, 11 Oct 2023 07:34:19 +0200 +Subject: [PATCH 1/2] socks: return error if hostname too long for remote + resolve + +Prior to this change the state machine attempted to change the remote +resolve to a local resolve if the hostname was longer than 255 +characters. Unfortunately that did not work as intended and caused a +security issue. + +Bug: https://curl.se/docs/CVE-2023-38545.html + +(cherry picked from commit fb4415d8aee6c1045be932a34fe6107c2f5ed147) + +Signed-off-by: Jan Macku +--- + lib/socks.c | 8 +++--- + tests/data/Makefile.inc | 2 +- + tests/data/test728 | 64 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+), 5 deletions(-) + create mode 100644 tests/data/test728 + +diff --git a/lib/socks.c b/lib/socks.c +index 95c2b004c..8cf694d1d 100644 +--- a/lib/socks.c ++++ b/lib/socks.c +@@ -588,9 +588,9 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, + + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ + if(!socks5_resolve_local && hostname_len > 255) { +- infof(data, "SOCKS5: server resolving disabled for hostnames of " +- "length > 255 [actual len=%zu]", hostname_len); +- socks5_resolve_local = TRUE; ++ failf(data, "SOCKS5: the destination hostname is too long to be " ++ "resolved remotely by the proxy."); ++ return CURLPX_LONG_HOSTNAME; + } + + if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) +@@ -904,7 +904,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, + } + else { + socksreq[len++] = 3; +- socksreq[len++] = (char) hostname_len; /* one byte address length */ ++ socksreq[len++] = (unsigned char) hostname_len; /* one byte length */ + memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */ + len += hostname_len; + } +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 7ed03a247..eb89437ef 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -100,7 +100,7 @@ test679 test680 test681 test682 test683 test684 test685 test686 \ + \ + test700 test701 test702 test703 test704 test705 test706 test707 test708 \ + test709 test710 test711 test712 test713 test714 test715 test716 test717 \ +-test718 test719 test720 test721 \ ++test718 test719 test720 test721 test728 \ + \ + test800 test801 test802 test803 test804 test805 test806 test807 test808 \ + test809 test810 test811 test812 test813 test814 test815 test816 test817 \ +diff --git a/tests/data/test728 b/tests/data/test728 +new file mode 100644 +index 000000000..05bcf2883 +--- /dev/null ++++ b/tests/data/test728 +@@ -0,0 +1,64 @@ ++ ++ ++ ++HTTP ++HTTP GET ++SOCKS5 ++SOCKS5h ++followlocation ++ ++ ++ ++# ++# Server-side ++ ++# The hostname in this redirect is 256 characters and too long (> 255) for ++# SOCKS5 remote resolve. curl must return error CURLE_PROXY in this case. ++ ++HTTP/1.1 301 Moved Permanently ++Location: http://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/ ++Content-Length: 0 ++Connection: close ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++proxy ++ ++ ++http ++socks5 ++ ++ ++SOCKS5h with HTTP redirect to hostname too long ++ ++ ++--no-progress-meter --location --proxy socks5h://%HOSTIP:%SOCKSPORT http://%HOSTIP:%HTTPPORT/%TESTNUMBER ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++User-Agent: curl/%VERSION ++Accept: */* ++ ++ ++ ++97 ++ ++# the error message is verified because error code CURLE_PROXY (97) may be ++# returned for any number of reasons and we need to make sure it is ++# specifically for the reason below so that we know the check is working. ++ ++curl: (97) SOCKS5: the destination hostname is too long to be resolved remotely by the proxy. ++ ++ ++ +-- +2.41.0 + diff --git a/0006-curl-8.0.1-CVE-2023-38546.patch b/0006-curl-8.0.1-CVE-2023-38546.patch new file mode 100644 index 0000000..111f0d3 --- /dev/null +++ b/0006-curl-8.0.1-CVE-2023-38546.patch @@ -0,0 +1,136 @@ +From a9a3f49fc87d4b64f380e19d69c139e9fba676f2 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 14 Sep 2023 23:28:32 +0200 +Subject: [PATCH 2/2] cookie: remove unnecessary struct fields + +Plus: reduce the hash table size from 256 to 63. It seems unlikely to +make much of a speed difference for most use cases but saves 1.5KB of +data per instance. + +Closes #11862 + +(cherry picked from commit 61275672b46d9abb3285740467b882e22ed75da8) + +Signed-off-by: Jan Macku +--- + lib/cookie.c | 13 +------------ + lib/cookie.h | 14 ++++---------- + lib/easy.c | 4 +--- + 3 files changed, 6 insertions(+), 25 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index 0c6e0f7cd..d34620351 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -119,7 +119,6 @@ static void freecookie(struct Cookie *co) + free(co->name); + free(co->value); + free(co->maxage); +- free(co->version); + free(co); + } + +@@ -726,11 +725,7 @@ Curl_cookie_add(struct Curl_easy *data, + } + } + else if((nlen == 7) && strncasecompare("version", namep, 7)) { +- strstore(&co->version, valuep, vlen); +- if(!co->version) { +- badcookie = TRUE; +- break; +- } ++ /* just ignore */ + } + else if((nlen == 7) && strncasecompare("max-age", namep, 7)) { + /* +@@ -1174,7 +1169,6 @@ Curl_cookie_add(struct Curl_easy *data, + free(clist->path); + free(clist->spath); + free(clist->expirestr); +- free(clist->version); + free(clist->maxage); + + *clist = *co; /* then store all the new data */ +@@ -1238,9 +1232,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + c = calloc(1, sizeof(struct CookieInfo)); + if(!c) + return NULL; /* failed to get memory */ +- c->filename = strdup(file?file:"none"); /* copy the name just in case */ +- if(!c->filename) +- goto fail; /* failed to get memory */ + /* + * Initialize the next_expiration time to signal that we don't have enough + * information yet. +@@ -1394,7 +1385,6 @@ static struct Cookie *dup_cookie(struct Cookie *src) + CLONE(name); + CLONE(value); + CLONE(maxage); +- CLONE(version); + d->expires = src->expires; + d->tailmatch = src->tailmatch; + d->secure = src->secure; +@@ -1611,7 +1601,6 @@ void Curl_cookie_cleanup(struct CookieInfo *c) + { + if(c) { + unsigned int i; +- free(c->filename); + for(i = 0; i < COOKIE_HASH_SIZE; i++) + Curl_cookie_freelist(c->cookies[i]); + free(c); /* free the base struct as well */ +diff --git a/lib/cookie.h b/lib/cookie.h +index 39bb08bc4..3a43bbf33 100644 +--- a/lib/cookie.h ++++ b/lib/cookie.h +@@ -36,11 +36,7 @@ struct Cookie { + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ +- +- /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ +- char *version; /* Version = */ + char *maxage; /* Max-Age = */ +- + bool tailmatch; /* whether we do tail-matching of the domain name */ + bool secure; /* whether the 'secure' keyword was used */ + bool livecookie; /* updated from a server, not a stored file */ +@@ -56,18 +52,16 @@ struct Cookie { + #define COOKIE_PREFIX__SECURE (1<<0) + #define COOKIE_PREFIX__HOST (1<<1) + +-#define COOKIE_HASH_SIZE 256 ++#define COOKIE_HASH_SIZE 63 + + struct CookieInfo { + /* linked list of cookies we know of */ + struct Cookie *cookies[COOKIE_HASH_SIZE]; +- +- char *filename; /* file we read from/write to */ +- long numcookies; /* number of cookies in the "jar" */ ++ curl_off_t next_expiration; /* the next time at which expiration happens */ ++ int numcookies; /* number of cookies in the "jar" */ ++ int lastct; /* last creation-time used in the jar */ + bool running; /* state info, for cookie adding information */ + bool newsession; /* new session, discard session cookies on load */ +- int lastct; /* last creation-time used in the jar */ +- curl_off_t next_expiration; /* the next time at which expiration happens */ + }; + + /* This is the maximum line length we accept for a cookie line. RFC 2109 +diff --git a/lib/easy.c b/lib/easy.c +index 27124a72f..fddf047f2 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -911,9 +911,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ +- outcurl->cookies = Curl_cookie_init(data, +- data->cookies->filename, +- outcurl->cookies, ++ outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; +-- +2.41.0 + diff --git a/0007-curl-8.0.1-CVE-2023-46218.patch b/0007-curl-8.0.1-CVE-2023-46218.patch new file mode 100644 index 0000000..1494a41 --- /dev/null +++ b/0007-curl-8.0.1-CVE-2023-46218.patch @@ -0,0 +1,55 @@ +From ef4abe34b2b704e2a318063b387b628773b78663 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 23 Nov 2023 08:15:47 +0100 +Subject: [PATCH 1/2] cookie: lowercase the domain names before PSL checks + +Reported-by: Harry Sintonen + +Closes #12387 + +(cherry picked from commit 2b0994c29a721c91c572cff7808c572a24d251eb) + +Signed-off-by: Jan Macku +--- + lib/cookie.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index d34620351..730c3c6f4 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -1044,15 +1044,23 @@ Curl_cookie_add(struct Curl_easy *data, + * dereference it. + */ + if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) { +- const psl_ctx_t *psl = Curl_psl_use(data); +- int acceptable; +- +- if(psl) { +- acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); +- Curl_psl_release(data); ++ bool acceptable = FALSE; ++ char lcase[256]; ++ char lcookie[256]; ++ size_t dlen = strlen(domain); ++ size_t clen = strlen(co->domain); ++ if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) { ++ const psl_ctx_t *psl = Curl_psl_use(data); ++ if(psl) { ++ /* the PSL check requires lowercase domain name and pattern */ ++ Curl_strntolower(lcase, domain, dlen + 1); ++ Curl_strntolower(lcookie, co->domain, clen + 1); ++ acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie); ++ Curl_psl_release(data); ++ } ++ else ++ acceptable = !bad_domain(domain, strlen(domain)); + } +- else +- acceptable = !bad_domain(domain, strlen(domain)); + + if(!acceptable) { + infof(data, "cookie '%s' dropped, domain '%s' must not " +-- +2.43.0 + diff --git a/0008-curl-8.0.1-CVE-2023-46219.patch b/0008-curl-8.0.1-CVE-2023-46219.patch new file mode 100644 index 0000000..08c4938 --- /dev/null +++ b/0008-curl-8.0.1-CVE-2023-46219.patch @@ -0,0 +1,134 @@ +From 45ed144efd8b194cc7d0acbe00594f730a2ad62d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 23 Nov 2023 08:23:17 +0100 +Subject: [PATCH 2/2] fopen: create short(er) temporary file name + +Only using random letters in the name plus a ".tmp" extension. Not by +appending characters to the final file name. + +Reported-by: Maksymilian Arciemowicz + +Closes #12388 + +(cherry picked from commit 73b65e94f3531179de45c6f3c836a610e3d0a846) + +Signed-off-by: Jan Macku +--- + lib/fopen.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 60 insertions(+), 5 deletions(-) + +diff --git a/lib/fopen.c b/lib/fopen.c +index 8c728f2a8..7b9d4022e 100644 +--- a/lib/fopen.c ++++ b/lib/fopen.c +@@ -39,6 +39,51 @@ + #include "curl_memory.h" + #include "memdebug.h" + ++/* ++ The dirslash() function breaks a null-terminated pathname string into ++ directory and filename components then returns the directory component up ++ to, *AND INCLUDING*, a final '/'. If there is no directory in the path, ++ this instead returns a "" string. ++ ++ This function returns a pointer to malloc'ed memory. ++ ++ The input path to this function is expected to have a file name part. ++*/ ++ ++#ifdef _WIN32 ++#define PATHSEP "\\" ++#define IS_SEP(x) (((x) == '/') || ((x) == '\\')) ++#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) ++#define PATHSEP "\\" ++#define IS_SEP(x) ((x) == '\\') ++#else ++#define PATHSEP "/" ++#define IS_SEP(x) ((x) == '/') ++#endif ++ ++static char *dirslash(const char *path) ++{ ++ size_t n; ++ struct dynbuf out; ++ DEBUGASSERT(path); ++ Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH); ++ n = strlen(path); ++ if(n) { ++ /* find the rightmost path separator, if any */ ++ while(n && !IS_SEP(path[n-1])) ++ --n; ++ /* skip over all the path separators, if any */ ++ while(n && IS_SEP(path[n-1])) ++ --n; ++ } ++ if(Curl_dyn_addn(&out, path, n)) ++ return NULL; ++ /* if there was a directory, append a single trailing slash */ ++ if(n && Curl_dyn_addn(&out, PATHSEP, 1)) ++ return NULL; ++ return Curl_dyn_ptr(&out); ++} ++ + /* + * Curl_fopen() opens a file for writing with a temp name, to be renamed + * to the final name when completed. If there is an existing file using this +@@ -50,25 +95,34 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + FILE **fh, char **tempname) + { + CURLcode result = CURLE_WRITE_ERROR; +- unsigned char randsuffix[9]; ++ unsigned char randbuf[41]; + char *tempstore = NULL; + struct_stat sb; + int fd = -1; ++ char *dir; + *tempname = NULL; + ++ dir = dirslash(filename); ++ if(!dir) ++ goto fail; ++ + *fh = fopen(filename, FOPEN_WRITETEXT); + if(!*fh) + goto fail; +- if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) ++ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) { ++ free(dir); + return CURLE_OK; ++ } + fclose(*fh); + *fh = NULL; + +- result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix)); ++ result = Curl_rand_hex(data, randbuf, sizeof(randbuf)); + if(result) + goto fail; + +- tempstore = aprintf("%s.%s.tmp", filename, randsuffix); ++ /* The temp file name should not end up too long for the target file ++ system */ ++ tempstore = aprintf("%s%s.tmp", dir, randbuf); + if(!tempstore) { + result = CURLE_OUT_OF_MEMORY; + goto fail; +@@ -95,6 +149,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, + if(!*fh) + goto fail; + ++ free(dir); + *tempname = tempstore; + return CURLE_OK; + +@@ -105,7 +160,7 @@ fail: + } + + free(tempstore); +- ++ free(dir); + return result; + } + +-- +2.43.0 + diff --git a/0009-curl-8.0.1-fix-openldap-conftest.patch b/0009-curl-8.0.1-fix-openldap-conftest.patch new file mode 100644 index 0000000..c3e2e17 --- /dev/null +++ b/0009-curl-8.0.1-fix-openldap-conftest.patch @@ -0,0 +1,43 @@ +From 0ac6108856b9d500bc376d1d7e0b648d15499837 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 22 Jun 2023 14:34:49 +0200 +Subject: [PATCH] configure: add check for ldap_init_fd + +... as otherwise the configure script will say it is OpenLDAP in the +summary, but not set the USE_OPENLDAP define, therefor not using the +intended OpenLDAP code paths. + +Regression since 4d7385446 (7.85.0) +Fixes #11372 +Closes #11374 +Reported-by: vlkl-sap on github +--- + configure.ac | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 373e2e0cef6862..696a50505f37ab 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1706,16 +1706,19 @@ if test x$CURL_DISABLE_LDAP != x1 ; then + fi + + if test x$CURL_DISABLE_LDAP != x1 ; then +- AC_CHECK_FUNCS([ldap_url_parse]) ++ AC_CHECK_FUNCS([ldap_url_parse \ ++ ldap_init_fd]) + + if test "$LDAPLIBNAME" = "wldap32"; then + curl_ldap_msg="enabled (winldap)" + AC_DEFINE(USE_WIN32_LDAP, 1, [Use Windows LDAP implementation]) + else +- curl_ldap_msg="enabled (OpenLDAP)" + if test "x$ac_cv_func_ldap_init_fd" = "xyes"; then ++ curl_ldap_msg="enabled (OpenLDAP)" + AC_DEFINE(USE_OPENLDAP, 1, [Use OpenLDAP-specific code]) + AC_SUBST(USE_OPENLDAP, [1]) ++ else ++ curl_ldap_msg="enabled (ancient OpenLDAP)" + fi + fi + fi diff --git a/0104-curl-7.88.0-tests-warnings.patch b/0104-curl-7.88.0-tests-warnings.patch new file mode 100644 index 0000000..dff89f9 --- /dev/null +++ b/0104-curl-7.88.0-tests-warnings.patch @@ -0,0 +1,30 @@ +From d506d885aa16b4a87acbac082eea41dccdc7b69f Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 15 Feb 2023 10:42:38 +0100 +Subject: [PATCH] Revert "runtests: consider warnings fatal and error on them" + +While it might be useful for upstream developers, it is not so useful +for downstream consumers. + +This reverts upstream commit 22f795c834cfdbacbb1b55426028a581e3cf67a8. +--- + tests/runtests.pl | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tests/runtests.pl b/tests/runtests.pl +index 71644ad18..0cf85c3fe 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -75,8 +75,7 @@ BEGIN { + } + + use strict; +-# Promote all warnings to fatal +-use warnings FATAL => 'all'; ++use warnings; + use Cwd; + use Digest::MD5 qw(md5); + use MIME::Base64; +-- +2.39.1 + diff --git a/0105-curl-8.0.1-tests-stunnel-port.patch b/0105-curl-8.0.1-tests-stunnel-port.patch new file mode 100644 index 0000000..47d1419 --- /dev/null +++ b/0105-curl-8.0.1-tests-stunnel-port.patch @@ -0,0 +1,97 @@ +From c9a1d18e5f8f28b90c1b2fcc1f15699327067e59 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 21 Apr 2023 17:44:10 +0200 +Subject: [PATCH] tests/runtests.pl: attempt to fix a conflict on port numbers + +... where stunnel listens for legacy HTTPS and HTTP/2, which manifests +as a hard-to-explain failure of the following tests: 1630 1631 1632 1904 +1941 1945 2050 2055 3028 +``` +[...] +startnew: perl -I../../tests ../../tests/secureserver.pl --pidfile ".https_server.pid" --logfile "log/https_stunnel.log" --ipv4 --proto https --stunnel "/usr/bin/stunnel" --srcdir "../../tests" --connect 42917 --accept 24642 +RUN: HTTPS server is PID 114398 port 24642 +* pid https => 114398 114402 +[...] +startnew: perl -I../../tests ../../tests/secureserver.pl --pidfile ".https2_server.pid" --logfile "log/https2_stunnel.log" --id 2 --ipv4 --proto https --stunnel "/usr/bin/stunnel" --srcdir "../../tests" --connect 36763 --accept 24642 +startnew: child process has died, server might start up +Warning: http2 server unexpectedly alive +RUN: Process with pid 73992 signalled to die +RUN: Process with pid 73992 forced to die with SIGKILL +== Contents of files in the log/ dir after test 1630 +=== Start of file http2_server.log + 14:01:21.881018 exit_signal_handler: 15 + 14:01:21.881372 signalled to die + 14:01:21.881511 ========> IPv4 sws (port 36763 pid: 73992) exits with signal (15) +=== End of file http2_server.log +=== Start of file https2_stunnel.log + [ ] Initializing inetd mode configuration + [ ] Clients allowed=500 + [.] stunnel 5.69 on x86_64-redhat-linux-gnu platform + [.] Compiled/running with OpenSSL 3.0.8 7 Feb 2023 + [.] Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,FIPS,OCSP,PSK,SNI + [ ] errno: (*__errno_location ()) + [ ] Initializing inetd mode configuration + [.] Reading configuration from file /builddir/build/BUILD/curl-8.0.1/build-minimal/tests/https_stunnel.conf + [.] UTF-8 byte order mark not detected + [.] FIPS mode disabled + [ ] Compression disabled + [ ] No PRNG seeding was required + [ ] Initializing service [curltest] + [ ] Using the default TLS minimum version as specified in crypto policies. Not setting explicitly. + [ ] Using the default TLS maximum version as specified in crypto policies. Not setting explicitly + [ ] stunnel default security level set: 2 + [ ] Ciphers: PROFILE=SYSTEM + [ ] TLSv1.3 ciphersuites: TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 + [ ] TLS options: 0x2100000 (+0x0, -0x0) + [ ] Session resumption enabled + [ ] Loading certificate from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Certificate loaded from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Loading private key from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Private key loaded from file: /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Private key check succeeded + [!] No trusted certificates found + [ ] DH initialization needed for DHE-RSA-AES256-GCM-SHA384 + [ ] DH initialization + [ ] Could not load DH parameters from /builddir/build/BUILD/curl-8.0.1/tests/stunnel.pem + [ ] Using dynamic DH parameters + [ ] ECDH initialization + [ ] ECDH initialized with curves X25519:P-256:X448:P-521:P-384 + [.] Configuration successful + [ ] Deallocating deployed section defaults + [ ] Binding service [curltest] + [ ] Listening file descriptor created (FD=8) + [ ] Setting accept socket options (FD=8) + [ ] Option SO_REUSEADDR set on accept socket + [.] Binding service [curltest] to 0.0.0.0:24642: Address already in use (98) + [ ] Listening file descriptor created (FD=8) + [ ] Setting accept socket options (FD=8) + [ ] Option SO_REUSEADDR set on accept socket + [.] Binding service [curltest] to :::24642: Address already in use (98) + [!] Binding service [curltest] failed + [ ] Unbinding service [curltest] + [ ] Service [curltest] closed + [ ] Deallocating deployed section defaults + [ ] Deallocating section [curltest] + [ ] Initializing inetd mode configuration +=== End of file https2_stunnel.log +``` +--- + tests/runtests.pl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/runtests.pl b/tests/runtests.pl +index 54f6923..bb362c9 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -1802,7 +1802,7 @@ sub runhttpsserver { + + my $pid2; + my $httpspid; +- my $port = 24512; # start attempt ++ my $port = 24512 * $idnum; # start attempt + for (1 .. 10) { + $port += int(rand(600)); + my $options = "$flags --accept $port"; +-- +2.39.2 + diff --git a/curl.spec b/curl.spec index 61f3004..7224088 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl -Version: 7.87.0 -Release: 4%{?dist} +Version: 8.0.1 +Release: 7%{?dist} License: MIT Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -10,8 +10,32 @@ Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc # which points to the GPG key as of April 7th 2016 of https://daniel.haxx.se/mykey.asc Source2: mykey.asc -# fix regression in a public header file (#2162716) -Patch1: 0001-curl-7.87.0-header-file-regression.patch +# fix more POST-after-PUT confusion (CVE-2023-28322) +Patch1: 0001-curl-8.0.1-CVE-2023-28322.patch + +# fix IDN wildcard match (CVE-2023-28321) +Patch2: 0002-curl-8.0.1-CVE-2023-28321.patch + +# fix fopen race condition (CVE-2023-32001) +Patch3: 0003-curl-8.0.1-CVE-2023-32001.patch + +# fix HTTP headers eat all memory (CVE-2023-38039) +Patch4: 0004-curl-8.0.1-CVE-2023-38039.patch + +# fix SOCKS5 heap buffer overflow (CVE-2023-38545) +Patch5: 0005-curl-8.0.1-CVE-2023-38545.patch + +# fix cookie injection with none file (CVE-2023-38546) +Patch6: 0006-curl-8.0.1-CVE-2023-38546.patch + +# fix cookie mixed case PSL bypass (CVE-2023-46218) +Patch7: 0007-curl-8.0.1-CVE-2023-46218.patch + +# fix HSTS long file name clears contents (CVE-2023-46219) +Patch8: 0008-curl-8.0.1-CVE-2023-46219.patch + +# fix OpenLDAP conftest +Patch9: 0009-curl-8.0.1-fix-openldap-conftest.patch # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -22,6 +46,12 @@ Patch102: 0102-curl-7.84.0-test3026.patch # test3012: temporarily disable valgrind (#2143040) Patch103: 0103-curl-7.87.0-test3012.patch +# do not fail on warnings in the upstream test driver +Patch104: 0104-curl-7.88.0-tests-warnings.patch + +# tests: attempt to fix a conflict on port numbers +Patch105: 0105-curl-8.0.1-tests-stunnel-port.patch + Provides: curl-full = %{version}-%{release} Provides: webclient URL: https://curl.se/ @@ -60,6 +90,9 @@ BuildRequires: perl(Pod::Usage) BuildRequires: perl(strict) BuildRequires: perl(warnings) +# needed for test1560 to succeed +BuildRequires: glibc-langpack-en + # gnutls-serv is used by the upstream test-suite BuildRequires: gnutls-utils @@ -197,45 +230,11 @@ be installed. %prep %{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' -%setup -q +%autosetup -p1 -# upstream patches -%patch1 -p1 - -# Fedora patches -%patch101 -p1 -%patch102 -p1 -%patch103 -p1 - -# disable test 1112 (#565305), test 1455 (occasionally fails with 'bind failed -# with errno 98: Address already in use' in Koji environment), and test 1801 +# disable test 1801 # -printf "1112\n1455\n1184\n1801\n" >> tests/data/DISABLED - -# disable test 1319 on ppc64 (server times out) -%ifarch ppc64 -echo "1319" >> tests/data/DISABLED -%endif - -# disable tests 320..322 on ppc64le where it started to hang/fail -%ifarch ppc64le -printf "320\n321\n322\n" >> tests/data/DISABLED -%endif - -# temporarily disable tests 582 and 1452 on s390x (client times out) -%ifarch s390x -printf "582\n1452\n" >> tests/data/DISABLED -%endif - -# temporarily disable tests 702 703 716 on armv7hl (#1829180) -%ifarch armv7hl -printf "702\n703\n716\n" >> tests/data/DISABLED -%endif - -# temporarily disable tests 300{0,1} on x86_64 (stunnel clashes with itself) -%ifarch x86_64 -printf "3000\n3001\n" >> tests/data/DISABLED -%endif +echo "1801" >> tests/data/DISABLED # test3026: avoid pthread_create() failure due to resource exhaustion on i386 %ifarch %{ix86} @@ -435,6 +434,57 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Feb 14 2024 Lukáš Zaoral - 8.0.1-7 +- fix openldap conftest + +* Wed Dec 06 2023 Jan Macku - 8.0.1-6 +- fix HSTS long file name clears contents (CVE-2023-46219) +- fix cookie mixed case PSL bypass (CVE-2023-46218) + +* Thu Oct 12 2023 Jan Macku - 8.0.1-5 +- fix cookie injection with none file (CVE-2023-38546) +- fix SOCKS5 heap buffer overflow (CVE-2023-38545) + +* Wed Sep 13 2023 Jan Macku - 8.0.1-4 +- fix HTTP headers eat all memory (CVE-2023-38039) + +* Thu Jul 20 2023 Jan Macku - 8.0.1-3 +- fix fopen race condition (CVE-2023-32001) + +* Mon Jun 05 2023 Jan Macku - 8.0.1-2 +- fix more POST-after-PUT confusion (CVE-2023-28322) +- fix IDN wildcard match (CVE-2023-28321) + +* Wed May 03 2023 Kamil Dudka - 8.0.1-1 +- tests: re-enable temporarily disabled test-cases +- tests: attempt to fix a conflict on port numbers +- apply patches automatically +- rebase to latest upstream release (#2192665) + +* Wed May 03 2023 Kamil Dudka - 7.87.0-10 +- http_proxy: fix memory corruption with http proxy tunneling (#2192665) + +* Wed May 03 2023 Kamil Dudka - 7.87.0-9 +- vtls: fix hostname handling in filters (#2192665) + +* Fri Apr 21 2023 Kamil Dudka - 7.87.0-8 +- cfilters: use the first non-connected filter (#2185433) + +* Fri Mar 24 2023 Kamil Dudka - 7.87.0-7 +- fix SSH connection too eager reuse still (CVE-2023-27538) +- fix HSTS double-free (CVE-2023-27537) +- 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 Mar 15 2023 Kamil Dudka - 7.87.0-6 +- tests: make sure gnuserv-tls has SRP support before using it + +* Wed Feb 15 2023 Kamil Dudka - 7.87.0-5 +- fix HTTP multi-header compression denial of service (CVE-2023-23916) +- share HSTS between handles (CVE-2023-23915 CVE-2023-23914) + * Fri Jan 20 2023 Kamil Dudka - 7.87.0-4 - fix regression in a public header file (#2162716) diff --git a/sources b/sources index 7906eb7..fe0a4ce 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (curl-7.87.0.tar.xz) = aa125991592667280dce3788aabe81487cf8c55b0afc59d675cc30b76055bb7114f5380b4a0e3b6461a8f81bf9812fa26d493a85f7e01d84263d484a0d699ee7 -SHA512 (curl-7.87.0.tar.xz.asc) = 0bcc12bafc4ae50d80128af2cf4bf1a1ec6018ebb8d5b9c49f52b51c0c25acc77e820858965656549ef43c1f923f4e5fe75b0a3523623154b4cfb9dc8a1d76e4 +SHA512 (curl-8.0.1.tar.xz) = 3bb777982659ed697ae90f113ff7b65d6ce8ba9fe6a8984cfd6769d2f051a72ba953c911abe234c204ec2cc5a35d68b4d033037fad7fba31bb92a52543f8d13d +SHA512 (curl-8.0.1.tar.xz.asc) = 92c6a0570e9a8a708fe2f717b8b37a68dcb9cd4520ca50c9baafec5891bda103bce2d2dcb67f1387bf11bd7e51e0e64ccd52d196e61d58b598ad3aa1960386cf diff --git a/tests/non-root-user-download/runtest.sh b/tests/non-root-user-download/runtest.sh index 0529a12..4d51e62 100755 --- a/tests/non-root-user-download/runtest.sh +++ b/tests/non-root-user-download/runtest.sh @@ -31,9 +31,9 @@ PACKAGE="curl" -FTP_URL=ftp://ftp.fi.muni.cz/pub/linux/fedora/linux/releases/36/Everything/x86_64/iso/Fedora-Everything-36-1.5-x86_64-CHECKSUM -HTTP_URL=https://archives.fedoraproject.org/pub/fedora/linux/releases/36/Everything/x86_64/iso/Fedora-Everything-36-1.5-x86_64-CHECKSUM -CONTENT=85cb450443d68d513b41e57b0bd818a740279dac5dfc09c68e681ff8a3006404 +FTP_URL=ftp://ftp.fi.muni.cz/pub/linux/fedora/linux/releases/38/Everything/x86_64/iso/Fedora-Everything-38-1.6-x86_64-CHECKSUM +HTTP_URL=https://archives.fedoraproject.org/pub/fedora/linux/releases/38/Everything/x86_64/iso/Fedora-Everything-38-1.6-x86_64-CHECKSUM +CONTENT=4d042dedc8886856db10bc882074b84dcce52f829ea7b3f31d8031db8d84df20 PASSWORD=pAssw0rd OPTIONS="" rlIsRHEL 7 && OPTIONS="--insecure"