Compare commits

...
Sign in to create a new pull request.

29 commits

Author SHA1 Message Date
Lukáš Zaoral
5bf3c70332
fix openldap conftest 2024-02-14 12:31:44 +01:00
Jan Macku
1f7f31bdbf Resolves: CVE-2023-46219 - HSTS long file name clears contents 2023-12-06 16:08:39 +01:00
Jan Macku
eee0c7d606 Resolves: CVE-2023-46218 - cookie mixed case PSL bypass 2023-12-06 16:06:31 +01:00
Jan Macku
e1c9c5d683 Resolves: CVE-2023-38546 - cookie injection with none file 2023-10-12 09:37:18 +02:00
Jan Macku
4db7b87ac4 Resolves: CVE-2023-38545 - SOCKS5 heap buffer overflow 2023-10-12 09:32:40 +02:00
Lukáš Zaoral
8a97eeb08a
tests: use newer Fedora URLs for testing
... because F36 URLs are no longer available.
2023-10-09 10:41:14 +02:00
Jan Macku
640fb40e90 Resolves: CVE-2023-38039 - fix HTTP headers eat all memory 2023-09-13 13:39:44 +02:00
Jan Macku
3eba762b34 Resolves: CVE-2023-32001 - fix fopen race condition 2023-07-20 09:44:10 +02:00
Jan Macku
0d582aa92f Resolves: CVE-2023-28321 - fix IDN wildcard match 2023-06-05 08:43:27 +02:00
Jan Macku
3ce778ed47 Resolves: CVE-2023-28322 - fix more POST-after-PUT confusion 2023-06-05 08:29:08 +02:00
Kamil Dudka
c2176d668a tests: re-enable temporarily disabled test-cases 2023-05-03 18:41:55 +02:00
Kamil Dudka
e76d3e0e65 tests: 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
```
2023-05-03 18:41:55 +02:00
Kamil Dudka
24723f4bdf curl.spec: apply patches automatically
... to ease maintenance and to avoid the following warning on Fedora
Rawhide:
```
warning: %patchN is deprecated (4 usages found), use %patch N (or %patch -P N)
```
2023-05-03 18:41:55 +02:00
Kamil Dudka
0980c80da7 add glibc-langpack-en BR needed for test1560 to succeed
Suggested-by: Paul Howarth
2023-05-03 18:41:55 +02:00
Kamil Dudka
a70e47eb40 do not fail on warnings in the upstream test driver 2023-05-03 16:20:42 +02:00
Kamil Dudka
f854769ba4 Resolves: #2192665 - new upstream release - 8.0.1 2023-05-03 16:20:41 +02:00
Kamil Dudka
ac9ca2137b 0009-curl-7.87.0-http-proxy.patch: add forgotten patch 2023-05-03 15:46:13 +02:00
Kamil Dudka
23fee3d386 Resolves: #2192665 - http_proxy: fix memory corruption with http proxy tunneling 2023-05-03 15:41:31 +02:00
Kamil Dudka
472ff9ff39 Resolves: #2192665 - vtls: fix hostname handling in filters 2023-05-03 13:48:50 +02:00
Kamil Dudka
7a1d94d30c Resolves: #2185433 - cfilters: use the first non-connected filter 2023-04-21 13:54:14 +02:00
Kamil Dudka
a3bc8ee146 Resolves: CVE-2023-27538 - fix SSH connection too eager reuse still 2023-03-24 13:28:18 +01:00
Kamil Dudka
be852f01b8 Resolves: CVE-2023-27537 - fix HSTS double-free 2023-03-24 13:26:50 +01:00
Kamil Dudka
4b9d351868 Resolves: CVE-2023-27536 - fix GSS delegation too eager connection re-use 2023-03-24 13:25:23 +01:00
Kamil Dudka
8c6f543d9e Resolves: CVE-2023-27535 - fix FTP too eager connection reuse 2023-03-24 13:24:04 +01:00
Kamil Dudka
bdb83efe75 Resolves: CVE-2023-27534 - fix SFTP path ~ resolving discrepancy 2023-03-24 13:17:56 +01:00
Kamil Dudka
0703082041 Resolves: CVE-2023-27533 - fix TELNET option IAC injection 2023-03-24 13:14:43 +01:00
Kamil Dudka
ec2bc20d6e tests: make sure gnuserv-tls has SRP support before using it 2023-03-15 16:46:54 +01:00
Kamil Dudka
5e6ef31ed9 Resolves: CVE-2023-23916 - fix HTTP multi-header compression denial of service 2023-02-15 18:01:30 +01:00
Kamil Dudka
531c0747a3 share HSTS between handles
Resolves: CVE-2023-23915 - HSTS amnesia with --parallel
Resolves: CVE-2023-23914 - HSTS ignored on multiple requests
2023-02-15 14:51:53 +01:00
15 changed files with 1902 additions and 101 deletions

View file

@ -1,55 +0,0 @@
From 613d3c45879636e88b88fcebee48dc77de345291 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
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 <kdudka@redhat.com>
---
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

View file

@ -0,0 +1,437 @@
From 074adec63f0dd7a8f0d823ee503dfb0626061505 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 25 Apr 2023 08:28:01 +0200
Subject: [PATCH] lib: unify the upload/method handling
By making sure we set state.upload based on the set.method value and not
independently as set.upload, we reduce confusion and mixup risks, both
internally and externally.
Closes #11017
(cherry picked from commit 7815647d6582c0a4900be2e1de6c5e61272c496b)
Signed-off-by: Jan Macku <jamacku@redhat.com>
---
lib/curl_rtmp.c | 4 ++--
lib/file.c | 4 ++--
lib/ftp.c | 8 ++++----
lib/http.c | 4 ++--
lib/imap.c | 6 +++---
lib/rtsp.c | 4 ++--
lib/setopt.c | 6 ++----
lib/smb.c | 6 +++---
lib/smtp.c | 4 ++--
lib/tftp.c | 8 ++++----
lib/transfer.c | 4 ++--
lib/urldata.h | 2 +-
lib/vssh/libssh.c | 6 +++---
lib/vssh/libssh2.c | 6 +++---
lib/vssh/wolfssh.c | 2 +-
15 files changed, 36 insertions(+), 38 deletions(-)
diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
index 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

View file

@ -0,0 +1,498 @@
From 9cfc8e3107920116ac31ab1fbf6439d38ab2f30e Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 24 Apr 2023 21:07:02 +0200
Subject: [PATCH] hostcheck: fix host name wildcard checking
The leftmost "label" of the host name can now only match against single
'*'. Like the browsers have worked for a long time.
- extended unit test 1397 for this
- move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc
Reported-by: Hiroki Kurosawa
Closes #11018
(cherry picked from commit 199f2d440d8659b42670c1b796220792b01a97bf)
Signed-off-by: Jan Macku <jamacku@redhat.com>
---
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 @@
<info>
<keywords>
unittest
-ssl
-wildcard
+Curl_cert_hostcheck
</keywords>
</info>
@@ -16,9 +15,8 @@ none
<features>
unittest
</features>
- <name>
-Check wildcard certificate matching function Curl_cert_hostcheck
- </name>
+<name>
+Curl_cert_hostcheck unit tests
+</name>
</client>
-
</testcase>
diff --git a/tests/unit/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

View file

@ -0,0 +1,40 @@
From 98474a7848e20716935f471f4e48610b00fe9dc0 Mon Sep 17 00:00:00 2001
From: SaltyMilk <soufiane.elmelcaoui@gmail.com>
Date: Mon, 10 Jul 2023 21:43:28 +0200
Subject: [PATCH] fopen: optimize
Closes #11419
(cherry picked from commit 0c667188e0c6cda615a036b8a2b4125f2c404dde)
Signed-off-by: Jan Macku <jamacku@redhat.com>
---
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

View file

@ -0,0 +1,201 @@
From fe13e206a80cee9ffa686ead170980dbdb2cf9e1 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
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 <jamacku@redhat.com>
---
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

View file

@ -0,0 +1,135 @@
From fa4aed65588db8e7c7e3d98f6c5bcf394f3a515d Mon Sep 17 00:00:00 2001
From: Jay Satiro <raysatiro@yahoo.com>
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 <jamacku@redhat.com>
---
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 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+SOCKS5
+SOCKS5h
+followlocation
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+# The hostname in this redirect is 256 characters and too long (> 255) for
+# SOCKS5 remote resolve. curl must return error CURLE_PROXY in this case.
+<data>
+HTTP/1.1 301 Moved Permanently
+Location: http://AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/
+Content-Length: 0
+Connection: close
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+socks5
+</server>
+ <name>
+SOCKS5h with HTTP redirect to hostname too long
+ </name>
+ <command>
+--no-progress-meter --location --proxy socks5h://%HOSTIP:%SOCKSPORT http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+<errorcode>
+97
+</errorcode>
+# the error message is verified because error code CURLE_PROXY (97) may be
+# returned for any number of reasons and we need to make sure it is
+# specifically for the reason below so that we know the check is working.
+<stderr mode="text">
+curl: (97) SOCKS5: the destination hostname is too long to be resolved remotely by the proxy.
+</stderr>
+</verify>
+</testcase>
--
2.41.0

View file

@ -0,0 +1,136 @@
From a9a3f49fc87d4b64f380e19d69c139e9fba676f2 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
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 <jamacku@redhat.com>
---
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 = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
-
- /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
- char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */
-
bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
@@ -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

View file

@ -0,0 +1,55 @@
From ef4abe34b2b704e2a318063b387b628773b78663 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
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 <jamacku@redhat.com>
---
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

View file

@ -0,0 +1,134 @@
From 45ed144efd8b194cc7d0acbe00594f730a2ad62d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
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 <jamacku@redhat.com>
---
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

View file

@ -0,0 +1,43 @@
From 0ac6108856b9d500bc376d1d7e0b648d15499837 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
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

View file

@ -0,0 +1,30 @@
From d506d885aa16b4a87acbac082eea41dccdc7b69f Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
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

View file

@ -0,0 +1,97 @@
From c9a1d18e5f8f28b90c1b2fcc1f15699327067e59 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
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

132
curl.spec
View file

@ -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
# <https://github.com/bagder/curl/commit/21e82bd6#commitcomment-12226582>
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 <lzaoral@redhat.com> - 8.0.1-7
- fix openldap conftest
* Wed Dec 06 2023 Jan Macku <jamacku@redhat.com> - 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 <jamacku@redhat.com> - 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 <jamacku@redhat.com> - 8.0.1-4
- fix HTTP headers eat all memory (CVE-2023-38039)
* Thu Jul 20 2023 Jan Macku <jamacku@redhat.com> - 8.0.1-3
- fix fopen race condition (CVE-2023-32001)
* Mon Jun 05 2023 Jan Macku <jamacku@redhat.com> - 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 <kdudka@redhat.com> - 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 <kdudka@redhat.com> - 7.87.0-10
- http_proxy: fix memory corruption with http proxy tunneling (#2192665)
* Wed May 03 2023 Kamil Dudka <kdudka@redhat.com> - 7.87.0-9
- vtls: fix hostname handling in filters (#2192665)
* Fri Apr 21 2023 Kamil Dudka <kdudka@redhat.com> - 7.87.0-8
- cfilters: use the first non-connected filter (#2185433)
* Fri Mar 24 2023 Kamil Dudka <kdudka@redhat.com> - 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 <kdudka@redhat.com> - 7.87.0-6
- tests: make sure gnuserv-tls has SRP support before using it
* Wed Feb 15 2023 Kamil Dudka <kdudka@redhat.com> - 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 <kdudka@redhat.com> - 7.87.0-4
- fix regression in a public header file (#2162716)

View file

@ -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

View file

@ -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"