Compare commits

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

16 commits

Author SHA1 Message Date
Kamil Dudka
4dd9624cd7 Resolves: CVE-2021-22947 - fix STARTTLS protocol injection via MITM 2021-09-17 09:53:05 +02:00
Kamil Dudka
46b1c25738 Resolves: CVE-2021-22946 - fix protocol downgrade required TLS bypass 2021-09-17 09:40:38 +02:00
Kamil Dudka
8545535d63 Resolves: CVE-2021-22945 - fix use-after-free and double-free in MQTT sending 2021-09-17 09:26:56 +02:00
Kamil Dudka
f2473c9f84 changelog: fix date in the last entry 2021-07-22 09:29:55 +02:00
Kamil Dudka
1dc08c9d96 Resolves: CVE-2021-22925 - fix TELNET stack contents disclosure again 2021-07-21 18:31:02 +02:00
Kamil Dudka
fa90718ce5 Resolves: CVE-2021-22898 - fix TELNET stack contents disclosure 2021-07-21 18:28:42 +02:00
Kamil Dudka
ff41f425b6 Resolves: CVE-2021-22924 - fix bad connection reuse due to flawed path name checks 2021-07-21 18:25:20 +02:00
Kamil Dudka
22ead1eab2 build the curl tool without metalink support
Resolves: CVE-2021-22923 - metalink download sends credentials
Resolves: CVE-2021-22922 - wrong content via metalink not discarded
2021-07-21 18:00:57 +02:00
Kamil Dudka
9aaddd4aa3 Resolves: CVE-2021-22890 - fix TLS 1.3 session ticket proxy host mixup 2021-03-31 16:59:27 +02:00
Kamil Dudka
1ee2417a75 Resolves: CVE-2021-22876 - prevent automatic referer from leaking credentials 2021-03-31 16:59:25 +02:00
Kamil Dudka
4c39814d7c Resolves: CVE-2020-8286 - curl: Inferior OCSP verification 2020-12-09 13:24:38 +01:00
Kamil Dudka
a52387704a Resolves: CVE-2020-8285 - libcurl: FTP wildcard stack overflow 2020-12-09 13:24:36 +01:00
Kamil Dudka
aa87f54d87 Resolves: CVE-2020-8284 - curl: trusting FTP PASV responses 2020-12-09 11:41:07 +01:00
Paul Howarth
89e3fb5767 Fix bug reference in changelog 2020-10-14 09:31:10 +02:00
Jinoh Kang
5470570402 Resolves: #1877671O - fix multiarch conflicts in libcurl-minimal 2020-09-10 10:23:41 +02:00
Kamil Dudka
2c28dfb932 Resolves: CVE-2020-8231 - libcurl: wrong connect-only connection 2020-08-19 14:03:52 +02:00
13 changed files with 4426 additions and 5 deletions

View file

