You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
8.2 KiB
354 lines
8.2 KiB
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 |
|
@@ -2740,6 +2740,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, |
|
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 |
|
@@ -964,6 +964,10 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data, |
|
|
|
(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 |
|
@@ -771,6 +771,10 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data, |
|
CURLcode result = CURLE_OK; |
|
(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 |
|
@@ -834,6 +834,10 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data, |
|
CURLcode result = CURLE_OK; |
|
(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 |
|
@@ -117,7 +117,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 |
|
|
|
|