@ -0,0 +1,281 @@
From 6830828c9eecd9ab14404f2f49f19b56dec62130 Mon Sep 17 00:00:00 2001
From: Marc Aldorasi <marc@groundctl.com>
Date: Thu, 30 Jul 2020 14:16:17 -0400
Subject: [PATCH 1/2] multi_remove_handle: close unused connect-only
connections
Previously any connect-only connections in a multi handle would be kept
alive until the multi handle was closed. Since these connections cannot
be re-used, they can be marked for closure when the associated easy
handle is removed from the multi handle.
Closes #5749
Upstream-commit: d5bb459ccf1fc5980ae4b95c05b4ecf6454a7599
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/multi.c | 34 ++++++++++++++++++++++++++++++----
tests/data/test1554 | 6 ++++++
2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/lib/multi.c b/lib/multi.c
index 249e360..f1371bd 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -689,6 +689,26 @@ static CURLcode multi_done(struct Curl_easy *data,
return result;
}
+static int close_connect_only(struct connectdata *conn, void *param)
+{
+ struct Curl_easy *data = param;
+
+ if(data->state.lastconnect != conn)
+ return 0;
+
+ if(conn->data != data)
+ return 1;
+ conn->data = NULL;
+
+ if(!conn->bits.connect_only)
+ return 1;
+
+ connclose(conn, "Removing connect-only easy handle");
+ conn->bits.connect_only = FALSE;
+
+ return 1;
+}
+
CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
struct Curl_easy *data)
{
@@ -776,10 +796,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
multi_done() as that may actually call Curl_expire that uses this */
Curl_llist_destroy(&data->state.timeoutlist, NULL);
- /* as this was using a shared connection cache we clear the pointer to that
- since we're not part of that multi handle anymore */
- data->state.conn_cache = NULL;
-
/* change state without using multistate(), only to make singlesocket() do
what we want */
data->mstate = CURLM_STATE_COMPLETED;
@@ -789,12 +805,22 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* Remove the association between the connection and the handle */
Curl_detach_connnection(data);
+ if(data->state.lastconnect) {
+ /* Mark any connect-only connection for closure */
+ Curl_conncache_foreach(data, data->state.conn_cache,
+ data, &close_connect_only);
+ }
+
#ifdef USE_LIBPSL
/* Remove the PSL association. */
if(data->psl == &multi->psl)
data->psl = NULL;
#endif
+ /* as this was using a shared connection cache we clear the pointer to that
+ since we're not part of that multi handle anymore */
+ data->state.conn_cache = NULL;
+
data->multi = NULL; /* clear the association to this multi handle */
/* make sure there's no pending message in the queue sent from this easy
diff --git a/tests/data/test1554 b/tests/data/test1554
index d3926d9..fffa6ad 100644
--- a/tests/data/test1554
+++ b/tests/data/test1554
@@ -50,6 +50,8 @@ run 1: foobar and so on fun!
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
run 1: foobar and so on fun!
-> Mutex lock
<- Mutex unlock
@@ -65,6 +67,8 @@ run 1: foobar and so on fun!
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
run 1: foobar and so on fun!
-> Mutex lock
<- Mutex unlock
@@ -74,6 +78,8 @@ run 1: foobar and so on fun!
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
</datacheck>
</reply>
--
2.25.4
From 01148ee40dd913a169435b0f9ea90e6393821e70 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sun, 16 Aug 2020 11:34:35 +0200
Subject: [PATCH 2/2] Curl_easy: remember last connection by id, not by pointer
CVE-2020-8231
Bug: https://curl.haxx.se/docs/CVE-2020-8231.html
Reported-by: Marc Aldorasi
Closes #5824
Upstream-commit: 3c9e021f86872baae412a427e807fbfa2f3e8a22
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/connect.c | 19 ++++++++++---------
lib/easy.c | 3 +--
lib/multi.c | 9 +++++----
lib/url.c | 2 +-
lib/urldata.h | 2 +-
5 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/lib/connect.c b/lib/connect.c
index 29293f0..e1c5662 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -1363,15 +1363,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
struct connfind {
- struct connectdata *tofind;
- bool found;
+ long id_tofind;
+ struct connectdata *found;
};
static int conn_is_conn(struct connectdata *conn, void *param)
{
struct connfind *f = (struct connfind *)param;
- if(conn == f->tofind) {
- f->found = TRUE;
+ if(conn->connection_id == f->id_tofind) {
+ f->found = conn;
return 1;
}
return 0;
@@ -1393,21 +1393,22 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
* - that is associated with a multi handle, and whose connection
* was detached with CURLOPT_CONNECT_ONLY
*/
- if(data->state.lastconnect && (data->multi_easy || data->multi)) {
- struct connectdata *c = data->state.lastconnect;
+ if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) {
+ struct connectdata *c;
struct connfind find;
- find.tofind = data->state.lastconnect;
- find.found = FALSE;
+ find.id_tofind = data->state.lastconnect_id;
+ find.found = NULL;
Curl_conncache_foreach(data, data->multi_easy?
&data->multi_easy->conn_cache:
&data->multi->conn_cache, &find, conn_is_conn);
if(!find.found) {
- data->state.lastconnect = NULL;
+ data->state.lastconnect_id = -1;
return CURL_SOCKET_BAD;
}
+ c = find.found;
if(connp) {
/* only store this if the caller cares for it */
*connp = c;
diff --git a/lib/easy.c b/lib/easy.c
index 292cca7..a69eb9e 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -838,8 +838,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
/* the connection cache is setup on demand */
outcurl->state.conn_cache = NULL;
-
- outcurl->state.lastconnect = NULL;
+ outcurl->state.lastconnect_id = -1;
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
diff --git a/lib/multi.c b/lib/multi.c
index f1371bd..778c537 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -455,6 +455,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->state.conn_cache = &data->share->conn_cache;
else
data->state.conn_cache = &multi->conn_cache;
+ data->state.lastconnect_id = -1;
#ifdef USE_LIBPSL
/* Do the same for PSL. */
@@ -677,11 +678,11 @@ static CURLcode multi_done(struct Curl_easy *data,
CONNCACHE_UNLOCK(data);
if(Curl_conncache_return_conn(data, conn)) {
/* remember the most recently used connection */
- data->state.lastconnect = conn;
+ data->state.lastconnect_id = conn->connection_id;
infof(data, "%s\n", buffer);
}
else
- data->state.lastconnect = NULL;
+ data->state.lastconnect_id = -1;
}
Curl_safefree(data->state.buffer);
@@ -693,7 +694,7 @@ static int close_connect_only(struct connectdata *conn, void *param)
{
struct Curl_easy *data = param;
- if(data->state.lastconnect != conn)
+ if(data->state.lastconnect_id != conn->connection_id)
return 0;
if(conn->data != data)
@@ -805,7 +806,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* Remove the association between the connection and the handle */
Curl_detach_connnection(data);
- if(data->state.lastconnect) {
+ if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache,
data, &close_connect_only);
diff --git a/lib/url.c b/lib/url.c
index a1a6b69..2919a3d 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -630,7 +630,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
Curl_initinfo(data);
/* most recent connection is not yet defined */
- data->state.lastconnect = NULL;
+ data->state.lastconnect_id = -1;
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
diff --git a/lib/urldata.h b/lib/urldata.h
index f80a02d..6d8eb69 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1300,7 +1300,7 @@ struct UrlState {
/* buffers to store authentication data in, as parsed from input options */
struct curltime keeps_speed; /* for the progress meter really */
- struct connectdata *lastconnect; /* The last connection, NULL if undefined */
+ long lastconnect_id; /* The last connection, -1 if undefined */
struct dynbuf headerb; /* buffer to store headers in */
char *buffer; /* download buffer */
--
2.25.4

View file

@ -0,0 +1,208 @@
From c7cc15980d50a51857de66b701b7762789139b46 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 24 Nov 2020 14:56:57 +0100
Subject: [PATCH] ftp: CURLOPT_FTP_SKIP_PASV_IP by default
The command line tool also independently sets --ftp-skip-pasv-ip by
default.
Ten test cases updated to adapt the modified --libcurl output.
Bug: https://curl.se/docs/CVE-2020-8284.html
CVE-2020-8284
Reported-by: Varnavas Papaioannou
Upstream-commit: ec9cc725d598ac77de7b6df8afeec292b3c8ad46
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
docs/cmdline-opts/ftp-skip-pasv-ip.d | 2 ++
docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | 8 +++++---
lib/url.c | 1 +
src/tool_cfgable.c | 1 +
tests/data/test1400 | 1 +
tests/data/test1401 | 1 +
tests/data/test1402 | 1 +
tests/data/test1403 | 1 +
tests/data/test1404 | 1 +
tests/data/test1405 | 1 +
tests/data/test1406 | 1 +
tests/data/test1407 | 1 +
tests/data/test1420 | 1 +
13 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d
index da6ab11..4be8b43 100644
--- a/docs/cmdline-opts/ftp-skip-pasv-ip.d
+++ b/docs/cmdline-opts/ftp-skip-pasv-ip.d
@@ -9,4 +9,6 @@ to curl's PASV command when curl connects the data connection. Instead curl
will re-use the same IP address it already uses for the control
connection.
+Since curl 7.74.0 this option is enabled by default.
+
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
index e68d2e7..29bc672 100644
--- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
+++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -36,11 +36,13 @@ address it already uses for the control connection. But it will use the port
number from the 227-response.
This option thus allows libcurl to work around broken server installations
-that due to NATs, firewalls or incompetence report the wrong IP address back.
+that due to NATs, firewalls or incompetence report the wrong IP address
+back. Setting the option also reduces the risk for various sorts of client
+abuse by malicious servers.
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
.SH DEFAULT
-0
+1 since 7.74.0, was 0 before then.
.SH PROTOCOLS
FTP
.SH EXAMPLE
diff --git a/lib/url.c b/lib/url.c
index 2919a3d..41029d6 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -480,6 +480,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
set->ftp_filemethod = FTPFILE_MULTICWD;
+ set->ftp_skip_ip = TRUE; /* skip PASV IP by default */
#endif
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 63bdeaa..22770c4 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -44,6 +44,7 @@ void config_init(struct OperationConfig *config)
config->tcp_nodelay = TRUE; /* enabled by default */
config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT;
config->http09_allowed = FALSE;
+ config->ftp_skip_ip = TRUE;
}
static void free_config_fields(struct OperationConfig *config)
diff --git a/tests/data/test1400 b/tests/data/test1400
index c0d409b..ade50d4 100644
--- a/tests/data/test1400
+++ b/tests/data/test1400
@@ -76,6 +76,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
diff --git a/tests/data/test1401 b/tests/data/test1401
index ec3b25c..a2e9ef2 100644
--- a/tests/data/test1401
+++ b/tests/data/test1401
@@ -90,6 +90,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE |
(long)CURLPROTO_FTP |
diff --git a/tests/data/test1402 b/tests/data/test1402
index bf7eb7b..99d4b70 100644
--- a/tests/data/test1402
+++ b/tests/data/test1402
@@ -81,6 +81,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
diff --git a/tests/data/test1403 b/tests/data/test1403
index 731d274..90f9b4e 100644
--- a/tests/data/test1403
+++ b/tests/data/test1403
@@ -76,6 +76,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
diff --git a/tests/data/test1404 b/tests/data/test1404
index d3c66a9..d351c3e 100644
--- a/tests/data/test1404
+++ b/tests/data/test1404
@@ -147,6 +147,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
diff --git a/tests/data/test1405 b/tests/data/test1405
index dcc8f80..d1ebb7c 100644
--- a/tests/data/test1405
+++ b/tests/data/test1405
@@ -89,6 +89,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, slist2);
curl_easy_setopt(hnd, CURLOPT_PREQUOTE, slist3);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
diff --git a/tests/data/test1406 b/tests/data/test1406
index 8803c84..31db82a 100644
--- a/tests/data/test1406
+++ b/tests/data/test1406
@@ -79,6 +79,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406");
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com");
curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1);
diff --git a/tests/data/test1407 b/tests/data/test1407
index 917a5de..d329509 100644
--- a/tests/data/test1407
+++ b/tests/data/test1407
@@ -62,6 +62,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 1L);
curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
diff --git a/tests/data/test1420 b/tests/data/test1420
index 03c4584..c1ba190 100644
--- a/tests/data/test1420
+++ b/tests/data/test1420
@@ -67,6 +67,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;MAILINDEX=1");
curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
/* Here is a list of options the curl code used that cannot get generated
--
2.26.2

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,129 @@
From 2ad3b3d39e45a9eeaf6845f393928ef0095893e7 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 2 Dec 2020 23:01:11 +0100
Subject: [PATCH] openssl: make the OCSP verification verify the certificate id
CVE-2020-8286
Reported by anonymous
Bug: https://curl.se/docs/CVE-2020-8286.html
Upstream-commit: d9d01672785b8ac04aab1abb6de95fe3072ae199
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/vtls/openssl.c | 83 ++++++++++++++++++++++++++++++----------------
1 file changed, 54 insertions(+), 29 deletions(-)
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 2e9f900..5803fd1 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -1775,6 +1775,11 @@ static CURLcode verifystatus(struct connectdata *conn,
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;
struct ssl_backend_data *backend = connssl->backend;
+ X509 *cert;
+ OCSP_CERTID *id = NULL;
+ int cert_status, crl_reason;
+ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ int ret;
long len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status);
@@ -1843,43 +1848,63 @@ static CURLcode verifystatus(struct connectdata *conn,
goto end;
}
- for(i = 0; i < OCSP_resp_count(br); i++) {
- int cert_status, crl_reason;
- OCSP_SINGLERESP *single = NULL;
-
- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ /* Compute the certificate's ID */
+ cert = SSL_get_peer_certificate(backend->handle);
+ if(!cert) {
+ failf(data, "Error getting peer certficate");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- single = OCSP_resp_get0(br, i);
- if(!single)
- continue;
+ for(i = 0; i < sk_X509_num(ch); i++) {
+ X509 *issuer = sk_X509_value(ch, i);
+ if(X509_check_issued(issuer, cert) == X509_V_OK) {
+ id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
+ break;
+ }
+ }
+ X509_free(cert);
- cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
- &thisupd, &nextupd);
+ if(!id) {
+ failf(data, "Error computing OCSP ID");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
- failf(data, "OCSP response has expired");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
+ /* Find the single OCSP response corresponding to the certificate ID */
+ ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
+ &thisupd, &nextupd);
+ OCSP_CERTID_free(id);
+ if(ret != 1) {
+ failf(data, "Could not find certificate ID in OCSP response");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- infof(data, "SSL certificate status: %s (%d)\n",
- OCSP_cert_status_str(cert_status), cert_status);
+ /* Validate the corresponding single OCSP response */
+ if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
+ failf(data, "OCSP response has expired");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- switch(cert_status) {
- case V_OCSP_CERTSTATUS_GOOD:
- break;
+ infof(data, "SSL certificate status: %s (%d)\n",
+ OCSP_cert_status_str(cert_status), cert_status);
- case V_OCSP_CERTSTATUS_REVOKED:
- result = CURLE_SSL_INVALIDCERTSTATUS;
+ switch(cert_status) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ break;
- failf(data, "SSL certificate revocation reason: %s (%d)",
- OCSP_crl_reason_str(crl_reason), crl_reason);
- goto end;
+ case V_OCSP_CERTSTATUS_REVOKED:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ failf(data, "SSL certificate revocation reason: %s (%d)",
+ OCSP_crl_reason_str(crl_reason), crl_reason);
+ goto end;
- case V_OCSP_CERTSTATUS_UNKNOWN:
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ default:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
}
end:
--
2.26.2

View file

@ -0,0 +1,64 @@
From 1c875f3e08124c32205a7d33b5c10256ff9352cc Mon Sep 17 00:00:00 2001
From: Viktor Szakats <commit@vsz.me>
Date: Tue, 23 Feb 2021 14:54:46 +0100
Subject: [PATCH] transfer: strip credentials from the auto-referer header
field
Added test 2081 to verify.
CVE-2021-22876
Bug: https://curl.se/docs/CVE-2021-22876.html
Upstream-commit: 7214288898f5625a6cc196e22a74232eada7861c
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/transfer.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/lib/transfer.c b/lib/transfer.c
index 44104ab..3325a0e 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1582,6 +1582,9 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->set.followlocation++; /* count location-followers */
if(data->set.http_auto_referer) {
+ CURLU *u;
+ char *referer;
+
/* We are asked to automatically set the previous URL as the referer
when we get the next URL. We pick the ->url field, which may or may
not be 100% correct */
@@ -1591,9 +1594,26 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->change.referer_alloc = FALSE;
}
- data->change.referer = strdup(data->change.url);
- if(!data->change.referer)
+ /* Make a copy of the URL without crenditals and fragment */
+ u = curl_url();
+ if(!u)
+ return CURLE_OUT_OF_MEMORY;
+
+ uc = curl_url_set(u, CURLUPART_URL, data->change.url, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
+ if(!uc)
+ uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
+ if(!uc)
+ uc = curl_url_get(u, CURLUPART_URL, &referer, 0);
+
+ curl_url_cleanup(u);
+
+ if(uc || referer == NULL)
return CURLE_OUT_OF_MEMORY;
+ data->change.referer = referer;
data->change.referer_alloc = TRUE; /* yes, free this later */
}
}
--
2.26.3

View file

@ -0,0 +1,217 @@
From 840011af52fcdac15a749f14f19b00401a49dc51 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 19 Mar 2021 12:38:49 +0100
Subject: [PATCH] vtls: add 'isproxy' argument to Curl_ssl_get/addsessionid()
To make sure we set and extract the correct session.
Reported-by: Mingtao Yang
Bug: https://curl.se/docs/CVE-2021-22890.html
CVE-2021-22890
Upstream-commit: b09c8ee15771c614c4bf3ddac893cdb12187c844
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/vtls/openssl.c | 52 +++++++++++++++++++++++++++++++++++-----------
lib/vtls/vtls.c | 12 ++++++++---
lib/vtls/vtls.h | 2 ++
3 files changed, 51 insertions(+), 15 deletions(-)
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 5803fd1..16276f3 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -360,12 +360,23 @@ static int ossl_get_ssl_conn_index(void)
*/
static int ossl_get_ssl_sockindex_index(void)
{
- static int ssl_ex_data_sockindex_index = -1;
- if(ssl_ex_data_sockindex_index < 0) {
- ssl_ex_data_sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL,
- NULL);
+ static int sockindex_index = -1;
+ if(sockindex_index < 0) {
+ sockindex_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
}
- return ssl_ex_data_sockindex_index;
+ return sockindex_index;
+}
+
+/* Return an extra data index for proxy boolean.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_proxy_index(void)
+{
+ static int proxy_index = -1;
+ if(proxy_index < 0) {
+ proxy_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ }
+ return proxy_index;
}
static int passwd_callback(char *buf, int num, int encrypting,
@@ -1133,7 +1144,8 @@ static int Curl_ossl_init(void)
Curl_tls_keylog_open();
/* Initialize the extra data indexes */
- if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
+ if(ossl_get_ssl_conn_index() < 0 ||
+ ossl_get_ssl_sockindex_index() < 0 || ossl_get_proxy_index() < 0)
return 0;
return 1;
@@ -2425,8 +2437,10 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
curl_socket_t *sockindex_ptr;
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
+ int proxy_idx = ossl_get_proxy_index();
+ bool isproxy;
- if(connectdata_idx < 0 || sockindex_idx < 0)
+ if(connectdata_idx < 0 || sockindex_idx < 0 || proxy_idx < 0)
return 0;
conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
@@ -2439,13 +2453,18 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
sockindex = (int)(sockindex_ptr - conn->sock);
+ isproxy = SSL_get_ex_data(ssl, proxy_idx) ? TRUE : FALSE;
+
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
void *old_ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
- sockindex));
+ if(isproxy)
+ incache = FALSE;
+ else
+ incache = !(Curl_ssl_getsessionid(conn, isproxy,
+ &old_ssl_sessionid, NULL, sockindex));
if(incache) {
if(old_ssl_sessionid != ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
@@ -2455,7 +2474,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
}
if(!incache) {
- if(!Curl_ssl_addsessionid(conn, ssl_sessionid,
+ if(!Curl_ssl_addsessionid(conn, isproxy, ssl_sessionid,
0 /* unknown size */, sockindex)) {
/* the session has been put into the session cache */
res = 1;
@@ -3170,16 +3189,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
void *ssl_sessionid = NULL;
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
+ int proxy_idx = ossl_get_proxy_index();
- if(connectdata_idx >= 0 && sockindex_idx >= 0) {
+ if(connectdata_idx >= 0 && sockindex_idx >= 0 && proxy_idx >= 0) {
/* Store the data needed for the "new session" callback.
* The sockindex is stored as a pointer to an array element. */
SSL_set_ex_data(backend->handle, connectdata_idx, conn);
SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
+#ifndef CURL_DISABLE_PROXY
+ SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1:
+ NULL);
+#else
+ SSL_set_ex_data(backend->handle, proxy_idx, NULL);
+#endif
+
}
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
+ if(!Curl_ssl_getsessionid(conn, SSL_IS_PROXY() ? TRUE : FALSE,
+ &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
Curl_ssl_sessionid_unlock(conn);
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index c3a55fb..e50fdd2 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -358,6 +358,7 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn)
* there's one suitable, it is provided. Returns TRUE when no entry matched.
*/
bool Curl_ssl_getsessionid(struct connectdata *conn,
+ const bool isProxy,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex)
@@ -369,7 +370,6 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
bool no_match = TRUE;
#ifndef CURL_DISABLE_PROXY
- const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
&conn->proxy_ssl_config :
&conn->ssl_config;
@@ -381,10 +381,15 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
struct ssl_primary_config * const ssl_config = &conn->ssl_config;
const char * const name = conn->host.name;
int port = conn->remote_port;
- (void)sockindex;
#endif
+ (void)sockindex;
*ssl_sessionid = NULL;
+#ifdef CURL_DISABLE_PROXY
+ if(isProxy)
+ return TRUE;
+#endif
+
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
if(!SSL_SET_OPTION(primary.sessionid))
@@ -472,6 +477,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
* later on.
*/
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+ bool isProxy,
void *ssl_sessionid,
size_t idsize,
int sockindex)
@@ -485,7 +491,6 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
int conn_to_port;
long *general_age;
#ifndef CURL_DISABLE_PROXY
- const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
&conn->proxy_ssl_config :
&conn->ssl_config;
@@ -498,6 +503,7 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
const char *hostname = conn->host.name;
(void)sockindex;
#endif
+ (void)sockindex;
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
clone_host = strdup(hostname);
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index bcc8444..343cad0 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -203,6 +203,7 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn);
* under sessionid mutex).
*/
bool Curl_ssl_getsessionid(struct connectdata *conn,
+ const bool isproxy,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex);
@@ -212,6 +213,7 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
* object with cache (e.g. incrementing refcount on success)
*/
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+ const bool isProxy,
void *ssl_sessionid,
size_t idsize,
int sockindex);
--
2.26.3

View file

@ -0,0 +1,788 @@
From c3e2c52593b94bd93775b50063e1d54bc7b1b911 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 18 Feb 2021 10:13:56 +0100
Subject: [PATCH 1/2] urldata: remove the _ORIG suffix from string names
It doesn't provide any useful info but only makes the names longer.
Closes #6624
Upstream-commit: 70472a44deaff387cf8c8c197e04f3add2a96e2e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/doh.c | 12 ++++++------
lib/setopt.c | 38 +++++++++++++++++++-------------------
lib/url.c | 42 +++++++++++++++++++++---------------------
lib/urldata.h | 34 +++++++++++++++++-----------------
lib/vtls/gskit.c | 2 +-
lib/vtls/gtls.c | 2 +-
lib/vtls/mbedtls.c | 4 ++--
lib/vtls/nss.c | 2 +-
lib/vtls/openssl.c | 2 +-
lib/vtls/schannel.c | 2 +-
lib/vtls/sectransp.c | 7 ++++---
lib/vtls/wolfssl.c | 4 ++--
12 files changed, 76 insertions(+), 75 deletions(-)
diff --git a/lib/doh.c b/lib/doh.c
index ebb2c24..cbd34f6 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -318,17 +318,17 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
if(data->set.ssl.primary.verifystatus)
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
- if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
+ if(data->set.str[STRING_SSL_CAFILE]) {
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
- data->set.str[STRING_SSL_CAFILE_ORIG]);
+ data->set.str[STRING_SSL_CAFILE]);
}
- if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
+ if(data->set.str[STRING_SSL_CAPATH]) {
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
- data->set.str[STRING_SSL_CAPATH_ORIG]);
+ data->set.str[STRING_SSL_CAPATH]);
}
- if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
+ if(data->set.str[STRING_SSL_CRLFILE]) {
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
- data->set.str[STRING_SSL_CRLFILE_ORIG]);
+ data->set.str[STRING_SSL_CRLFILE]);
}
if(data->set.ssl.certinfo)
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
diff --git a/lib/setopt.c b/lib/setopt.c
index d621335..58d92e2 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -174,7 +174,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
- result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -187,7 +187,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_TLS13_CIPHERS:
if(Curl_ssl_tls13_ciphersuites()) {
/* set preferred list of TLS 1.3 cipher suites */
- result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
va_arg(param, char *));
}
else
@@ -1643,14 +1643,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file name of the SSL certificate to use
*/
- result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_CERT],
va_arg(param, char *));
break;
case CURLOPT_SSLCERT_BLOB:
/*
* Blob that holds file name of the SSL certificate to use
*/
- result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_ORIG],
+ result = Curl_setblobopt(&data->set.blobs[BLOB_CERT],
va_arg(param, struct curl_blob *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1673,7 +1673,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file type of the SSL certificate to use
*/
- result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1689,14 +1689,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file name of the SSL key to use
*/
- result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_KEY],
va_arg(param, char *));
break;
case CURLOPT_SSLKEY_BLOB:
/*
* Blob that holds file name of the SSL key to use
*/
- result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_ORIG],
+ result = Curl_setblobopt(&data->set.blobs[BLOB_KEY],
va_arg(param, struct curl_blob *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1719,7 +1719,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds file type of the SSL key to use
*/
- result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1735,7 +1735,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* String that holds the SSL or SSH private key password.
*/
- result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1944,7 +1944,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
- result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
va_arg(param, char *));
else
#endif
@@ -1969,7 +1969,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
- result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -1990,7 +1990,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
- result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
va_arg(param, char *));
else
#endif
@@ -2017,7 +2017,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set CRL file info for SSL connection. Specify file name of the CRL
* to check certificates revocation
*/
- result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE],
va_arg(param, char *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -2035,14 +2035,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set Issuer certificate file
* to check certificates issuer
*/
- result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
va_arg(param, char *));
break;
case CURLOPT_ISSUERCERT_BLOB:
/*
* Blob that holds Issuer certificate to check certificates issuer
*/
- result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG],
+ result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT],
va_arg(param, struct curl_blob *));
break;
#ifndef CURL_DISABLE_PROXY
@@ -2638,9 +2638,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
#ifdef USE_TLS_SRP
case CURLOPT_TLSAUTH_USERNAME:
- result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
case CURLOPT_PROXY_TLSAUTH_USERNAME:
@@ -2653,9 +2653,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
break;
case CURLOPT_TLSAUTH_PASSWORD:
- result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
+ result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
diff --git a/lib/url.c b/lib/url.c
index 307b66e..dd18c63 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -543,7 +543,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
*/
if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#if defined(CURL_CA_BUNDLE)
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(result)
return result;
@@ -553,7 +553,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
return result;
#endif
#if defined(CURL_CA_PATH)
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
if(result)
return result;
@@ -3600,17 +3600,17 @@ static CURLcode create_conn(struct Curl_easy *data,
that will be freed as part of the Curl_easy struct, but all cloned
copies will be separately allocated.
*/
- data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
- data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.primary.cipher_list =
- data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
+ data->set.str[STRING_SSL_CIPHER_LIST];
data->set.ssl.primary.cipher_list13 =
- data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
+ data->set.str[STRING_SSL_CIPHER13_LIST];
data->set.ssl.primary.pinned_key =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
- data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
@@ -3636,26 +3636,26 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
- data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
- data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
- data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
- data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
- data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
- data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
- data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.cert = data->set.str[STRING_CERT];
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
+ data->set.ssl.key = data->set.str[STRING_KEY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
#ifdef USE_TLS_SRP
- data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
- data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+ data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
#endif
- data->set.ssl.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
- data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG];
- data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
+ data->set.ssl.cert_blob = data->set.blobs[BLOB_CERT];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
+ data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
&conn->ssl_config)) {
diff --git a/lib/urldata.h b/lib/urldata.h
index df9d998..0fb046f 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1491,9 +1491,9 @@ struct Curl_multi; /* declared and used only in multi.c */
* are catered for in curl_easy_setopt_ccsid()
*/
enum dupstring {
- STRING_CERT_ORIG, /* client certificate file name */
+ STRING_CERT, /* client certificate file name */
STRING_CERT_PROXY, /* client certificate file name */
- STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/
+ STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
STRING_COOKIE, /* HTTP cookie string to send */
STRING_COOKIEJAR, /* dump all cookies to this file */
@@ -1504,11 +1504,11 @@ enum dupstring {
STRING_FTP_ACCOUNT, /* ftp account data */
STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
STRING_FTPPORT, /* port to send with the FTP PORT command */
- STRING_KEY_ORIG, /* private key file name */
+ STRING_KEY, /* private key file name */
STRING_KEY_PROXY, /* private key file name */
- STRING_KEY_PASSWD_ORIG, /* plain text private key password */
+ STRING_KEY_PASSWD, /* plain text private key password */
STRING_KEY_PASSWD_PROXY, /* plain text private key password */
- STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */
+ STRING_KEY_TYPE, /* format for private key (default: PEM) */
STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */
STRING_KRB_LEVEL, /* krb security level */
STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
@@ -1518,22 +1518,22 @@ enum dupstring {
STRING_SET_RANGE, /* range, if used */
STRING_SET_REFERER, /* custom string for the HTTP referer field */
STRING_SET_URL, /* what original URL to work on */
- STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
- STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */
+ STRING_SSL_CAFILE, /* certificate file to verify peer against */
STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
- STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */
+ STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
- STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */
+ STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
- STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */
+ STRING_SSL_CIPHER13_LIST, /* list of TLS 1.3 ciphers to use */
STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
STRING_USERAGENT, /* User-Agent string */
- STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */
+ STRING_SSL_CRLFILE, /* crl file to check certificate */
STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
- STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
+ STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
STRING_SSL_ENGINE, /* name of ssl engine */
STRING_USERNAME, /* <username>, if used */
@@ -1557,9 +1557,9 @@ enum dupstring {
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
- STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth <username> */
+ STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
- STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth <password> */
+ STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
STRING_BEARER, /* <bearer>, if used */
@@ -1593,11 +1593,11 @@ enum dupstring {
};
enum dupblob {
- BLOB_CERT_ORIG,
+ BLOB_CERT,
BLOB_CERT_PROXY,
- BLOB_KEY_ORIG,
+ BLOB_KEY,
BLOB_KEY_PROXY,
- BLOB_SSL_ISSUERCERT_ORIG,
+ BLOB_SSL_ISSUERCERT,
BLOB_SSL_ISSUERCERT_PROXY,
BLOB_LAST
};
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 0538e4a..de9a9db 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -1039,7 +1039,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
/* Check pinned public key. */
ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(!result && ptr) {
curl_X509certificate x509;
curl_asn1Element *p;
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 9b4c365..2ce5749 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -1184,7 +1184,7 @@ gtls_connect_step3(struct connectdata *conn,
}
ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(ptr) {
result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
if(result != CURLE_OK) {
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 545f824..bf3683d 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -546,10 +546,10 @@ mbed_connect_step2(struct connectdata *conn,
#ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = SSL_IS_PROXY() ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#else
const char * const pinnedpubkey =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#endif
conn->recv[sockindex] = mbed_recv;
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index fca2926..9dad33f 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -2131,7 +2131,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
const char * const pinnedpubkey = SSL_IS_PROXY() ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
/* check timeout situation */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 16276f3..acf6577 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -3965,7 +3965,7 @@ static CURLcode servercert(struct connectdata *conn,
result = CURLE_OK;
ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(!result && ptr) {
result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
if(result)
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 1996526..ba82513 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -1243,7 +1243,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
pubkey_ptr = SSL_IS_PROXY() ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(pubkey_ptr) {
result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
if(result) {
diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index 2627aff..120df3a 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -2609,9 +2609,10 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
connssl->connecting_state = ssl_connect_3;
#ifdef SECTRANSP_PINNEDPUBKEY
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
- CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
+ if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ CURLcode result =
+ pkp_pin_peer_pubkey(data, backend->ssl_ctx,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
return result;
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index 7b2a124..fc41748 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -549,12 +549,12 @@ wolfssl_connect_step2(struct connectdata *conn,
conn->http_proxy.host.dispname : conn->host.dispname;
const char * const pinnedpubkey = SSL_IS_PROXY() ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#else
const char * const hostname = conn->host.name;
const char * const dispname = conn->host.dispname;
const char * const pinnedpubkey =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#endif
conn->recv[sockindex] = wolfssl_recv;
--
2.31.1
From fea46e2ddc6050b0aa008033325afbb0606d2b55 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 19 Jun 2021 00:42:28 +0200
Subject: [PATCH 2/2] vtls: fix connection reuse checks for issuer cert and
case sensitivity
CVE-2021-22924
Reported-by: Harry Sintonen
Bug: https://curl.se/docs/CVE-2021-22924.html
Upstream-commit: 5ea3145850ebff1dc2b13d17440300a01ca38161
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 9 ++++++---
lib/urldata.h | 4 ++--
lib/vtls/gtls.c | 10 +++++-----
lib/vtls/nss.c | 4 ++--
lib/vtls/openssl.c | 18 +++++++++---------
lib/vtls/vtls.c | 26 +++++++++++++++++++++-----
6 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index dd18c63..71e226e 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -3602,6 +3602,8 @@ static CURLcode create_conn(struct Curl_easy *data,
*/
data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.primary.cipher_list =
@@ -3625,8 +3627,11 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert =
+ data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert_blob =
+ data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
- data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
@@ -3637,7 +3642,6 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
data->set.ssl.cert = data->set.str[STRING_CERT];
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
data->set.ssl.key = data->set.str[STRING_KEY];
@@ -3655,7 +3659,6 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.ssl.cert_blob = data->set.blobs[BLOB_CERT];
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
- data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
&conn->ssl_config)) {
diff --git a/lib/urldata.h b/lib/urldata.h
index 0fb046f..8b5b597 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -223,6 +223,7 @@ struct ssl_primary_config {
long version_max; /* max supported version the client wants to use*/
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
+ char *issuercert; /* optional issuer certificate filename */
char *clientcert;
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
@@ -230,6 +231,7 @@ struct ssl_primary_config {
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
struct curl_blob *cert_blob;
+ struct curl_blob *issuercert_blob;
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -240,8 +242,6 @@ struct ssl_config_data {
struct ssl_primary_config primary;
long certverifyresult; /* result from the certificate verification */
char *CRLfile; /* CRL to check certificate revocation */
- char *issuercert;/* optional issuer certificate filename */
- struct curl_blob *issuercert_blob;
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
char *cert; /* client certificate file name */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 2ce5749..1b87085 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -851,7 +851,7 @@ gtls_connect_step3(struct connectdata *conn,
if(!chainp) {
if(SSL_CONN_CONFIG(verifypeer) ||
SSL_CONN_CONFIG(verifyhost) ||
- SSL_SET_OPTION(issuercert)) {
+ SSL_CONN_CONFIG(issuercert)) {
#ifdef USE_TLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL
@@ -1035,21 +1035,21 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
- if(SSL_SET_OPTION(issuercert)) {
+ if(SSL_CONN_CONFIG(issuercert)) {
gnutls_x509_crt_init(&x509_issuer);
- issuerp = load_file(SSL_SET_OPTION(issuercert));
+ issuerp = load_file(SSL_CONN_CONFIG(issuercert));
gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
gnutls_x509_crt_deinit(x509_issuer);
unload_file(issuerp);
if(rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
- SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
+ SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_ISSUER_ERROR;
}
infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
- SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
+ SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
}
size = sizeof(certname);
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 9dad33f..d1b0016 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -2159,9 +2159,9 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
if(result)
goto error;
- if(SSL_SET_OPTION(issuercert)) {
+ if(SSL_CONN_CONFIG(issuercert)) {
SECStatus ret = SECFailure;
- char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
+ char *nickname = dup_nickname(data, SSL_CONN_CONFIG(issuercert));
if(nickname) {
/* we support only nicknames in case of issuercert for now */
ret = check_issuer_cert(backend->handle, nickname);
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index acf6577..56171ae 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -3871,10 +3871,10 @@ static CURLcode servercert(struct connectdata *conn,
deallocating the certificate. */
/* e.g. match issuer name with provided issuer certificate */
- if(SSL_SET_OPTION(issuercert) || SSL_SET_OPTION(issuercert_blob)) {
- if(SSL_SET_OPTION(issuercert_blob))
- fp = BIO_new_mem_buf(SSL_SET_OPTION(issuercert_blob)->data,
- (int)SSL_SET_OPTION(issuercert_blob)->len);
+ if(SSL_CONN_CONFIG(issuercert) || SSL_CONN_CONFIG(issuercert_blob)) {
+ if(SSL_CONN_CONFIG(issuercert_blob))
+ fp = BIO_new_mem_buf(SSL_CONN_CONFIG(issuercert_blob)->data,
+ (int)SSL_CONN_CONFIG(issuercert_blob)->len);
else {
fp = BIO_new(BIO_s_file());
if(fp == NULL) {
@@ -3888,10 +3888,10 @@ static CURLcode servercert(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
+ if(BIO_read_filename(fp, SSL_CONN_CONFIG(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3903,7 +3903,7 @@ static CURLcode servercert(struct connectdata *conn,
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -3914,7 +3914,7 @@ static CURLcode servercert(struct connectdata *conn,
if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -3923,7 +3923,7 @@ static CURLcode servercert(struct connectdata *conn,
}
infof(data, " SSL certificate issuer check ok (%s)\n",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
}
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index e50fdd2..855ee66 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -121,6 +121,16 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
return !memcmp(first->data, second->data, first->len); /* same data */
}
+static bool safecmp(char *a, char *b)
+{
+ if(a && b)
+ return !strcmp(a, b);
+ else if(!a && !b)
+ return TRUE; /* match */
+ return FALSE; /* no match */
+}
+
+
bool
Curl_ssl_config_matches(struct ssl_primary_config *data,
struct ssl_primary_config *needle)
@@ -131,11 +141,13 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
(data->verifyhost == needle->verifyhost) &&
(data->verifystatus == needle->verifystatus) &&
blobcmp(data->cert_blob, needle->cert_blob) &&
- Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
- Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
- Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
- Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
- Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
+ blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
+ safecmp(data->CApath, needle->CApath) &&
+ safecmp(data->CAfile, needle->CAfile) &&
+ safecmp(data->issuercert, needle->issuercert) &&
+ safecmp(data->clientcert, needle->clientcert) &&
+ safecmp(data->random_file, needle->random_file) &&
+ safecmp(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
@@ -156,8 +168,10 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->sessionid = source->sessionid;
CLONE_BLOB(cert_blob);
+ CLONE_BLOB(issuercert_blob);
CLONE_STRING(CApath);
CLONE_STRING(CAfile);
+ CLONE_STRING(issuercert);
CLONE_STRING(clientcert);
CLONE_STRING(random_file);
CLONE_STRING(egdsocket);
@@ -172,6 +186,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->issuercert);
Curl_safefree(sslc->clientcert);
Curl_safefree(sslc->random_file);
Curl_safefree(sslc->egdsocket);
@@ -179,6 +194,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
Curl_safefree(sslc->cert_blob);
+ Curl_safefree(sslc->issuercert_blob);
}
#ifdef USE_SSL
--
2.31.1

View file

@ -0,0 +1,31 @@
From ae2dc830fb37e9243dbdaf8b92e41df91f43b3f2 Mon Sep 17 00:00:00 2001
From: Harry Sintonen <sintonen@iki.fi>
Date: Fri, 7 May 2021 13:09:57 +0200
Subject: [PATCH] telnet: check sscanf() for correct number of matches
CVE-2021-22898
Bug: https://curl.se/docs/CVE-2021-22898.html
Upstream-commit: 39ce47f219b09c380b81f89fe54ac586c8db6bde
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/telnet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/telnet.c b/lib/telnet.c
index 1fc5af1..ea6bc71 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -967,7 +967,7 @@ static void suboption(struct connectdata *conn)
size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
+ if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
msnprintf((char *)&temp[len], sizeof(temp) - len,
"%c%s%c%s", CURL_NEW_ENV_VAR, varname,
CURL_NEW_ENV_VALUE, varval);
--
2.31.1

View file

@ -0,0 +1,47 @@
From 2fbbf282e42ae476459f7efe68a88dcb63dcc43b Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 12 Jun 2021 18:25:15 +0200
Subject: [PATCH] telnet: fix option parser to not send uninitialized contents
CVE-2021-22925
Reported-by: Red Hat Product Security
Bug: https://curl.se/docs/CVE-2021-22925.html
Upstream-commit: 894f6ec730597eb243618d33cc84d71add8d6a8a
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/telnet.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/lib/telnet.c b/lib/telnet.c
index ea6bc71..f8428b8 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -967,12 +967,17 @@ static void suboption(struct connectdata *conn)
size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
- msnprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
- CURL_NEW_ENV_VALUE, varval);
- len += tmplen;
- }
+ int rv;
+ char sep[2] = "";
+ varval[0] = 0;
+ rv = sscanf(v->data, "%127[^,]%1[,]%127s", varname, sep, varval);
+ if(rv == 1)
+ len += msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s", CURL_NEW_ENV_VAR, varname);
+ else if(rv >= 2)
+ len += msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+ CURL_NEW_ENV_VALUE, varval);
}
}
msnprintf((char *)&temp[len], sizeof(temp) - len,
--
2.31.1

View file

@ -0,0 +1,33 @@
From bb7619897e53ed424e0712ca5a4c93d5fae99715 Mon Sep 17 00:00:00 2001
From: z2_ on hackerone <>
Date: Tue, 24 Aug 2021 09:50:33 +0200
Subject: [PATCH] mqtt: clear the leftovers pointer when sending succeeds
CVE-2021-22945
Bug: https://curl.se/docs/CVE-2021-22945.html
Upstream-commit: 43157490a5054bd24256fe12876931e8abc9df49
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mqtt.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/mqtt.c b/lib/mqtt.c
index d88fa73..f3fc045 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -123,6 +123,10 @@ static CURLcode mqtt_send(struct connectdata *conn,
mq->sendleftovers = sendleftovers;
mq->nsend = nsend;
}
+ else {
+ mq->sendleftovers = NULL;
+ mq->nsend = 0;
+ }
return result;
}
--
2.31.1

View file

@ -0,0 +1,331 @@
From 03ca8c6faca7de6628f9cbec3001ec6466c88d07 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Wed, 8 Sep 2021 11:56:22 +0200
Subject: [PATCH] ftp,imap,pop3: do not ignore --ssl-reqd
In imap and pop3, check if TLS is required even when capabilities
request has failed.
In ftp, ignore preauthentication (230 status of server greeting) if TLS
is required.
Bug: https://curl.se/docs/CVE-2021-22946.html
CVE-2021-22946
Upstream-commit: 364f174724ef115c63d5e5dc1d3342c8a43b1cca
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/ftp.c | 9 ++++---
lib/imap.c | 24 ++++++++----------
lib/pop3.c | 33 +++++++++++-------------
tests/data/Makefile.inc | 2 ++
tests/data/test984 | 56 +++++++++++++++++++++++++++++++++++++++++
tests/data/test985 | 54 +++++++++++++++++++++++++++++++++++++++
tests/data/test986 | 53 ++++++++++++++++++++++++++++++++++++++
7 files changed, 195 insertions(+), 36 deletions(-)
create mode 100644 tests/data/test984
create mode 100644 tests/data/test985
create mode 100644 tests/data/test986
diff --git a/lib/ftp.c b/lib/ftp.c
index 71c9642..30ebeaa 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2622,9 +2622,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* we have now received a full FTP server response */
switch(ftpc->state) {
case FTP_WAIT220:
- if(ftpcode == 230)
- /* 230 User logged in - already! */
- return ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ if(ftpcode == 230) {
+ /* 230 User logged in - already! Take as 220 if TLS required. */
+ if(data->set.use_ssl <= CURLUSESSL_TRY ||
+ conn->ssl[FIRSTSOCKET].use)
+ return ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ }
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
diff --git a/lib/imap.c b/lib/imap.c
index bda23a5..7e159d4 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -917,22 +917,18 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
line += wordlen;
}
}
- else if(imapcode == IMAP_RESP_OK) {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
- /* We don't have a SSL/TLS connection yet, but SSL is requested */
- if(imapc->tls_supported)
- /* Switch to TLS connection now */
- result = imap_perform_starttls(conn);
- else if(data->set.use_ssl == CURLUSESSL_TRY)
- /* Fallback and carry on with authentication */
- result = imap_perform_authentication(conn);
- else {
- failf(data, "STARTTLS not supported.");
- result = CURLE_USE_SSL_FAILED;
- }
+ else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* PREAUTH is not compatible with STARTTLS. */
+ if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
+ /* Switch to TLS connection now */
+ result = imap_perform_starttls(conn);
}
- else
+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
result = imap_perform_authentication(conn);
+ else {
+ failf(data, "STARTTLS not available.");
+ result = CURLE_USE_SSL_FAILED;
+ }
}
else
result = imap_perform_authentication(conn);
diff --git a/lib/pop3.c b/lib/pop3.c
index 04cc887..3e916ce 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -721,28 +721,23 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
}
}
}
- else if(pop3code == '+') {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
- /* We don't have a SSL/TLS connection yet, but SSL is requested */
- if(pop3c->tls_supported)
- /* Switch to TLS connection now */
- result = pop3_perform_starttls(conn);
- else if(data->set.use_ssl == CURLUSESSL_TRY)
- /* Fallback and carry on with authentication */
- result = pop3_perform_authentication(conn);
- else {
- failf(data, "STLS not supported.");
- result = CURLE_USE_SSL_FAILED;
- }
- }
- else
- result = pop3_perform_authentication(conn);
- }
else {
/* Clear text is supported when CAPA isn't recognised */
- pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+ if(pop3code != '+')
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
- result = pop3_perform_authentication(conn);
+ if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
+ result = pop3_perform_authentication(conn);
+ else if(pop3code == '+' && pop3c->tls_supported)
+ /* Switch to TLS connection now */
+ result = pop3_perform_starttls(conn);
+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = pop3_perform_authentication(conn);
+ else {
+ failf(data, "STLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
}
return result;
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index ef9252b..1ba482b 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -115,6 +115,8 @@ test945 test946 test947 test948 test949 test950 test951 test952 test953 \
test954 test955 test956 test957 test958 test959 test960 test961 test962 \
test963 test964 test965 test966 test967 test968 test969 test970 test971 \
\
+test984 test985 test986 \
+\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
test1016 test1017 test1018 test1019 test1020 test1021 test1022 test1023 \
diff --git a/tests/data/test984 b/tests/data/test984
new file mode 100644
index 0000000..e573f23
--- /dev/null
+++ b/tests/data/test984
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY CAPABILITY A001 BAD Not implemented
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+imap
+</server>
+ <name>
+IMAP require STARTTLS with failing capabilities
+ </name>
+ <command>
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl-reqd
+</command>
+<file name="log/upload%TESTNUMBER">
+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
+From: Fred Foobar <foobar@example.COM>
+Subject: afternoon meeting
+To: joe@example.com
+Message-Id: <B27397-0100000@example.COM>
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
+
+Hello Joe, do you think we can meet at 3:30 tomorrow?
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 64 is CURLE_USE_SSL_FAILED
+<errorcode>
+64
+</errorcode>
+<protocol>
+A001 CAPABILITY
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test985 b/tests/data/test985
new file mode 100644
index 0000000..d0db4aa
--- /dev/null
+++ b/tests/data/test985
@@ -0,0 +1,54 @@
+<testcase>
+<info>
+<keywords>
+POP3
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY CAPA -ERR Not implemented
+</servercmd>
+<data nocheck="yes">
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+pop3
+</server>
+ <name>
+POP3 require STARTTLS with failing capabilities
+ </name>
+ <command>
+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl-reqd
+ </command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 64 is CURLE_USE_SSL_FAILED
+<errorcode>
+64
+</errorcode>
+<protocol>
+CAPA
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test986 b/tests/data/test986
new file mode 100644
index 0000000..a709437
--- /dev/null
+++ b/tests/data/test986
@@ -0,0 +1,53 @@
+<testcase>
+<info>
+<keywords>
+FTP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY welcome 230 Welcome
+REPLY AUTH 500 unknown command
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+ftp
+</server>
+ <name>
+FTP require STARTTLS while preauthenticated
+ </name>
+<file name="log/test%TESTNUMBER.txt">
+data
+ to
+ see
+that FTPS
+works
+ so does it?
+</file>
+ <command>
+--ssl-reqd --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+# 64 is CURLE_USE_SSL_FAILED
+<errorcode>
+64
+</errorcode>
+<protocol>
+AUTH SSL
+AUTH TLS
+</protocol>
+</verify>
+</testcase>
--
2.31.1

View file

@ -0,0 +1,354 @@
From a1ec463c8207bde97b3575d12e396e999a55a8d0 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Tue, 7 Sep 2021 13:26:42 +0200
Subject: [PATCH] ftp,imap,pop3,smtp: reject STARTTLS server response
pipelining
If a server pipelines future responses within the STARTTLS response, the
former are preserved in the pingpong cache across TLS negotiation and
used as responses to the encrypted commands.
This fix detects pipelined STARTTLS responses and rejects them with an
error.
CVE-2021-22947
Bug: https://curl.se/docs/CVE-2021-22947.html
Upstream-commit: 8ef147c43646e91fdaad5d0e7b60351f842e5c68
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/ftp.c | 3 +++
lib/imap.c | 4 +++
lib/pop3.c | 4 +++
lib/smtp.c | 4 +++
tests/data/Makefile.inc | 2 +-
tests/data/test980 | 52 ++++++++++++++++++++++++++++++++++++
tests/data/test981 | 59 +++++++++++++++++++++++++++++++++++++++++
tests/data/test982 | 57 +++++++++++++++++++++++++++++++++++++++
tests/data/test983 | 52 ++++++++++++++++++++++++++++++++++++
9 files changed, 236 insertions(+), 1 deletion(-)
create mode 100644 tests/data/test980
create mode 100644 tests/data/test981
create mode 100644 tests/data/test982
create mode 100644 tests/data/test983
diff --git a/lib/ftp.c b/lib/ftp.c
index 71f998e..e920138 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -2692,6 +2692,9 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_AUTH:
/* we have gotten the response to a previous AUTH command */
+ if(pp->cache_size)
+ return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
+
/* RFC2228 (page 5) says:
*
* If the server is willing to accept the named security mechanism,
diff --git a/lib/imap.c b/lib/imap.c
index feb7445..09bc5d6 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -946,6 +946,10 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.imapc.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(imapcode != IMAP_RESP_OK) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
diff --git a/lib/pop3.c b/lib/pop3.c
index 7698d1c..dccfced 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -753,6 +753,10 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.pop3c.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(pop3code != '+') {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
diff --git a/lib/smtp.c b/lib/smtp.c
index 1defb25..1f89777 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -817,6 +817,10 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.smtpc.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(smtpcode != 220) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied, code %d", smtpcode);
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 163ce59..42b0569 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -115,7 +115,7 @@ test945 test946 test947 test948 test949 test950 test951 test952 test953 \
test954 test955 test956 test957 test958 test959 test960 test961 test962 \
test963 test964 test965 test966 test967 test968 test969 test970 test971 \
\
-test984 test985 test986 \
+test980 test981 test982 test983 test984 test985 test986 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
diff --git a/tests/data/test980 b/tests/data/test980
new file mode 100644
index 0000000..97567f8
--- /dev/null
+++ b/tests/data/test980
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA STARTTLS
+AUTH PLAIN
+REPLY STARTTLS 454 currently unavailable\r\n235 Authenticated\r\n250 2.1.0 Sender ok\r\n250 2.1.5 Recipient ok\r\n354 Enter mail\r\n250 2.0.0 Accepted
+REPLY AUTH 535 5.7.8 Authentication credentials invalid
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+smtp
+</server>
+ <name>
+SMTP STARTTLS pipelined server response
+ </name>
+<stdin>
+mail body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -u user:secret --ssl --sasl-ir -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+EHLO %TESTNUMBER
+STARTTLS
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test981 b/tests/data/test981
new file mode 100644
index 0000000..2b98ce4
--- /dev/null
+++ b/tests/data/test981
@@ -0,0 +1,59 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA STARTTLS
+REPLY STARTTLS A002 BAD currently unavailable\r\nA003 OK Authenticated\r\nA004 OK Accepted
+REPLY LOGIN A003 BAD Authentication credentials invalid
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+imap
+</server>
+ <name>
+IMAP STARTTLS pipelined server response
+ </name>
+ <command>
+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl
+</command>
+<file name="log/upload%TESTNUMBER">
+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
+From: Fred Foobar <foobar@example.COM>
+Subject: afternoon meeting
+To: joe@example.com
+Message-Id: <B27397-0100000@example.COM>
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
+
+Hello Joe, do you think we can meet at 3:30 tomorrow?
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+A001 CAPABILITY
+A002 STARTTLS
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test982 b/tests/data/test982
new file mode 100644
index 0000000..9e07cc0
--- /dev/null
+++ b/tests/data/test982
@@ -0,0 +1,57 @@
+<testcase>
+<info>
+<keywords>
+POP3
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA STLS USER
+REPLY STLS -ERR currently unavailable\r\n+OK user accepted\r\n+OK authenticated
+REPLY PASS -ERR Authentication credentials invalid
+</servercmd>
+<data nocheck="yes">
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+pop3
+</server>
+ <name>
+POP3 STARTTLS pipelined server response
+ </name>
+ <command>
+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl
+ </command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+CAPA
+STLS
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test983 b/tests/data/test983
new file mode 100644
index 0000000..300ec45
--- /dev/null
+++ b/tests/data/test983
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+FTP
+STARTTLS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY AUTH 500 unknown command\r\n500 unknown command\r\n331 give password\r\n230 Authenticated\r\n257 "/"\r\n200 OK\r\n200 OK\r\n200 OK\r\n226 Transfer complete
+REPLY PASS 530 Login incorrect
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<features>
+SSL
+</features>
+<server>
+ftp
+</server>
+ <name>
+FTP STARTTLS pipelined server response
+ </name>
+<file name="log/test%TESTNUMBER.txt">
+data
+ to
+ see
+that FTPS
+works
+ so does it?
+</file>
+ <command>
+--ssl --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret -P %CLIENTIP
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+# 8 is CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+<protocol>
+AUTH SSL
+</protocol>
+</verify>
+</testcase>
--
2.31.1

View file

@ -1,7 +1,7 @@
Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
Name: curl
Version: 7.71.1
Release: 5%{?dist}
Release: 11%{?dist}
License: MIT
Source: https://curl.haxx.se/download/%{name}-%{version}.tar.xz
@ -11,6 +11,42 @@ Patch1: 0001-curl-7.71.1-tool-krb-opt.patch
# setopt: unset NOBODY switches to GET if still HEAD
Patch2: 0002-curl-7.71.1-unset-nobody.patch
# libcurl: wrong connect-only connection (CVE-2020-8231)
Patch4: 0004-curl-7.71.1-CVE-2020-8231.patch
# curl: trusting FTP PASV responses (CVE-2020-8284)
Patch5: 0005-curl-7.71.1-CVE-2020-8284.patch
# libcurl: FTP wildcard stack overflow (CVE-2020-8285)
Patch6: 0006-curl-7.71.1-CVE-2020-8285.patch
# curl: Inferior OCSP verification (CVE-2020-8286)
Patch7: 0007-curl-7.71.1-CVE-2020-8286.patch
# prevent automatic referer from leaking credentials (CVE-2021-22876)
Patch8: 0008-curl-7.71.1-CVE-2021-22876.patch
# fix TLS 1.3 session ticket proxy host mixup (CVE-2021-22890)
Patch9: 0009-curl-7.71.1-CVE-2021-22890.patch
# fix bad connection reuse due to flawed path name checks (CVE-2021-22924)
Patch10: 0010-curl-7.71.1-CVE-2021-22924.patch
# fix TELNET stack contents disclosure (CVE-2021-22898)
Patch11: 0011-curl-7.71.1-CVE-2021-22898.patch
# fix TELNET stack contents disclosure again (CVE-2021-22925)
Patch12: 0012-curl-7.71.1-CVE-2021-22925.patch
# fix use-after-free and double-free in MQTT sending (CVE-2021-22945)
Patch13: 0013-curl-7.71.1-CVE-2021-22945.patch
# fix protocol downgrade required TLS bypass (CVE-2021-22946)
Patch14: 0014-curl-7.71.1-CVE-2021-22946.patch
# fix STARTTLS protocol injection via MITM (CVE-2021-22947)
Patch15: 0015-curl-7.71.1-CVE-2021-22947.patch
# patch making libcurl multilib ready
Patch101: 0101-curl-7.32.0-multilib.patch
@ -33,7 +69,6 @@ BuildRequires: gcc
BuildRequires: groff
BuildRequires: krb5-devel
BuildRequires: libidn2-devel
BuildRequires: libmetalink-devel
BuildRequires: libnghttp2-devel
BuildRequires: libpsl-devel
BuildRequires: libssh-devel
@ -163,7 +198,7 @@ Summary: Conservatively configured build of libcurl for minimal installations
Requires: openssl-libs%{?_isa} >= 1:%{openssl_version}
Provides: libcurl = %{version}-%{release}
Provides: libcurl%{?_isa} = %{version}-%{release}
Conflicts: libcurl
Conflicts: libcurl%{?_isa}
RemovePathPostfixes: .minimal
# needed for RemovePathPostfixes to work with shared libraries
%undefine __brp_ldconfig
@ -180,6 +215,18 @@ be installed.
# upstream patches
%patch1 -p1
%patch2 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
# Fedora patches
%patch101 -p1
@ -226,6 +273,7 @@ export common_configure_opts=" \
--enable-symbol-hiding \
--enable-ipv6 \
--enable-threaded-resolver \
--without-libmetalink \
--with-gssapi \
--with-nghttp2 \
--with-ssl --with-ca-bundle=%{_sysconfdir}/pki/tls/certs/ca-bundle.crt"
@ -241,7 +289,6 @@ export common_configure_opts=" \
--disable-manual \
--without-brotli \
--without-libidn2 \
--without-libmetalink \
--without-libpsl \
--without-libssh
)
@ -255,7 +302,6 @@ export common_configure_opts=" \
--enable-manual \
--with-brotli \
--with-libidn2 \
--with-libmetalink \
--with-libpsl \
--with-libssh
)
@ -358,6 +404,34 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la
%{_libdir}/libcurl.so.4.[0-9].[0-9].minimal
%changelog
* Fri Sep 17 2021 Kamil Dudka <kdudka@redhat.com> - 7.71.1-11
- fix STARTTLS protocol injection via MITM (CVE-2021-22947)
- fix protocol downgrade required TLS bypass (CVE-2021-22946)
- fix use-after-free and double-free in MQTT sending (CVE-2021-22945)
* Wed Jul 21 2021 Kamil Dudka <kdudka@redhat.com> - 7.71.1-10
- fix TELNET stack contents disclosure again (CVE-2021-22925)
- fix TELNET stack contents disclosure (CVE-2021-22898)
- fix bad connection reuse due to flawed path name checks (CVE-2021-22924)
- disable metalink support to fix the following vulnerabilities
CVE-2021-22923 - metalink download sends credentials
CVE-2021-22922 - wrong content via metalink not discarded
* Wed Mar 31 2021 Kamil Dudka <kdudka@redhat.com> - 7.71.1-9
- fix TLS 1.3 session ticket proxy host mixup (CVE-2021-22890)
- prevent automatic referer from leaking credentials (CVE-2021-22876)
* Wed Dec 09 2020 Kamil Dudka <kdudka@redhat.com> - 7.71.1-8
- curl: Inferior OCSP verification (CVE-2020-8286)
- libcurl: FTP wildcard stack overflow (CVE-2020-8285)
- curl: trusting FTP PASV responses (CVE-2020-8284)
* Thu Sep 10 2020 Jinoh Kang <aurhb20@protonmail.ch> - 7.71.1-7
- fix multiarch conflicts in libcurl-minimal (#1877671)
* Wed Aug 19 2020 Kamil Dudka <kdudka@redhat.com> - 7.71.1-6
- libcurl: wrong connect-only connection (CVE-2020-8231)
* Thu Aug 06 2020 Kamil Dudka <kdudka@redhat.com> - 7.71.1-5
- setopt: unset NOBODY switches to GET if still HEAD