diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/0002-curl-7.76.1-CVE-2021-22898.patch b/0002-curl-7.76.1-CVE-2021-22898.patch new file mode 100644 index 0000000..691850b --- /dev/null +++ b/0002-curl-7.76.1-CVE-2021-22898.patch @@ -0,0 +1,31 @@ +From 886f7458bbf005299f3f8224103d1903cd6fa7a4 Mon Sep 17 00:00:00 2001 +From: Harry Sintonen +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 +--- + lib/telnet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/telnet.c b/lib/telnet.c +index f96a4cb..4551435 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -921,7 +921,7 @@ static void suboption(struct Curl_easy *data) + 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 + diff --git a/0003-curl-7.76.1-CVE-2021-22901.patch b/0003-curl-7.76.1-CVE-2021-22901.patch new file mode 100644 index 0000000..1af7204 --- /dev/null +++ b/0003-curl-7.76.1-CVE-2021-22901.patch @@ -0,0 +1,1012 @@ +From c8210a16e8b61704da7bbf4bb0992ecbb1c7746d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 17 May 2021 08:54:00 +0200 +Subject: [PATCH 1/3] conn: add 'attach' to protocol handler, make libssh2 use + it + +The libssh2 backend has SSH session associated with the connection but +the callback context is the easy handle, so when a connection gets +attached to a transfer, the protocol handler now allows for a custom +function to get used to set things up correctly. + +Reported-by: Michael O'Farrell +Fixes #6898 +Closes #7078 + +Upstream-commit: 0c55fbab45bedb761766109d41c3da49c4bc66c6 +Signed-off-by: Kamil Dudka +--- + lib/curl_rtmp.c | 6 ++++++ + lib/dict.c | 1 + + lib/file.c | 1 + + lib/ftp.c | 2 ++ + lib/gopher.c | 2 ++ + lib/http.c | 2 ++ + lib/http2.c | 2 ++ + lib/imap.c | 2 ++ + lib/ldap.c | 2 ++ + lib/mqtt.c | 1 + + lib/multi.c | 2 ++ + lib/openldap.c | 2 ++ + lib/pop3.c | 2 ++ + lib/rtsp.c | 1 + + lib/smb.c | 2 ++ + lib/smtp.c | 2 ++ + lib/telnet.c | 1 + + lib/tftp.c | 1 + + lib/url.c | 1 + + lib/urldata.h | 4 ++++ + lib/vssh/libssh.c | 2 ++ + lib/vssh/libssh2.c | 20 ++++++++++++++++++++ + lib/vssh/ssh.h | 3 +++ + lib/vssh/wolfssh.c | 2 ++ + 24 files changed, 66 insertions(+) + +diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c +index 1360f33..2fa0267 100644 +--- a/lib/curl_rtmp.c ++++ b/lib/curl_rtmp.c +@@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_rtmp = { + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMP, /* protocol */ + CURLPROTO_RTMP, /* family */ +@@ -101,6 +102,7 @@ const struct Curl_handler Curl_handler_rtmpt = { + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPT, /* protocol */ + CURLPROTO_RTMPT, /* family */ +@@ -123,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = { + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMPE, /* protocol */ + CURLPROTO_RTMPE, /* family */ +@@ -145,6 +148,7 @@ const struct Curl_handler Curl_handler_rtmpte = { + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPTE, /* protocol */ + CURLPROTO_RTMPTE, /* family */ +@@ -167,6 +171,7 @@ const struct Curl_handler Curl_handler_rtmps = { + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPS, /* protocol */ + CURLPROTO_RTMP, /* family */ +@@ -189,6 +194,7 @@ const struct Curl_handler Curl_handler_rtmpts = { + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPTS, /* protocol */ + CURLPROTO_RTMPT, /* family */ +diff --git a/lib/dict.c b/lib/dict.c +index 4319dad..7b27f79 100644 +--- a/lib/dict.c ++++ b/lib/dict.c +@@ -89,6 +89,7 @@ const struct Curl_handler Curl_handler_dict = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_DICT, /* defport */ + CURLPROTO_DICT, /* protocol */ + CURLPROTO_DICT, /* family */ +diff --git a/lib/file.c b/lib/file.c +index 1d174e5..10d8f05 100644 +--- a/lib/file.c ++++ b/lib/file.c +@@ -111,6 +111,7 @@ const struct Curl_handler Curl_handler_file = { + file_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + 0, /* defport */ + CURLPROTO_FILE, /* protocol */ + CURLPROTO_FILE, /* family */ +diff --git a/lib/ftp.c b/lib/ftp.c +index 5bf44f1..5ef1e2e 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -175,6 +175,7 @@ const struct Curl_handler Curl_handler_ftp = { + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_FTP, /* defport */ + CURLPROTO_FTP, /* protocol */ + CURLPROTO_FTP, /* family */ +@@ -205,6 +206,7 @@ const struct Curl_handler Curl_handler_ftps = { + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_FTPS, /* defport */ + CURLPROTO_FTPS, /* protocol */ + CURLPROTO_FTP, /* family */ +diff --git a/lib/gopher.c b/lib/gopher.c +index a39cc7e..f61232f 100644 +--- a/lib/gopher.c ++++ b/lib/gopher.c +@@ -74,6 +74,7 @@ const struct Curl_handler Curl_handler_gopher = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_GOPHER, /* defport */ + CURLPROTO_GOPHER, /* protocol */ + CURLPROTO_GOPHER, /* family */ +@@ -97,6 +98,7 @@ const struct Curl_handler Curl_handler_gophers = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_GOPHER, /* defport */ + CURLPROTO_GOPHERS, /* protocol */ + CURLPROTO_GOPHER, /* family */ +diff --git a/lib/http.c b/lib/http.c +index 02c81c4..91da200 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -133,6 +133,7 @@ const struct Curl_handler Curl_handler_http = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + CURLPROTO_HTTP, /* family */ +@@ -160,6 +161,7 @@ const struct Curl_handler Curl_handler_https = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_HTTPS, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + CURLPROTO_HTTP, /* family */ +diff --git a/lib/http2.c b/lib/http2.c +index d0f69ea..1eb4e89 100644 +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -319,6 +319,7 @@ static const struct Curl_handler Curl_handler_http2 = { + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + http2_conncheck, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + CURLPROTO_HTTP, /* family */ +@@ -341,6 +342,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = { + http2_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + http2_conncheck, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTPS, /* protocol */ + CURLPROTO_HTTP, /* family */ +diff --git a/lib/imap.c b/lib/imap.c +index e887357..e50d7fd 100644 +--- a/lib/imap.c ++++ b/lib/imap.c +@@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_imap = { + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_IMAP, /* defport */ + CURLPROTO_IMAP, /* protocol */ + CURLPROTO_IMAP, /* family */ +@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_imaps = { + imap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_IMAPS, /* defport */ + CURLPROTO_IMAPS, /* protocol */ + CURLPROTO_IMAP, /* family */ +diff --git a/lib/ldap.c b/lib/ldap.c +index 860a4a8..d632a7e 100644 +--- a/lib/ldap.c ++++ b/lib/ldap.c +@@ -149,6 +149,7 @@ const struct Curl_handler Curl_handler_ldap = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + CURLPROTO_LDAP, /* family */ +@@ -176,6 +177,7 @@ const struct Curl_handler Curl_handler_ldaps = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + CURLPROTO_LDAP, /* family */ +diff --git a/lib/mqtt.c b/lib/mqtt.c +index 2134409..d88fa73 100644 +--- a/lib/mqtt.c ++++ b/lib/mqtt.c +@@ -86,6 +86,7 @@ const struct Curl_handler Curl_handler_mqtt = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_MQTT, /* defport */ + CURLPROTO_MQTT, /* protocol */ + CURLPROTO_MQTT, /* family */ +diff --git a/lib/multi.c b/lib/multi.c +index be3e41f..e624bc3 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -890,6 +890,8 @@ void Curl_attach_connnection(struct Curl_easy *data, + data->conn = conn; + Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data, + &data->conn_queue); ++ if(conn->handler->attach) ++ conn->handler->attach(data, conn); + } + + static int waitconnect_getsock(struct connectdata *conn, +diff --git a/lib/openldap.c b/lib/openldap.c +index b6980c5..b515554 100644 +--- a/lib/openldap.c ++++ b/lib/openldap.c +@@ -107,6 +107,7 @@ const struct Curl_handler Curl_handler_ldap = { + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + CURLPROTO_LDAP, /* family */ +@@ -134,6 +135,7 @@ const struct Curl_handler Curl_handler_ldaps = { + ldap_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + CURLPROTO_LDAP, /* family */ +diff --git a/lib/pop3.c b/lib/pop3.c +index ccfebd0..6168b12 100644 +--- a/lib/pop3.c ++++ b/lib/pop3.c +@@ -131,6 +131,7 @@ const struct Curl_handler Curl_handler_pop3 = { + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_POP3, /* defport */ + CURLPROTO_POP3, /* protocol */ + CURLPROTO_POP3, /* family */ +@@ -159,6 +160,7 @@ const struct Curl_handler Curl_handler_pop3s = { + pop3_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_POP3S, /* defport */ + CURLPROTO_POP3S, /* protocol */ + CURLPROTO_POP3, /* family */ +diff --git a/lib/rtsp.c b/lib/rtsp.c +index 3029ff5..cdd49dc 100644 +--- a/lib/rtsp.c ++++ b/lib/rtsp.c +@@ -109,6 +109,7 @@ const struct Curl_handler Curl_handler_rtsp = { + rtsp_disconnect, /* disconnect */ + rtsp_rtp_readwrite, /* readwrite */ + rtsp_conncheck, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_RTSP, /* defport */ + CURLPROTO_RTSP, /* protocol */ + CURLPROTO_RTSP, /* family */ +diff --git a/lib/smb.c b/lib/smb.c +index 183bc12..9f65cfd 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -88,6 +88,7 @@ const struct Curl_handler Curl_handler_smb = { + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SMB, /* defport */ + CURLPROTO_SMB, /* protocol */ + CURLPROTO_SMB, /* family */ +@@ -114,6 +115,7 @@ const struct Curl_handler Curl_handler_smbs = { + smb_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SMBS, /* defport */ + CURLPROTO_SMBS, /* protocol */ + CURLPROTO_SMB, /* family */ +diff --git a/lib/smtp.c b/lib/smtp.c +index be4cd67..1defb25 100644 +--- a/lib/smtp.c ++++ b/lib/smtp.c +@@ -136,6 +136,7 @@ const struct Curl_handler Curl_handler_smtp = { + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SMTP, /* defport */ + CURLPROTO_SMTP, /* protocol */ + CURLPROTO_SMTP, /* family */ +@@ -164,6 +165,7 @@ const struct Curl_handler Curl_handler_smtps = { + smtp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SMTPS, /* defport */ + CURLPROTO_SMTPS, /* protocol */ + CURLPROTO_SMTP, /* family */ +diff --git a/lib/telnet.c b/lib/telnet.c +index 4551435..fdd137f 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -185,6 +185,7 @@ const struct Curl_handler Curl_handler_telnet = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_TELNET, /* defport */ + CURLPROTO_TELNET, /* protocol */ + CURLPROTO_TELNET, /* family */ +diff --git a/lib/tftp.c b/lib/tftp.c +index 76d3ff4..bf499f3 100644 +--- a/lib/tftp.c ++++ b/lib/tftp.c +@@ -182,6 +182,7 @@ const struct Curl_handler Curl_handler_tftp = { + tftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_TFTP, /* defport */ + CURLPROTO_TFTP, /* protocol */ + CURLPROTO_TFTP, /* family */ +diff --git a/lib/url.c b/lib/url.c +index 19fcfb8..9f2c9f2 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -292,6 +292,7 @@ static const struct Curl_handler Curl_handler_dummy = { + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + 0, /* defport */ + 0, /* protocol */ + 0, /* family */ +diff --git a/lib/urldata.h b/lib/urldata.h +index fec8756..2bb7d81 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -791,12 +791,16 @@ struct Curl_handler { + struct connectdata *conn, + unsigned int checks_to_perform); + ++ /* attach() attaches this transfer to this connection */ ++ void (*attach)(struct Curl_easy *data, struct connectdata *conn); ++ + int defport; /* Default port. */ + unsigned int protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ + unsigned int family; /* single bit for protocol family; basically the + non-TLS name of the protocol this is */ + unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ ++ + }; + + #define PROTOPT_NONE 0 /* nothing extra */ +diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c +index 4644f4c..450ab28 100644 +--- a/lib/vssh/libssh.c ++++ b/lib/vssh/libssh.c +@@ -159,6 +159,7 @@ const struct Curl_handler Curl_handler_scp = { + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + CURLPROTO_SCP, /* family */ +@@ -185,6 +186,7 @@ const struct Curl_handler Curl_handler_sftp = { + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + CURLPROTO_SFTP, /* family */ +diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c +index 9d188d0..0a468dd 100644 +--- a/lib/vssh/libssh2.c ++++ b/lib/vssh/libssh2.c +@@ -121,6 +121,7 @@ static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn, + curl_socket_t *sock); + static CURLcode ssh_setup_connection(struct Curl_easy *data, + struct connectdata *conn); ++static void ssh_attach(struct Curl_easy *data, struct connectdata *conn); + + /* + * SCP protocol handler. +@@ -142,6 +143,7 @@ const struct Curl_handler Curl_handler_scp = { + scp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ssh_attach, + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + CURLPROTO_SCP, /* family */ +@@ -170,6 +172,7 @@ const struct Curl_handler Curl_handler_sftp = { + sftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ssh_attach, + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + CURLPROTO_SFTP, /* family */ +@@ -3607,4 +3610,21 @@ size_t Curl_ssh_version(char *buffer, size_t buflen) + return msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION); + } + ++/* The SSH session is associated with the *CONNECTION* but the callback user ++ * pointer is an easy handle pointer. This function allows us to reassign the ++ * user pointer to the *CURRENT* (new) easy handle. ++ */ ++static void ssh_attach(struct Curl_easy *data, struct connectdata *conn) ++{ ++ DEBUGASSERT(data); ++ DEBUGASSERT(conn); ++ if(conn->handler->protocol & PROTO_FAMILY_SSH) { ++ struct ssh_conn *sshc = &conn->proto.sshc; ++ if(sshc->ssh_session) { ++ /* only re-attach if the session already exists */ ++ void **abstract = libssh2_session_abstract(sshc->ssh_session); ++ *abstract = data; ++ } ++ } ++} + #endif /* USE_LIBSSH2 */ +diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h +index 52e1ee6..505b078 100644 +--- a/lib/vssh/ssh.h ++++ b/lib/vssh/ssh.h +@@ -263,9 +263,12 @@ extern const struct Curl_handler Curl_handler_sftp; + CURLcode Curl_ssh_init(void); + void Curl_ssh_cleanup(void); + size_t Curl_ssh_version(char *buffer, size_t buflen); ++void Curl_ssh_attach(struct Curl_easy *data, ++ struct connectdata *conn); + #else + /* for non-SSH builds */ + #define Curl_ssh_cleanup() ++#define Curl_ssh_attach(x,y) + #endif + + #endif /* HEADER_CURL_SSH_H */ +diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c +index de0b1c7..8aa8067 100644 +--- a/lib/vssh/wolfssh.c ++++ b/lib/vssh/wolfssh.c +@@ -91,6 +91,7 @@ const struct Curl_handler Curl_handler_scp = { + wscp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SSH, /* defport */ + CURLPROTO_SCP, /* protocol */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION +@@ -119,6 +120,7 @@ const struct Curl_handler Curl_handler_sftp = { + wsftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + ZERO_NULL, /* connection_check */ ++ ZERO_NULL, /* attach connection */ + PORT_SSH, /* defport */ + CURLPROTO_SFTP, /* protocol */ + CURLPROTO_SFTP, /* family */ +-- +2.31.1 + + +From b5971f4854aab00fcd7810aa9a425c0a6790e050 Mon Sep 17 00:00:00 2001 +From: Harry Sintonen +Date: Wed, 5 May 2021 13:42:26 +0200 +Subject: [PATCH 2/3] openssl: associate/detach the transfer from connection + +CVE-2021-22901 + +Bug: https://curl.se/docs/CVE-2021-22901.html + +Upstream-commit: 7f4a9a9b2a49547eae24d2e19bc5c346e9026479 +Signed-off-by: Kamil Dudka +--- + lib/multi.c | 5 +- + lib/vtls/gskit.c | 4 +- + lib/vtls/gtls.c | 4 +- + lib/vtls/mbedtls.c | 4 +- + lib/vtls/mesalink.c | 4 +- + lib/vtls/nss.c | 4 +- + lib/vtls/openssl.c | 146 +++++++++++++++++++++++++++++++------------ + lib/vtls/rustls.c | 4 +- + lib/vtls/schannel.c | 4 +- + lib/vtls/sectransp.c | 2 + + lib/vtls/vtls.c | 23 ++++++- + lib/vtls/vtls.h | 12 ++++ + lib/vtls/wolfssl.c | 4 +- + 13 files changed, 171 insertions(+), 49 deletions(-) + +diff --git a/lib/multi.c b/lib/multi.c +index e624bc3..2228264 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -872,8 +872,10 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi) + void Curl_detach_connnection(struct Curl_easy *data) + { + struct connectdata *conn = data->conn; +- if(conn) ++ if(conn) { + Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL); ++ Curl_ssl_detach_conn(data, conn); ++ } + data->conn = NULL; + } + +@@ -892,6 +894,7 @@ void Curl_attach_connnection(struct Curl_easy *data, + &data->conn_queue); + if(conn->handler->attach) + conn->handler->attach(data, conn); ++ Curl_ssl_associate_conn(data, conn); + } + + static int waitconnect_getsock(struct connectdata *conn, +diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c +index b0c7343..3fe54c1 100644 +--- a/lib/vtls/gskit.c ++++ b/lib/vtls/gskit.c +@@ -1281,7 +1281,9 @@ const struct Curl_ssl Curl_ssl_gskit = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- NULL /* sha256sum */ ++ NULL, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif /* USE_GSKIT */ +diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c +index e3fad7f..ea54fe3 100644 +--- a/lib/vtls/gtls.c ++++ b/lib/vtls/gtls.c +@@ -1645,7 +1645,9 @@ const struct Curl_ssl Curl_ssl_gnutls = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- gtls_sha256sum /* sha256sum */ ++ gtls_sha256sum, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif /* USE_GNUTLS */ +diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c +index 4b36f2d..0a9f7b4 100644 +--- a/lib/vtls/mbedtls.c ++++ b/lib/vtls/mbedtls.c +@@ -1113,7 +1113,9 @@ const struct Curl_ssl Curl_ssl_mbedtls = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- mbedtls_sha256sum /* sha256sum */ ++ mbedtls_sha256sum, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif /* USE_MBEDTLS */ +diff --git a/lib/vtls/mesalink.c b/lib/vtls/mesalink.c +index 5d6a149..0a41dd3 100644 +--- a/lib/vtls/mesalink.c ++++ b/lib/vtls/mesalink.c +@@ -667,7 +667,9 @@ const struct Curl_ssl Curl_ssl_mesalink = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- NULL /* sha256sum */ ++ NULL, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif +diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c +index a9f6959..ae3945c 100644 +--- a/lib/vtls/nss.c ++++ b/lib/vtls/nss.c +@@ -2442,7 +2442,9 @@ const struct Curl_ssl Curl_ssl_nss = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + nss_false_start, /* false_start */ +- nss_sha256sum /* sha256sum */ ++ nss_sha256sum, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif /* USE_NSS */ +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 6583300..2404393 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -246,6 +246,10 @@ struct ssl_backend_data { + #endif + }; + ++static void ossl_associate_connection(struct Curl_easy *data, ++ struct connectdata *conn, ++ int sockindex); ++ + /* + * Number of bytes to read from the random number seed file. This must be + * a finite value (because some entropy "files" like /dev/urandom have +@@ -2528,6 +2532,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ctx_option_t ctx_options = 0; ++ void *ssl_sessionid = NULL; + + #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + bool sni; +@@ -3209,46 +3214,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + } + #endif + +- /* Check if there's a cached ID we can/should use here! */ +- if(SSL_SET_OPTION(primary.sessionid)) { +- void *ssl_sessionid = NULL; +- int data_idx = ossl_get_ssl_data_index(); +- int connectdata_idx = ossl_get_ssl_conn_index(); +- int sockindex_idx = ossl_get_ssl_sockindex_index(); +- int proxy_idx = ossl_get_proxy_index(); +- +- if(data_idx >= 0 && 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, data_idx, data); +- 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 +- +- } ++ ossl_associate_connection(data, conn, sockindex); + +- Curl_ssl_sessionid_lock(data); +- if(!Curl_ssl_getsessionid(data, 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(data); +- failf(data, "SSL: SSL_set_session failed: %s", +- ossl_strerror(ERR_get_error(), error_buffer, +- sizeof(error_buffer))); +- return CURLE_SSL_CONNECT_ERROR; +- } +- /* Informational message */ +- infof(data, "SSL re-using session ID\n"); ++ Curl_ssl_sessionid_lock(data); ++ if(!Curl_ssl_getsessionid(data, 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(data); ++ failf(data, "SSL: SSL_set_session failed: %s", ++ ossl_strerror(ERR_get_error(), error_buffer, ++ sizeof(error_buffer))); ++ return CURLE_SSL_CONNECT_ERROR; + } +- Curl_ssl_sessionid_unlock(data); ++ /* Informational message */ ++ infof(data, "SSL re-using session ID\n"); + } ++ Curl_ssl_sessionid_unlock(data); + + #ifndef CURL_DISABLE_PROXY + if(conn->proxy_ssl[sockindex].use) { +@@ -4474,6 +4456,90 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl, + (void *)backend->ctx : (void *)backend->handle; + } + ++static void ossl_associate_connection(struct Curl_easy *data, ++ struct connectdata *conn, ++ int sockindex) ++{ ++ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ++ struct ssl_backend_data *backend = connssl->backend; ++ ++ /* If we don't have SSL context, do nothing. */ ++ if(!backend->handle) ++ return; ++ ++ if(SSL_SET_OPTION(primary.sessionid)) { ++ int data_idx = ossl_get_ssl_data_index(); ++ int connectdata_idx = ossl_get_ssl_conn_index(); ++ int sockindex_idx = ossl_get_ssl_sockindex_index(); ++ int proxy_idx = ossl_get_proxy_index(); ++ ++ if(data_idx >= 0 && 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, data_idx, data); ++ 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 ++ } ++ } ++} ++ ++/* ++ * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after ++ * the handshake. If the transfer that sets up the callback gets killed before ++ * this callback arrives, we must make sure to properly clear the data to ++ * avoid UAF problems. A future optimization could be to instead store another ++ * transfer that might still be using the same connection. ++ */ ++ ++static void ossl_disassociate_connection(struct Curl_easy *data, ++ int sockindex) ++{ ++ struct connectdata *conn = data->conn; ++ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ++ struct ssl_backend_data *backend = connssl->backend; ++ ++ /* If we don't have SSL context, do nothing. */ ++ if(!backend->handle) ++ return; ++ ++ if(SSL_SET_OPTION(primary.sessionid)) { ++ bool isproxy = FALSE; ++ bool incache; ++ void *old_ssl_sessionid = NULL; ++ int data_idx = ossl_get_ssl_data_index(); ++ int connectdata_idx = ossl_get_ssl_conn_index(); ++ int sockindex_idx = ossl_get_ssl_sockindex_index(); ++ int proxy_idx = ossl_get_proxy_index(); ++ ++ if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 && ++ proxy_idx >= 0) { ++ /* Invalidate the session cache entry, if any */ ++ isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE; ++ ++ /* Disable references to data in "new session" callback to avoid ++ * accessing a stale pointer. */ ++ SSL_set_ex_data(backend->handle, data_idx, NULL); ++ SSL_set_ex_data(backend->handle, connectdata_idx, NULL); ++ SSL_set_ex_data(backend->handle, sockindex_idx, NULL); ++ SSL_set_ex_data(backend->handle, proxy_idx, NULL); ++ } ++ ++ Curl_ssl_sessionid_lock(data); ++ incache = !(Curl_ssl_getsessionid(data, conn, isproxy, ++ &old_ssl_sessionid, NULL, sockindex)); ++ if(incache) ++ Curl_ssl_delsessionid(data, old_ssl_sessionid); ++ Curl_ssl_sessionid_unlock(data); ++ } ++} ++ + const struct Curl_ssl Curl_ssl_openssl = { + { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ + +@@ -4508,10 +4574,12 @@ const struct Curl_ssl Curl_ssl_openssl = { + ossl_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) +- ossl_sha256sum /* sha256sum */ ++ ossl_sha256sum, /* sha256sum */ + #else +- NULL /* sha256sum */ ++ NULL, /* sha256sum */ + #endif ++ ossl_associate_connection, /* associate_connection */ ++ ossl_disassociate_connection /* disassociate_connection */ + }; + + #endif /* USE_OPENSSL */ +diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c +index e4f589d..fb8d634 100644 +--- a/lib/vtls/rustls.c ++++ b/lib/vtls/rustls.c +@@ -554,7 +554,9 @@ const struct Curl_ssl Curl_ssl_rustls = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- NULL /* sha256sum */ ++ NULL, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif /* USE_RUSTLS */ +diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c +index 961a71f..a80eb50 100644 +--- a/lib/vtls/schannel.c ++++ b/lib/vtls/schannel.c +@@ -2429,7 +2429,9 @@ const struct Curl_ssl Curl_ssl_schannel = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- schannel_sha256sum /* sha256sum */ ++ schannel_sha256sum, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif /* USE_SCHANNEL */ +diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c +index 9d637da..b24b489 100644 +--- a/lib/vtls/sectransp.c ++++ b/lib/vtls/sectransp.c +@@ -3314,6 +3314,8 @@ const struct Curl_ssl Curl_ssl_sectransp = { + Curl_none_engines_list, /* engines_list */ + sectransp_false_start, /* false_start */ + sectransp_sha256sum /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #ifdef __clang__ +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 2e07df0..22cfb88 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -579,6 +579,25 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data, + return CURLE_OK; + } + ++void Curl_ssl_associate_conn(struct Curl_easy *data, ++ struct connectdata *conn) ++{ ++ if(Curl_ssl->associate_connection) { ++ Curl_ssl->associate_connection(data, conn, FIRSTSOCKET); ++ if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted) ++ Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET); ++ } ++} ++ ++void Curl_ssl_detach_conn(struct Curl_easy *data, ++ struct connectdata *conn) ++{ ++ if(Curl_ssl->disassociate_connection) { ++ Curl_ssl->disassociate_connection(data, FIRSTSOCKET); ++ if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted) ++ Curl_ssl->disassociate_connection(data, SECONDARYSOCKET); ++ } ++} + + void Curl_ssl_close_all(struct Curl_easy *data) + { +@@ -1207,7 +1226,9 @@ static const struct Curl_ssl Curl_ssl_multi = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- NULL /* sha256sum */ ++ NULL, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + const struct Curl_ssl *Curl_ssl = +diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h +index 2b43e77..78d1003 100644 +--- a/lib/vtls/vtls.h ++++ b/lib/vtls/vtls.h +@@ -83,6 +83,11 @@ struct Curl_ssl { + bool (*false_start)(void); + CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, + unsigned char *sha256sum, size_t sha256sumlen); ++ ++ void (*associate_connection)(struct Curl_easy *data, ++ struct connectdata *conn, ++ int sockindex); ++ void (*disassociate_connection)(struct Curl_easy *data, int sockindex); + }; + + #ifdef USE_SSL +@@ -277,6 +282,11 @@ bool Curl_ssl_cert_status_request(void); + + bool Curl_ssl_false_start(void); + ++void Curl_ssl_associate_conn(struct Curl_easy *data, ++ struct connectdata *conn); ++void Curl_ssl_detach_conn(struct Curl_easy *data, ++ struct connectdata *conn); ++ + #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + + #else /* if not USE_SSL */ +@@ -303,6 +313,8 @@ bool Curl_ssl_false_start(void); + #define Curl_ssl_cert_status_request() FALSE + #define Curl_ssl_false_start() FALSE + #define Curl_ssl_tls13_ciphersuites() FALSE ++#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt ++#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt + #endif + + #endif /* HEADER_CURL_VTLS_H */ +diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c +index c6f4280..9c1598b 100644 +--- a/lib/vtls/wolfssl.c ++++ b/lib/vtls/wolfssl.c +@@ -1164,7 +1164,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ +- wolfssl_sha256sum /* sha256sum */ ++ wolfssl_sha256sum, /* sha256sum */ ++ NULL, /* associate_connection */ ++ NULL /* disassociate_connection */ + }; + + #endif +-- +2.31.1 + + +From dd657bd43c0dc406a0be442a3b6546b3f97bb13f Mon Sep 17 00:00:00 2001 +From: Koichi Shiraishi +Date: Mon, 24 May 2021 20:26:44 +0900 +Subject: [PATCH 3/3] sectransp: fix 7f4a9a9b2a49 commit about missing comma + +Follow-up to 7f4a9a9b2a495 + +Closes #7119 + +Upstream-commit: 98770344b2d6527c5b504fa740d7bbddbee1728e +Signed-off-by: Kamil Dudka +--- + lib/vtls/sectransp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c +index b24b489..f2d7835 100644 +--- a/lib/vtls/sectransp.c ++++ b/lib/vtls/sectransp.c +@@ -3313,7 +3313,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + sectransp_false_start, /* false_start */ +- sectransp_sha256sum /* sha256sum */ ++ sectransp_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ + }; +-- +2.31.1 + diff --git a/0004-curl-7.76.1-ldaps-segv.patch b/0004-curl-7.76.1-ldaps-segv.patch new file mode 100644 index 0000000..23f77b1 --- /dev/null +++ b/0004-curl-7.76.1-ldaps-segv.patch @@ -0,0 +1,44 @@ +From 39b68b3f82535d06e50443db4c191dbaa00df4eb Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +Date: Fri, 23 Apr 2021 00:33:46 +0200 +Subject: [PATCH] vtls: reset ssl use flag upon negotiation failure + +Fixes the segfault in ldaps disconnect. + +Reported-by: Illarion Taev +Fixes #6934 +Closes #6937 + +Upstream-commit: a4554b2c5e7c5788c8198001598818599c60ff7d +Signed-off-by: Kamil Dudka +--- + lib/vtls/vtls.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 22cfb88..fa8a6fa 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -315,6 +315,8 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn, + + if(!result) + Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ ++ else ++ conn->ssl[sockindex].use = FALSE; + + return result; + } +@@ -338,7 +340,9 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn, + /* mark this is being ssl requested from here on. */ + conn->ssl[sockindex].use = TRUE; + result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done); +- if(!result && *done) ++ if(result) ++ conn->ssl[sockindex].use = FALSE; ++ else if(*done) + Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */ + return result; + } +-- +2.31.1 + diff --git a/0005-curl-7.76.1-CVE-2021-22924.patch b/0005-curl-7.76.1-CVE-2021-22924.patch new file mode 100644 index 0000000..3160b8f --- /dev/null +++ b/0005-curl-7.76.1-CVE-2021-22924.patch @@ -0,0 +1,279 @@ +From 30c7b4dd01734b6ba20bfc7790b9fe8bc0500214 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 19 Jun 2021 00:42:28 +0200 +Subject: [PATCH] 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 +--- + lib/url.c | 10 ++++++---- + 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(+), 27 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 9f2c9f2..bdcb095 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -3723,6 +3723,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 = +@@ -3747,8 +3749,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_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; +@@ -3757,7 +3762,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_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]; +@@ -3771,9 +3775,7 @@ static CURLcode create_conn(struct Curl_easy *data, + data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; + #endif + #endif +- + 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 2bb7d81..7cf63d0 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -246,6 +246,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 */ +@@ -253,6 +254,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; + char *curves; /* list of curves to use */ + BIT(verifypeer); /* set TRUE if this is desired */ + BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */ +@@ -264,8 +266,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_type; /* format for certificate (default: PEM)*/ +diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c +index ea54fe3..ccc5ce8 100644 +--- a/lib/vtls/gtls.c ++++ b/lib/vtls/gtls.c +@@ -849,7 +849,7 @@ gtls_connect_step3(struct Curl_easy *data, + if(!chainp) { + if(SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost) || +- SSL_SET_OPTION(issuercert)) { ++ SSL_CONN_CONFIG(issuercert)) { + #ifdef HAVE_GNUTLS_SRP + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL +@@ -1033,21 +1033,21 @@ gtls_connect_step3(struct Curl_easy *data, + 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 ae3945c..b0b1e8c 100644 +--- a/lib/vtls/nss.c ++++ b/lib/vtls/nss.c +@@ -2156,9 +2156,9 @@ static CURLcode nss_do_connect(struct Curl_easy *data, + 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 2404393..be7b811 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -3872,10 +3872,10 @@ static CURLcode servercert(struct Curl_easy *data, + 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) { +@@ -3889,10 +3889,10 @@ static CURLcode servercert(struct Curl_easy *data, + 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; +@@ -3904,7 +3904,7 @@ static CURLcode servercert(struct Curl_easy *data, + 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); +@@ -3915,7 +3915,7 @@ static CURLcode servercert(struct Curl_easy *data, + 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); +@@ -3924,7 +3924,7 @@ static CURLcode servercert(struct Curl_easy *data, + } + + 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 fa8a6fa..1aa6fc8 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -125,6 +125,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) +@@ -135,11 +145,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->curves, needle->curves) && +@@ -161,8 +173,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); +@@ -178,6 +192,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); +@@ -185,6 +200,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); + Curl_safefree(sslc->curves); + } + +-- +2.31.1 + diff --git a/0006-curl-7.76.1-CVE-2021-22925.patch b/0006-curl-7.76.1-CVE-2021-22925.patch new file mode 100644 index 0000000..769f74c --- /dev/null +++ b/0006-curl-7.76.1-CVE-2021-22925.patch @@ -0,0 +1,47 @@ +From 3dbac7fb8b39a4f9aa871401d9d2790f0583ba01 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +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 +--- + lib/telnet.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/lib/telnet.c b/lib/telnet.c +index fdd137f..567c22c 100644 +--- a/lib/telnet.c ++++ b/lib/telnet.c +@@ -922,12 +922,17 @@ static void suboption(struct Curl_easy *data) + 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 + diff --git a/0007-curl-7.76.1-CVE-2021-22945.patch b/0007-curl-7.76.1-CVE-2021-22945.patch new file mode 100644 index 0000000..4d301fc --- /dev/null +++ b/0007-curl-7.76.1-CVE-2021-22945.patch @@ -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 +--- + 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 +@@ -128,6 +128,10 @@ static CURLcode mqtt_send(struct Curl_easy *data, + mq->sendleftovers = sendleftovers; + mq->nsend = nsend; + } ++ else { ++ mq->sendleftovers = NULL; ++ mq->nsend = 0; ++ } + return result; + } + +-- +2.31.1 + diff --git a/0008-curl-7.76.1-CVE-2021-22946.patch b/0008-curl-7.76.1-CVE-2021-22946.patch new file mode 100644 index 0000000..54a5957 --- /dev/null +++ b/0008-curl-7.76.1-CVE-2021-22946.patch @@ -0,0 +1,331 @@ +From 64f8bdbf7da9e6b65716ce0d020c6c01d0aba77d Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +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 +--- + 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 5ef1e2e..71f998e 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -2678,9 +2678,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, + /* 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(data, 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->bits.ftp_use_control_ssl) ++ return ftp_state_user_resp(data, 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 e50d7fd..feb7445 100644 +--- a/lib/imap.c ++++ b/lib/imap.c +@@ -935,22 +935,18 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, + 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(data, conn); +- else if(data->set.use_ssl == CURLUSESSL_TRY) +- /* Fallback and carry on with authentication */ +- result = imap_perform_authentication(data, 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(data, conn); + } +- else ++ else if(data->set.use_ssl <= CURLUSESSL_TRY) + result = imap_perform_authentication(data, conn); ++ else { ++ failf(data, "STARTTLS not available."); ++ result = CURLE_USE_SSL_FAILED; ++ } + } + else + result = imap_perform_authentication(data, conn); +diff --git a/lib/pop3.c b/lib/pop3.c +index 6168b12..7698d1c 100644 +--- a/lib/pop3.c ++++ b/lib/pop3.c +@@ -740,28 +740,23 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, 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(data, conn); +- else if(data->set.use_ssl == CURLUSESSL_TRY) +- /* Fallback and carry on with authentication */ +- result = pop3_perform_authentication(data, conn); +- else { +- failf(data, "STLS not supported."); +- result = CURLE_USE_SSL_FAILED; +- } +- } +- else +- result = pop3_perform_authentication(data, 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(data, conn); ++ if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use) ++ result = pop3_perform_authentication(data, conn); ++ else if(pop3code == '+' && pop3c->tls_supported) ++ /* Switch to TLS connection now */ ++ result = pop3_perform_starttls(data, conn); ++ else if(data->set.use_ssl <= CURLUSESSL_TRY) ++ /* Fallback and carry on with authentication */ ++ result = pop3_perform_authentication(data, 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 d083baf..163ce59 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -117,6 +117,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 @@ ++ ++ ++ ++IMAP ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++REPLY CAPABILITY A001 BAD Not implemented ++ ++ ++ ++# ++# Client-side ++ ++ ++SSL ++ ++ ++imap ++ ++ ++IMAP require STARTTLS with failing capabilities ++ ++ ++imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl-reqd ++ ++ ++Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) ++From: Fred Foobar ++Subject: afternoon meeting ++To: joe@example.com ++Message-Id: ++MIME-Version: 1.0 ++Content-Type: TEXT/PLAIN; CHARSET=US-ASCII ++ ++Hello Joe, do you think we can meet at 3:30 tomorrow? ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++# 64 is CURLE_USE_SSL_FAILED ++ ++64 ++ ++ ++A001 CAPABILITY ++ ++ ++ +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 @@ ++ ++ ++ ++POP3 ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++REPLY CAPA -ERR Not implemented ++ ++ ++From: me@somewhere ++To: fake@nowhere ++ ++body ++ ++-- ++ yours sincerely ++ ++ ++ ++# ++# Client-side ++ ++ ++SSL ++ ++ ++pop3 ++ ++ ++POP3 require STARTTLS with failing capabilities ++ ++ ++pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl-reqd ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++# 64 is CURLE_USE_SSL_FAILED ++ ++64 ++ ++ ++CAPA ++ ++ ++ +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 @@ ++ ++ ++ ++FTP ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++REPLY welcome 230 Welcome ++REPLY AUTH 500 unknown command ++ ++ ++ ++# Client-side ++ ++ ++SSL ++ ++ ++ftp ++ ++ ++FTP require STARTTLS while preauthenticated ++ ++ ++data ++ to ++ see ++that FTPS ++works ++ so does it? ++ ++ ++--ssl-reqd --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++# 64 is CURLE_USE_SSL_FAILED ++ ++64 ++ ++ ++AUTH SSL ++AUTH TLS ++ ++ ++ +-- +2.31.1 + diff --git a/0009-curl-7.76.1-CVE-2021-22947.patch b/0009-curl-7.76.1-CVE-2021-22947.patch new file mode 100644 index 0000000..6c4cab1 --- /dev/null +++ b/0009-curl-7.76.1-CVE-2021-22947.patch @@ -0,0 +1,354 @@ +From a1ec463c8207bde97b3575d12e396e999a55a8d0 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +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 +--- + 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 @@ ++ ++ ++ ++SMTP ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++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 ++ ++ ++ ++# ++# Client-side ++ ++ ++SSL ++ ++ ++smtp ++ ++ ++SMTP STARTTLS pipelined server response ++ ++ ++mail body ++ ++ ++smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -u user:secret --ssl --sasl-ir -T - ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++# 8 is CURLE_WEIRD_SERVER_REPLY ++ ++8 ++ ++ ++EHLO %TESTNUMBER ++STARTTLS ++ ++ ++ +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 @@ ++ ++ ++ ++IMAP ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++CAPA STARTTLS ++REPLY STARTTLS A002 BAD currently unavailable\r\nA003 OK Authenticated\r\nA004 OK Accepted ++REPLY LOGIN A003 BAD Authentication credentials invalid ++ ++ ++ ++# ++# Client-side ++ ++ ++SSL ++ ++ ++imap ++ ++ ++IMAP STARTTLS pipelined server response ++ ++ ++imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl ++ ++ ++Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) ++From: Fred Foobar ++Subject: afternoon meeting ++To: joe@example.com ++Message-Id: ++MIME-Version: 1.0 ++Content-Type: TEXT/PLAIN; CHARSET=US-ASCII ++ ++Hello Joe, do you think we can meet at 3:30 tomorrow? ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++# 8 is CURLE_WEIRD_SERVER_REPLY ++ ++8 ++ ++ ++A001 CAPABILITY ++A002 STARTTLS ++ ++ ++ +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 @@ ++ ++ ++ ++POP3 ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++CAPA STLS USER ++REPLY STLS -ERR currently unavailable\r\n+OK user accepted\r\n+OK authenticated ++REPLY PASS -ERR Authentication credentials invalid ++ ++ ++From: me@somewhere ++To: fake@nowhere ++ ++body ++ ++-- ++ yours sincerely ++ ++ ++ ++# ++# Client-side ++ ++ ++SSL ++ ++ ++pop3 ++ ++ ++POP3 STARTTLS pipelined server response ++ ++ ++pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++# 8 is CURLE_WEIRD_SERVER_REPLY ++ ++8 ++ ++ ++CAPA ++STLS ++ ++ ++ +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 @@ ++ ++ ++ ++FTP ++STARTTLS ++ ++ ++ ++# ++# Server-side ++ ++ ++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 ++ ++ ++ ++# Client-side ++ ++ ++SSL ++ ++ ++ftp ++ ++ ++FTP STARTTLS pipelined server response ++ ++ ++data ++ to ++ see ++that FTPS ++works ++ so does it? ++ ++ ++--ssl --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret -P %CLIENTIP ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++# 8 is CURLE_WEIRD_SERVER_REPLY ++ ++8 ++ ++ ++AUTH SSL ++ ++ ++ +-- +2.31.1 + diff --git a/0010-curl-7.76.1-CVE-2022-22576.patch b/0010-curl-7.76.1-CVE-2022-22576.patch new file mode 100644 index 0000000..90c94c7 --- /dev/null +++ b/0010-curl-7.76.1-CVE-2022-22576.patch @@ -0,0 +1,148 @@ +From 85d1103c2fc0c9b1bdfae470dbafd45758e1c2f0 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +Date: Mon, 25 Apr 2022 11:44:05 +0200 +Subject: [PATCH] url: check sasl additional parameters for connection reuse. + +Also move static function safecmp() as non-static Curl_safecmp() since +its purpose is needed at several places. + +Bug: https://curl.se/docs/CVE-2022-22576.html + +CVE-2022-22576 + +Closes #8746 + +Upstream-commit: 852aa5ad351ea53e5f01d2f44b5b4370c2bf5425 +Signed-off-by: Kamil Dudka +--- + lib/strcase.c | 10 ++++++++++ + lib/strcase.h | 2 ++ + lib/url.c | 13 ++++++++++++- + lib/urldata.h | 1 + + lib/vtls/vtls.c | 21 ++++++--------------- + 5 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/lib/strcase.c b/lib/strcase.c +index dd46ca1..692a3f1 100644 +--- a/lib/strcase.c ++++ b/lib/strcase.c +@@ -251,6 +251,16 @@ void Curl_strntolower(char *dest, const char *src, size_t n) + } while(*src++ && --n); + } + ++/* Compare case-sensitive NUL-terminated strings, taking care of possible ++ * null pointers. Return true if arguments match. ++ */ ++bool Curl_safecmp(char *a, char *b) ++{ ++ if(a && b) ++ return !strcmp(a, b); ++ return !a && !b; ++} ++ + /* --- public functions --- */ + + int curl_strequal(const char *first, const char *second) +diff --git a/lib/strcase.h b/lib/strcase.h +index b628656..382b80a 100644 +--- a/lib/strcase.h ++++ b/lib/strcase.h +@@ -48,4 +48,6 @@ char Curl_raw_toupper(char in); + void Curl_strntoupper(char *dest, const char *src, size_t n); + void Curl_strntolower(char *dest, const char *src, size_t n); + ++bool Curl_safecmp(char *a, char *b); ++ + #endif /* HEADER_CURL_STRCASE_H */ +diff --git a/lib/url.c b/lib/url.c +index adef2cd..94e3406 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -768,6 +768,7 @@ static void conn_free(struct connectdata *conn) + Curl_safefree(conn->passwd); + Curl_safefree(conn->sasl_authzid); + Curl_safefree(conn->options); ++ Curl_safefree(conn->oauth_bearer); + Curl_dyn_free(&conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ +@@ -1310,7 +1311,9 @@ ConnectionExists(struct Curl_easy *data, + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(strcmp(needle->user, check->user) || +- strcmp(needle->passwd, check->passwd)) { ++ strcmp(needle->passwd, check->passwd) || ++ !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) || ++ !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ + continue; + } +@@ -3554,6 +3557,14 @@ static CURLcode create_conn(struct Curl_easy *data, + } + } + ++ if(data->set.str[STRING_BEARER]) { ++ conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); ++ if(!conn->oauth_bearer) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } ++ } ++ + #ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); +diff --git a/lib/urldata.h b/lib/urldata.h +index cc8a600..03da59a 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -991,6 +991,7 @@ struct connectdata { + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + char *sasl_authzid; /* authorisation identity string, allocated */ ++ char *oauth_bearer; /* OAUTH2 bearer, allocated */ + unsigned char httpversion; /* the HTTP version*10 reported by the server */ + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 03b85ba..a40ac06 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -125,15 +125,6 @@ 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, +@@ -146,12 +137,12 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + (data->verifystatus == needle->verifystatus) && + blobcmp(data->cert_blob, needle->cert_blob) && + 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_safecmp(data->CApath, needle->CApath) && ++ Curl_safecmp(data->CAfile, needle->CAfile) && ++ Curl_safecmp(data->issuercert, needle->issuercert) && ++ Curl_safecmp(data->clientcert, needle->clientcert) && ++ Curl_safecmp(data->random_file, needle->random_file) && ++ Curl_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->curves, needle->curves) && +-- +2.34.1 + diff --git a/0011-curl-7.76.1-CVE-2022-27775.patch b/0011-curl-7.76.1-CVE-2022-27775.patch new file mode 100644 index 0000000..769a0fd --- /dev/null +++ b/0011-curl-7.76.1-CVE-2022-27775.patch @@ -0,0 +1,40 @@ +From 187d0795030ccb4f410eb6089e265ac3571e56dd Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 11:48:00 +0200 +Subject: [PATCH] conncache: include the zone id in the "bundle" hashkey + +Make connections to two separate IPv6 zone ids create separate +connections. + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27775.html +Closes #8747 + +Upstream-commit: 058f98dc3fe595f21dc26a5b9b1699e519ba5705 +Signed-off-by: Kamil Dudka +--- + lib/conncache.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/conncache.c b/lib/conncache.c +index cd5756a..9b9f683 100644 +--- a/lib/conncache.c ++++ b/lib/conncache.c +@@ -159,8 +159,12 @@ static void hashkey(struct connectdata *conn, char *buf, + /* report back which name we used */ + *hostp = hostname; + +- /* put the number first so that the hostname gets cut off if too long */ +- msnprintf(buf, len, "%ld%s", port, hostname); ++ /* put the numbers first so that the hostname gets cut off if too long */ ++#ifdef ENABLE_IPV6 ++ msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname); ++#else ++ msnprintf(buf, len, "%ld/%s", port, hostname); ++#endif + } + + /* Returns number of connections currently held in the connection cache. +-- +2.34.1 + diff --git a/0012-curl-7.76.1-CVE-2022-27776.patch b/0012-curl-7.76.1-CVE-2022-27776.patch new file mode 100644 index 0000000..7dd5fdf --- /dev/null +++ b/0012-curl-7.76.1-CVE-2022-27776.patch @@ -0,0 +1,243 @@ +From 2be87227d4b4024c91ff6c856520cac9c9619555 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 13:05:40 +0200 +Subject: [PATCH 1/2] http: avoid auth/cookie on redirects same host diff port + +CVE-2022-27776 + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27776.html +Closes #8749 + +Upstream-commit: 6e659993952aa5f90f48864be84a1bbb047fc258 +Signed-off-by: Kamil Dudka +--- + lib/http.c | 33 +++++++++++++++++++++------------ + lib/urldata.h | 16 +++++++++------- + 2 files changed, 30 insertions(+), 19 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index 799d4fb..0791dcf 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -775,6 +775,21 @@ output_auth_headers(struct Curl_easy *data, + return CURLE_OK; + } + ++/* ++ * allow_auth_to_host() tells if autentication, cookies or other "sensitive ++ * data" can (still) be sent to this host. ++ */ ++static bool allow_auth_to_host(struct Curl_easy *data) ++{ ++ struct connectdata *conn = data->conn; ++ return (!data->state.this_is_a_follow || ++ data->set.allow_auth_to_other_hosts || ++ (data->state.first_host && ++ strcasecompare(data->state.first_host, conn->host.name) && ++ (data->state.first_remote_port == conn->remote_port) && ++ (data->state.first_remote_protocol == conn->handler->protocol))); ++} ++ + /** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication +@@ -847,15 +862,11 @@ Curl_http_output_auth(struct Curl_easy *data, + with it */ + authproxy->done = TRUE; + +- /* To prevent the user+password to get sent to other than the original +- host due to a location-follow, we do some weirdo checks here */ +- if(!data->state.this_is_a_follow || +- conn->bits.netrc || +- !data->state.first_host || +- data->set.allow_auth_to_other_hosts || +- strcasecompare(data->state.first_host, conn->host.name)) { ++ /* To prevent the user+password to get sent to other than the original host ++ due to a location-follow */ ++ if(allow_auth_to_host(data) ++ || conn->bits.netrc) + result = output_auth_headers(data, conn, authhost, request, path, FALSE); +- } + else + authhost->done = TRUE; + +@@ -1906,10 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ +- (data->state.this_is_a_follow && +- data->state.first_host && +- !data->set.allow_auth_to_other_hosts && +- !strcasecompare(data->state.first_host, conn->host.name))) ++ !allow_auth_to_host(data)) + ; + else { + #ifdef USE_HYPER +@@ -2081,6 +2089,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) + return CURLE_OUT_OF_MEMORY; + + data->state.first_remote_port = conn->remote_port; ++ data->state.first_remote_protocol = conn->handler->protocol; + } + Curl_safefree(data->state.aptr.host); + +diff --git a/lib/urldata.h b/lib/urldata.h +index 03da59a..f92052a 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1336,14 +1336,16 @@ struct UrlState { + char *ulbuf; /* allocated upload buffer or NULL */ + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ +- char *first_host; /* host name of the first (not followed) request. +- if set, this should be the host name that we will +- sent authorization to, no else. Used to make Location: +- following not keep sending user+password... This is +- strdup() data. +- */ ++ ++ /* host name, port number and protocol of the first (not followed) request. ++ if set, this should be the host name that we will sent authorization to, ++ no else. Used to make Location: following not keep sending user+password. ++ This is strdup()ed data. */ ++ char *first_host; ++ int first_remote_port; ++ unsigned int first_remote_protocol; ++ + int retrycount; /* number of retries on a new connection */ +- int first_remote_port; /* remote port of the first (not followed) request */ + struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ +-- +2.34.1 + + +From c0d12f1634785596746e5d461319dcb95b5b6ae8 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 13:05:47 +0200 +Subject: [PATCH 2/2] test898: verify the fix for CVE-2022-27776 + +Do not pass on Authorization headers on redirects to another port + +Upstream-commit: afe752e0504ab60bf63787ede0b992cbe1065f78 +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.inc | 2 +- + tests/data/test898 | 90 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 tests/data/test898 + +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 59d46bc..7ae2cf8 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -106,7 +106,7 @@ test854 test855 test856 test857 test858 test859 test860 test861 test862 \ + test863 test864 test865 test866 test867 test868 test869 test870 test871 \ + test872 test873 test874 test875 test876 test877 test878 test879 test880 \ + test881 test882 test883 test884 test885 test886 test887 test888 test889 \ +-test890 test891 test892 test893 test894 test895 test896 \ ++test890 test891 test892 test893 test894 test895 test896 test898 \ + \ + test900 test901 test902 test903 test904 test905 test906 test907 test908 \ + test909 test910 test911 test912 test913 test914 test915 test916 test917 \ +diff --git a/tests/data/test898 b/tests/data/test898 +new file mode 100644 +index 0000000..5cbb7d8 +--- /dev/null ++++ b/tests/data/test898 +@@ -0,0 +1,90 @@ ++ ++ ++ ++HTTP ++--location ++Authorization ++Cookie ++ ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Connection: close ++Content-Type: text/html ++ ++hey ++ ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Connection: close ++Content-Type: text/html ++ ++hey ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ ++ ++HTTP with custom auth and cookies redirected to HTTP on a diff port ++ ++ ++-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -H "Authorization: Basic am9lOnNlY3JldA==" -H "Cookie: userpwd=am9lOnNlY3JldA==" ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET http://firsthost.com/ HTTP/1.1 ++Host: firsthost.com ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++Authorization: Basic am9lOnNlY3JldA== ++Cookie: userpwd=am9lOnNlY3JldA== ++ ++GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1 ++Host: firsthost.com:9999 ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +-- +2.34.1 + diff --git a/0013-curl-7.76.1-CVE-2022-27774.patch b/0013-curl-7.76.1-CVE-2022-27774.patch new file mode 100644 index 0000000..a911611 --- /dev/null +++ b/0013-curl-7.76.1-CVE-2022-27774.patch @@ -0,0 +1,635 @@ +From ecee0926868d138312e9608531b232f697e50cad Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH 1/4] connect: store "conn_remote_port" in the info struct + +To make it available after the connection ended. + +Upstream-commit: 08b8ef4e726ba10f45081ecda5b3cea788d3c839 +Signed-off-by: Kamil Dudka +--- + lib/connect.c | 1 + + lib/urldata.h | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lib/connect.c b/lib/connect.c +index 64f9511..7518807 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -619,6 +619,7 @@ void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn, + data->info.conn_scheme = conn->handler->scheme; + data->info.conn_protocol = conn->handler->protocol; + data->info.conn_primary_port = conn->port; ++ data->info.conn_remote_port = conn->remote_port; + data->info.conn_local_port = local_port; + } + +diff --git a/lib/urldata.h b/lib/urldata.h +index f92052a..5218f76 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1167,7 +1167,11 @@ struct PureInfo { + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; +- int conn_primary_port; ++ int conn_primary_port; /* this is the destination port to the connection, ++ which might have been a proxy */ ++ int conn_remote_port; /* this is the "remote port", which is the port ++ number of the used URL, independent of proxy or ++ not */ + char conn_local_ip[MAX_IPADR_LEN]; + int conn_local_port; + const char *conn_scheme; +-- +2.34.1 + + +From 12c129f8d0b165d83ed954f68717d88ffc1cfc5f Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH 2/4] transfer: redirects to other protocols or ports clear + auth + +... unless explicitly permitted. + +Bug: https://curl.se/docs/CVE-2022-27774.html +Reported-by: Harry Sintonen +Closes #8748 + +Upstream-commit: 620ea21410030a9977396b4661806bc187231b79 +Signed-off-by: Kamil Dudka +--- + lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/lib/transfer.c b/lib/transfer.c +index 1f8019b..752fe14 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1641,10 +1641,57 @@ CURLcode Curl_follow(struct Curl_easy *data, + return CURLE_OUT_OF_MEMORY; + } + else { +- + uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); + if(uc) + return Curl_uc_to_curlcode(uc); ++ ++ /* Clear auth if this redirects to a different port number or protocol, ++ unless permitted */ ++ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { ++ char *portnum; ++ int port; ++ bool clear = FALSE; ++ ++ if(data->set.use_port && data->state.allow_port) ++ /* a custom port is used */ ++ port = (int)data->set.use_port; ++ else { ++ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, ++ CURLU_DEFAULT_PORT); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ port = atoi(portnum); ++ free(portnum); ++ } ++ if(port != data->info.conn_remote_port) { ++ infof(data, "Clear auth, redirects to port from %u to %u", ++ data->info.conn_remote_port, port); ++ clear = TRUE; ++ } ++ else { ++ char *scheme; ++ const struct Curl_handler *p; ++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ ++ p = Curl_builtin_scheme(scheme); ++ if(p && (p->protocol != data->info.conn_protocol)) { ++ infof(data, "Clear auth, redirects scheme from %s to %s", ++ data->info.conn_scheme, scheme); ++ clear = TRUE; ++ } ++ free(scheme); ++ } ++ if(clear) { ++ Curl_safefree(data->state.aptr.user); ++ Curl_safefree(data->state.aptr.passwd); ++ } ++ } + } + + if(type == FOLLOW_FAKE) { +-- +2.34.1 + + +From 83bf4314d88cc16469afeaaefd6686a50371d1b7 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 16:24:33 +0200 +Subject: [PATCH 3/4] tests: verify the fix for CVE-2022-27774 + + - Test 973 redirects from HTTP to FTP, clear auth + - Test 974 redirects from HTTP to HTTP different port, clear auth + - Test 975 redirects from HTTP to FTP, permitted to keep auth + - Test 976 redirects from HTTP to HTTP different port, permitted to keep + auth + +Upstream-commit: 5295e8d64ac6949ecb3f9e564317a608f51b90d8 +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.inc | 1 + + tests/data/test973 | 88 +++++++++++++++++++++++++++++++++++++++++ + tests/data/test974 | 87 ++++++++++++++++++++++++++++++++++++++++ + tests/data/test975 | 88 +++++++++++++++++++++++++++++++++++++++++ + tests/data/test976 | 88 +++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 352 insertions(+) + create mode 100644 tests/data/test973 + create mode 100644 tests/data/test974 + create mode 100644 tests/data/test975 + create mode 100644 tests/data/test976 + +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 7ae2cf8..175fc43 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -116,6 +116,7 @@ test936 test937 test938 test939 test940 test941 test942 test943 test944 \ + 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 \ ++test973 test974 test975 test976 \ + \ + test980 test981 test982 test983 test984 test985 test986 \ + \ +diff --git a/tests/data/test973 b/tests/data/test973 +new file mode 100644 +index 0000000..6ced107 +--- /dev/null ++++ b/tests/data/test973 +@@ -0,0 +1,88 @@ ++ ++ ++ ++HTTP ++FTP ++--location ++ ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002 ++ ++ ++ ++data ++ to ++ see ++that FTP ++works ++ so does it? ++ ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002 ++ ++data ++ to ++ see ++that FTP ++works ++ so does it? ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ftp ++ ++ ++HTTP with auth redirected to FTP w/o auth ++ ++ ++http://%HOSTIP:%HTTPPORT/%TESTNUMBER -L -u joe:secret ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++Authorization: Basic am9lOnNlY3JldA== ++User-Agent: curl/%VERSION ++Accept: */* ++ ++USER anonymous ++PASS ftp@example.com ++PWD ++CWD a ++CWD path ++EPSV ++TYPE I ++SIZE %TESTNUMBER0002 ++RETR %TESTNUMBER0002 ++QUIT ++ ++ ++ +diff --git a/tests/data/test974 b/tests/data/test974 +new file mode 100644 +index 0000000..ac4e641 +--- /dev/null ++++ b/tests/data/test974 +@@ -0,0 +1,87 @@ ++ ++ ++ ++HTTP ++--location ++ ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Connection: close ++Content-Type: text/html ++ ++hey ++ ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Connection: close ++Content-Type: text/html ++ ++hey ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ ++ ++HTTP with auth redirected to HTTP on a diff port w/o auth ++ ++ ++-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -u joe:secret ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET http://firsthost.com/ HTTP/1.1 ++Host: firsthost.com ++Authorization: Basic am9lOnNlY3JldA== ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1 ++Host: firsthost.com:9999 ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +diff --git a/tests/data/test975 b/tests/data/test975 +new file mode 100644 +index 0000000..85e03e4 +--- /dev/null ++++ b/tests/data/test975 +@@ -0,0 +1,88 @@ ++ ++ ++ ++HTTP ++FTP ++--location-trusted ++ ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002 ++ ++ ++ ++data ++ to ++ see ++that FTP ++works ++ so does it? ++ ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: ftp://%HOSTIP:%FTPPORT/a/path/%TESTNUMBER0002 ++ ++data ++ to ++ see ++that FTP ++works ++ so does it? ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ftp ++ ++ ++HTTP with auth redirected to FTP allowing auth to continue ++ ++ ++http://%HOSTIP:%HTTPPORT/%TESTNUMBER --location-trusted -u joe:secret ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET /%TESTNUMBER HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++Authorization: Basic am9lOnNlY3JldA== ++User-Agent: curl/%VERSION ++Accept: */* ++ ++USER joe ++PASS secret ++PWD ++CWD a ++CWD path ++EPSV ++TYPE I ++SIZE %TESTNUMBER0002 ++RETR %TESTNUMBER0002 ++QUIT ++ ++ ++ +diff --git a/tests/data/test976 b/tests/data/test976 +new file mode 100644 +index 0000000..c4dd61e +--- /dev/null ++++ b/tests/data/test976 +@@ -0,0 +1,88 @@ ++ ++ ++ ++HTTP ++--location-trusted ++ ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Connection: close ++Content-Type: text/html ++ ++hey ++ ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 0 ++Connection: close ++Content-Type: text/html ++Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Connection: close ++Content-Type: text/html ++ ++hey ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ ++ ++HTTP with auth redirected to HTTP on a diff port --location-trusted ++ ++ ++-x http://%HOSTIP:%HTTPPORT http://firsthost.com --location-trusted -u joe:secret ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++GET http://firsthost.com/ HTTP/1.1 ++Host: firsthost.com ++Authorization: Basic am9lOnNlY3JldA== ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1 ++Host: firsthost.com:9999 ++Authorization: Basic am9lOnNlY3JldA== ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +-- +2.34.1 + + +From 443ce415aa60caaf8b1c9b0b71fff8d26263daca Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 17:59:15 +0200 +Subject: [PATCH 4/4] openssl: don't leak the SRP credentials in redirects + either + +Follow-up to 620ea21410030 + +Reported-by: Harry Sintonen +Closes #8751 + +Upstream-commit: 139a54ed0a172adaaf1a78d6f4fff50b2c3f9e08 +Signed-off-by: Kamil Dudka +--- + lib/http.c | 10 +++++----- + lib/http.h | 6 ++++++ + lib/vtls/openssl.c | 3 ++- + 3 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index 0791dcf..4433824 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -776,10 +776,10 @@ output_auth_headers(struct Curl_easy *data, + } + + /* +- * allow_auth_to_host() tells if autentication, cookies or other "sensitive +- * data" can (still) be sent to this host. ++ * Curl_allow_auth_to_host() tells if authentication, cookies or other ++ * "sensitive data" can (still) be sent to this host. + */ +-static bool allow_auth_to_host(struct Curl_easy *data) ++bool Curl_allow_auth_to_host(struct Curl_easy *data) + { + struct connectdata *conn = data->conn; + return (!data->state.this_is_a_follow || +@@ -864,7 +864,7 @@ Curl_http_output_auth(struct Curl_easy *data, + + /* To prevent the user+password to get sent to other than the original host + due to a location-follow */ +- if(allow_auth_to_host(data) ++ if(Curl_allow_auth_to_host(data) + || conn->bits.netrc) + result = output_auth_headers(data, conn, authhost, request, path, FALSE); + else +@@ -1917,7 +1917,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, + checkprefix("Cookie:", compare)) && + /* be careful of sending this potentially sensitive header to + other hosts */ +- !allow_auth_to_host(data)) ++ !Curl_allow_auth_to_host(data)) + ; + else { + #ifdef USE_HYPER +diff --git a/lib/http.h b/lib/http.h +index 07e963d..9000bae 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -317,4 +317,10 @@ Curl_http_output_auth(struct Curl_easy *data, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + ++/* ++ * Curl_allow_auth_to_host() tells if authentication, cookies or other ++ * "sensitive data" can (still) be sent to this host. ++ */ ++bool Curl_allow_auth_to_host(struct Curl_easy *data); ++ + #endif /* HEADER_CURL_HTTP_H */ +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 1bafe96..97c5666 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -2857,7 +2857,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + #endif + + #ifdef USE_OPENSSL_SRP +- if(ssl_authtype == CURL_TLSAUTH_SRP) { ++ if((ssl_authtype == CURL_TLSAUTH_SRP) && ++ Curl_allow_auth_to_host(data)) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s\n", ssl_username); +-- +2.34.1 + diff --git a/0014-curl-7.76.1-CVE-2022-27782.patch b/0014-curl-7.76.1-CVE-2022-27782.patch new file mode 100644 index 0000000..515ebd3 --- /dev/null +++ b/0014-curl-7.76.1-CVE-2022-27782.patch @@ -0,0 +1,461 @@ +From 50481ac42b4beae6ea85345e37b051124ac00f11 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 28 Jan 2022 16:48:38 +0100 +Subject: [PATCH 1/3] setopt: fix the TLSAUTH #ifdefs for proxy-disabled builds + +Closes #8350 + +Upstream-commit: 96629ba2c212cda2bd1b7b04e2a9fc01ef70b75d +Signed-off-by: Kamil Dudka +--- + lib/setopt.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/lib/setopt.c b/lib/setopt.c +index 08827d1..9eaa187 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -5,7 +5,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. ++ * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms +@@ -2699,30 +2699,30 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; ++#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); +-#ifndef CURL_DISABLE_PROXY + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ +-#endif + break; ++#endif + case CURLOPT_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; ++#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); +-#ifndef CURL_DISABLE_PROXY + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ +-#endif + break; ++#endif + case CURLOPT_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || +-- +2.34.1 + + +From 931fbabcae0b5d1a91657e6bb85f4f23fce7ac3d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 9 May 2022 23:13:53 +0200 +Subject: [PATCH 2/3] tls: check more TLS details for connection reuse + +CVE-2022-27782 + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27782.html +Closes #8825 + +Upstream-commit: f18af4f874cecab82a9797e8c7541e0990c7a64c +Signed-off-by: Kamil Dudka +--- + lib/setopt.c | 29 +++++++++++++++++------------ + lib/url.c | 23 ++++++++++++++++------- + lib/urldata.h | 13 +++++++------ + lib/vtls/openssl.c | 10 +++++----- + lib/vtls/vtls.c | 21 +++++++++++++++++++++ + 5 files changed, 66 insertions(+), 30 deletions(-) + +diff --git a/lib/setopt.c b/lib/setopt.c +index 8e1bf12..7aa6fdb 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -2268,6 +2268,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + + case CURLOPT_SSL_OPTIONS: + arg = va_arg(param, long); ++ data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff); + data->set.ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); +@@ -2281,6 +2282,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + #ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_SSL_OPTIONS: + arg = va_arg(param, long); ++ data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff); + data->set.proxy_ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); +@@ -2696,49 +2698,52 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + case CURLOPT_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], + va_arg(param, char *)); +- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) +- data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ ++ if(data->set.str[STRING_TLSAUTH_USERNAME] && ++ !data->set.ssl.primary.authtype) ++ data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + #ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && +- !data->set.proxy_ssl.authtype) +- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ ++ !data->set.proxy_ssl.primary.authtype) ++ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to ++ SRP */ + break; + #endif + case CURLOPT_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], + va_arg(param, char *)); +- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) +- data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ ++ if(data->set.str[STRING_TLSAUTH_USERNAME] && ++ !data->set.ssl.primary.authtype) ++ data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */ + break; + #ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && +- !data->set.proxy_ssl.authtype) +- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ ++ !data->set.proxy_ssl.primary.authtype) ++ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */ + break; + #endif + case CURLOPT_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) +- data->set.ssl.authtype = CURL_TLSAUTH_SRP; ++ data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; + else +- data->set.ssl.authtype = CURL_TLSAUTH_NONE; ++ data->set.ssl.primary.authtype = CURL_TLSAUTH_NONE; + break; + #ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXY_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) +- data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; ++ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; + else +- data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; ++ data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_NONE; + break; + #endif + #endif +diff --git a/lib/url.c b/lib/url.c +index 94e3406..5ebf5e2 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -540,7 +540,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) + set->ssl.primary.verifypeer = TRUE; + set->ssl.primary.verifyhost = TRUE; + #ifdef USE_TLS_SRP +- set->ssl.authtype = CURL_TLSAUTH_NONE; ++ set->ssl.primary.authtype = CURL_TLSAUTH_NONE; + #endif + set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth + type */ +@@ -1719,11 +1719,17 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) + conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus; + conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; + conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; ++ conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options; ++#ifdef USE_TLS_SRP ++#endif + #ifndef CURL_DISABLE_PROXY + conn->proxy_ssl_config.verifystatus = + data->set.proxy_ssl.primary.verifystatus; + conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; + conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; ++ conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options; ++#ifdef USE_TLS_SRP ++#endif + #endif + conn->ip_version = data->set.ipver; + conn->bits.connect_only = data->set.connect_only; +@@ -3764,7 +3770,8 @@ static CURLcode create_conn(struct Curl_easy *data, + 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.primary.CRLfile = ++ data->set.str[STRING_SSL_CRLFILE_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]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; +@@ -3772,18 +3779,20 @@ static CURLcode create_conn(struct Curl_easy *data, + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_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]; ++ data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; + 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]; +- data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; ++ data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME]; ++ data->set.ssl.primary.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]; ++ data->set.proxy_ssl.primary.username = ++ data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; ++ data->set.proxy_ssl.primary.password = ++ data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; + #endif + #endif + data->set.ssl.key_blob = data->set.blobs[BLOB_KEY]; +diff --git a/lib/urldata.h b/lib/urldata.h +index 5218f76..e006495 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -253,9 +253,16 @@ struct ssl_primary_config { + char *cipher_list; /* list of ciphers to use */ + char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ + char *pinned_key; ++ char *CRLfile; /* CRL to check certificate revocation */ + struct curl_blob *cert_blob; + struct curl_blob *issuercert_blob; ++#ifdef USE_TLS_SRP ++ char *username; /* TLS username (for, e.g., SRP) */ ++ char *password; /* TLS password (for, e.g., SRP) */ ++ enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ ++#endif + char *curves; /* list of curves to use */ ++ unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */ + 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 */ +@@ -265,7 +272,6 @@ struct ssl_primary_config { + struct ssl_config_data { + struct ssl_primary_config primary; + long certverifyresult; /* result from the certificate verification */ +- char *CRLfile; /* CRL to check certificate revocation */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /* parameter for call back */ + char *cert_type; /* format for certificate (default: PEM)*/ +@@ -273,11 +279,6 @@ struct ssl_config_data { + struct curl_blob *key_blob; + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ +-#ifdef USE_TLS_SRP +- char *username; /* TLS username (for, e.g., SRP) */ +- char *password; /* TLS password (for, e.g., SRP) */ +- enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ +-#endif + BIT(certinfo); /* gather lots of certificate info */ + BIT(falsestart); + BIT(enable_beast); /* allow this flaw for interoperability's sake*/ +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 97c5666..a4ef9d1 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -2546,7 +2546,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + #endif + const long int ssl_version = SSL_CONN_CONFIG(version); + #ifdef USE_OPENSSL_SRP +- const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); ++ const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(primary.authtype); + #endif + char * const ssl_cert = SSL_SET_OPTION(primary.clientcert); + const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); +@@ -2554,7 +2554,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); +- const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); ++ const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile); + char error_buffer[256]; + struct ssl_backend_data *backend = connssl->backend; + bool imported_native_ca = false; +@@ -2859,15 +2859,15 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + #ifdef USE_OPENSSL_SRP + if((ssl_authtype == CURL_TLSAUTH_SRP) && + Curl_allow_auth_to_host(data)) { +- char * const ssl_username = SSL_SET_OPTION(username); +- ++ char * const ssl_username = SSL_SET_OPTION(primary.username); ++ char * const ssl_password = SSL_SET_OPTION(primary.password); + infof(data, "Using TLS-SRP username: %s\n", ssl_username); + + if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) { + failf(data, "Unable to set SRP user name"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } +- if(!SSL_CTX_set_srp_password(backend->ctx, SSL_SET_OPTION(password))) { ++ if(!SSL_CTX_set_srp_password(backend->ctx, ssl_password)) { + failf(data, "failed setting SRP password"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index a40ac06..e2d3438 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -132,6 +132,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + { + if((data->version == needle->version) && + (data->version_max == needle->version_max) && ++ (data->ssl_options == needle->ssl_options) && + (data->verifypeer == needle->verifypeer) && + (data->verifyhost == needle->verifyhost) && + (data->verifystatus == needle->verifystatus) && +@@ -143,9 +144,15 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + Curl_safecmp(data->clientcert, needle->clientcert) && + Curl_safecmp(data->random_file, needle->random_file) && + Curl_safecmp(data->egdsocket, needle->egdsocket) && ++#ifdef USE_TLS_SRP ++ Curl_safecmp(data->username, needle->username) && ++ Curl_safecmp(data->password, needle->password) && ++ (data->authtype == needle->authtype) && ++#endif + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && + Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) && + Curl_safe_strcasecompare(data->curves, needle->curves) && ++ Curl_safe_strcasecompare(data->CRLfile, needle->CRLfile) && + Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key)) + return TRUE; + +@@ -162,6 +169,10 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + dest->verifyhost = source->verifyhost; + dest->verifystatus = source->verifystatus; + dest->sessionid = source->sessionid; ++ dest->ssl_options = source->ssl_options; ++#ifdef USE_TLS_SRP ++ dest->authtype = source->authtype; ++#endif + + CLONE_BLOB(cert_blob); + CLONE_BLOB(issuercert_blob); +@@ -175,6 +186,11 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + CLONE_STRING(cipher_list13); + CLONE_STRING(pinned_key); + CLONE_STRING(curves); ++ CLONE_STRING(CRLfile); ++#ifdef USE_TLS_SRP ++ CLONE_STRING(username); ++ CLONE_STRING(password); ++#endif + + return TRUE; + } +@@ -193,6 +209,11 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc) + Curl_safefree(sslc->cert_blob); + Curl_safefree(sslc->issuercert_blob); + Curl_safefree(sslc->curves); ++ Curl_safefree(sslc->CRLfile); ++#ifdef USE_TLS_SRP ++ Curl_safefree(sslc->username); ++ Curl_safefree(sslc->password); ++#endif + } + + #ifdef USE_SSL +-- +2.34.1 + + +From 5e9832048b30492e02dd222cd8bfe997e03cffa1 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 9 May 2022 23:13:53 +0200 +Subject: [PATCH 3/3] url: check SSH config match on connection reuse + +CVE-2022-27782 + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27782.html +Closes #8825 + +Upstream-commit: 1645e9b44505abd5cbaf65da5282c3f33b5924a5 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 11 +++++++++++ + lib/vssh/ssh.h | 6 +++--- + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 5ebf5e2..c713e54 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1073,6 +1073,12 @@ static void prune_dead_connections(struct Curl_easy *data) + } + } + ++static bool ssh_config_matches(struct connectdata *one, ++ struct connectdata *two) ++{ ++ return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) && ++ Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub)); ++} + /* + * Given one filled in connection struct (named needle), this function should + * detect if there already is one that has all the significant details +@@ -1319,6 +1325,11 @@ ConnectionExists(struct Curl_easy *data, + } + } + ++ if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) { ++ if(!ssh_config_matches(needle, check)) ++ continue; ++ } ++ + if((needle->handler->flags&PROTOPT_SSL) + #ifndef CURL_DISABLE_PROXY + || !needle->bits.httpproxy || needle->bits.tunnel_proxy +diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h +index 7972081..30d82e5 100644 +--- a/lib/vssh/ssh.h ++++ b/lib/vssh/ssh.h +@@ -7,7 +7,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. ++ * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms +@@ -131,8 +131,8 @@ struct ssh_conn { + + /* common */ + const char *passphrase; /* pass-phrase to use */ +- char *rsa_pub; /* path name */ +- char *rsa; /* path name */ ++ char *rsa_pub; /* strdup'ed public key file */ ++ char *rsa; /* strdup'ed private key file */ + bool authed; /* the connection has been authenticated fine */ + bool acceptfail; /* used by the SFTP_QUOTE (continue if + quote command fails) */ +-- +2.34.1 + diff --git a/ci.fmf b/ci.fmf new file mode 100644 index 0000000..d3546e9 --- /dev/null +++ b/ci.fmf @@ -0,0 +1,9 @@ +discover: + how: fmf +prepare: + how: install + exclude: + - libcurl-minimal + - curl-minimal +execute: + how: tmt diff --git a/curl.spec b/curl.spec index f8b0c24..93d26a2 100644 --- a/curl.spec +++ b/curl.spec @@ -1,13 +1,52 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.76.1 -Release: 2%{?dist} +Release: 16%{?dist} License: MIT Source: https://curl.se/download/%{name}-%{version}.tar.xz # http2: fix resource leaks detected by Coverity Patch1: 0001-curl-7.76.1-resource-leaks.patch +# fix TELNET stack contents disclosure (CVE-2021-22898) +Patch2: 0002-curl-7.76.1-CVE-2021-22898.patch + +# fix TLS session caching disaster (CVE-2021-22901) +Patch3: 0003-curl-7.76.1-CVE-2021-22901.patch + +# fix SIGSEGV upon disconnect of a ldaps:// transfer (#1941925) +Patch4: 0004-curl-7.76.1-ldaps-segv.patch + +# fix bad connection reuse due to flawed path name checks (CVE-2021-22924) +Patch5: 0005-curl-7.76.1-CVE-2021-22924.patch + +# fix TELNET stack contents disclosure again (CVE-2021-22925) +Patch6: 0006-curl-7.76.1-CVE-2021-22925.patch + +# fix use-after-free and double-free in MQTT sending (CVE-2021-22945) +Patch7: 0007-curl-7.76.1-CVE-2021-22945.patch + +# fix protocol downgrade required TLS bypass (CVE-2021-22946) +Patch8: 0008-curl-7.76.1-CVE-2021-22946.patch + +# fix STARTTLS protocol injection via MITM (CVE-2021-22947) +Patch9: 0009-curl-7.76.1-CVE-2021-22947.patch + +# fix OAUTH2 bearer bypass in connection re-use (CVE-2022-22576) +Patch10: 0010-curl-7.76.1-CVE-2022-22576.patch + +# fix bad local IPv6 connection reuse (CVE-2022-27775) +Patch11: 0011-curl-7.76.1-CVE-2022-27775.patch + +# fix auth/cookie leak on redirect (CVE-2022-27776) +Patch12: 0012-curl-7.76.1-CVE-2022-27776.patch + +# fix credential leak on redirect (CVE-2022-27774) +Patch13: 0013-curl-7.76.1-CVE-2022-27774.patch + +# fix too eager reuse of TLS and SSH connections (CVE-2022-27782) +Patch14: 0014-curl-7.76.1-CVE-2022-27782.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -27,7 +66,6 @@ BuildRequires: gcc BuildRequires: groff BuildRequires: krb5-devel BuildRequires: libidn2-devel -BuildRequires: libmetalink-devel BuildRequires: libnghttp2-devel BuildRequires: libpsl-devel BuildRequires: libssh-devel @@ -184,6 +222,19 @@ be installed. # upstream patches %patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 # Fedora patches %patch101 -p1 @@ -233,6 +284,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" @@ -248,7 +300,6 @@ export common_configure_opts=" \ --disable-manual \ --without-brotli \ --without-libidn2 \ - --without-libmetalink \ --without-libpsl \ --without-libssh ) @@ -262,7 +313,6 @@ export common_configure_opts=" \ --enable-manual \ --with-brotli \ --with-libidn2 \ - --with-libmetalink \ --with-libpsl \ --with-libssh ) @@ -364,6 +414,42 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed May 11 2022 Kamil Dudka - 7.76.1-16 +- fix too eager reuse of TLS and SSH connections (CVE-2022-27782) + +* Mon May 02 2022 Kamil Dudka - 7.76.1-15 +- fix leak of SRP credentials in redirects (CVE-2022-27774) + +* Fri Apr 29 2022 Kamil Dudka - 7.76.1-14 +- add missing tests to Makefile + +* Thu Apr 28 2022 Kamil Dudka - 7.76.1-13 +- fix credential leak on redirect (CVE-2022-27774) +- fix auth/cookie leak on redirect (CVE-2022-27776) +- fix bad local IPv6 connection reuse (CVE-2022-27775) +- fix OAUTH2 bearer bypass in connection re-use (CVE-2022-22576) + +* Fri Sep 17 2021 Kamil Dudka - 7.76.1-12 +- 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 - 7.76.1-7 +- fix TELNET stack contents disclosure again (CVE-2021-22925) +- fix bad connection reuse due to flawed path name checks (CVE-2021-22924) + +* Wed Jul 21 2021 Kamil Dudka - 7.76.1-5 +- 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 Jun 02 2021 Kamil Dudka - 7.76.1-4 +- fix SIGSEGV upon disconnect of a ldaps:// transfer (#1941925) + +* Wed May 26 2021 Kamil Dudka - 7.76.1-3 +- fix TLS session caching disaster (CVE-2021-22901) +- fix TELNET stack contents disclosure (CVE-2021-22898) + * Mon May 03 2021 Kamil Dudka - 7.76.1-2 - http2: fix resource leaks detected by Coverity diff --git a/tests/non-root-user-download/Makefile b/tests/non-root-user-download/Makefile deleted file mode 100644 index 9746b63..0000000 --- a/tests/non-root-user-download/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Makefile of /CoreOS/curl/Sanity/non-root-user-download -# Description: various download methods with non-root user -# Author: Karel Srot -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Copyright (c) 2013 Red Hat, Inc. All rights reserved. -# -# This copyrighted material is made available to anyone wishing -# to use, modify, copy, or redistribute it subject to the terms -# and conditions of the GNU General Public License version 2. -# -# This program is distributed in the hope that it will be -# useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public -# License along with this program; if not, write to the Free -# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -export TEST=/CoreOS/curl/Sanity/non-root-user-download -export TESTVERSION=1.0 - -BUILT_FILES= - -FILES=$(METADATA) runtest.sh Makefile PURPOSE - -.PHONY: all install download clean - -run: $(FILES) build - ./runtest.sh - -build: $(BUILT_FILES) - test -x runtest.sh || chmod a+x runtest.sh - -clean: - rm -f *~ $(BUILT_FILES) - - -include /usr/share/rhts/lib/rhts-make.include - -$(METADATA): Makefile - @echo "Owner: Karel Srot " > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "Description: various download methods with non-root user" >> $(METADATA) - @echo "Type: Sanity" >> $(METADATA) - @echo "TestTime: 5m" >> $(METADATA) - @echo "RunFor: curl" >> $(METADATA) - @echo "Requires: curl" >> $(METADATA) - @echo "Priority: Normal" >> $(METADATA) - @echo "License: GPLv2" >> $(METADATA) - @echo "Confidential: no" >> $(METADATA) - @echo "Destructive: no" >> $(METADATA) - - rhts-lint $(METADATA) diff --git a/tests/non-root-user-download/PURPOSE b/tests/non-root-user-download/PURPOSE deleted file mode 100644 index 048ed68..0000000 --- a/tests/non-root-user-download/PURPOSE +++ /dev/null @@ -1,3 +0,0 @@ -PURPOSE of /CoreOS/curl/Sanity/non-root-user-download -Description: various download methods with non-root user -Author: Karel Srot diff --git a/tests/non-root-user-download/main.fmf b/tests/non-root-user-download/main.fmf new file mode 100644 index 0000000..2e3980f --- /dev/null +++ b/tests/non-root-user-download/main.fmf @@ -0,0 +1,18 @@ +summary: various download methods with non-root user +description: '' +contact: Daniel Rusek +component: + - curl +require: + - findutils + - libselinux-utils + - openssh-clients + - openssh-server + - passwd +test: ./runtest.sh +framework: beakerlib +duration: 5m +enabled: true +tier: '1' +link: + - relates: https://bugzilla.redhat.com/show_bug.cgi?id=1049921 diff --git a/tests/non-root-user-download/runtest.sh b/tests/non-root-user-download/runtest.sh old mode 100644 new mode 100755 index 1b5f8f1..0529a12 --- a/tests/non-root-user-download/runtest.sh +++ b/tests/non-root-user-download/runtest.sh @@ -27,14 +27,13 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Include Beaker environment -. /usr/bin/rhts-environment.sh || exit 1 . /usr/share/beakerlib/beakerlib.sh || exit 1 PACKAGE="curl" -FTP_URL=ftp://ftp.scientificlinux.org/linux/fedora/releases/18/Live/x86_64/Fedora-18-x86_64-Live-CHECKSUM -HTTP_URL=https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/18/Live/x86_64/Fedora-18-x86_64-Live-CHECKSUM -CONTENT=a276e06d244e04b765f0a35532d9036ad84f340b0bdcc32e0233a8fbc31d5bed +FTP_URL=ftp://ftp.fi.muni.cz/pub/linux/fedora/linux/releases/36/Everything/x86_64/iso/Fedora-Everything-36-1.5-x86_64-CHECKSUM +HTTP_URL=https://archives.fedoraproject.org/pub/fedora/linux/releases/36/Everything/x86_64/iso/Fedora-Everything-36-1.5-x86_64-CHECKSUM +CONTENT=85cb450443d68d513b41e57b0bd818a740279dac5dfc09c68e681ff8a3006404 PASSWORD=pAssw0rd OPTIONS="" rlIsRHEL 7 && OPTIONS="--insecure" @@ -47,9 +46,11 @@ rlJournalStart rlRun "useradd -m curltester" 0 "Adding the test user" rlRun "echo $PASSWORD | passwd --stdin curltester" 0 "Setting the password for the test user" rlRun "su - curltester -c 'echo $CONTENT > ~/testfile'" 0 "Creating ~curltester/testfile" + rlFileBackup --clean --missing-ok $HOME/.ssh /etc/hosts + rlRun "rm -f $HOME/.ssh/*" [ -d $HOME/.ssh ] || ( mkdir $HOME/.ssh && restorecon HOME/.ssh ) - rlFileBackup $HOME/.ssh/known_hosts /etc/hosts - ssh-keygen -F localhost -f $HOME/.ssh/known_hosts || rlRun "ssh-keyscan localhost >> $HOME/.ssh/known_hosts" + rlRun "rlServiceStart sshd" + rlRun "ssh-keyscan localhost >> $HOME/.ssh/known_hosts" rlPhaseEnd rlPhaseStartTest "http download" @@ -82,7 +83,7 @@ if ! rlIsRHEL 5; then fi rlPhaseStartCleanup - rlRun "rm -f $HOME/.ssh/known_hosts" + rlRun "rlServiceRestore" rlFileRestore rlRun "popd" rlRun "rm -r $TmpDir" 0 "Removing tmp directory" diff --git a/tests/non-root-user-download/runtest.yml b/tests/non-root-user-download/runtest.yml deleted file mode 100644 index c03e729..0000000 --- a/tests/non-root-user-download/runtest.yml +++ /dev/null @@ -1,64 +0,0 @@ -- hosts: '{{ hosts | default("localhost") }}' - vars: - package: "curl" - tasks: - - name: "Set Content variables" - set_fact: - content: "a276e06d244e04b765f0a35532d9036ad84f340b0bdcc32e0233a8fbc31d5bed" - password: "pAssw0rd" - crypt_password: "$6$/5GE87XLYLLfB3qx$w84Kct34UZG/4buTSXWkaaVIsw2xGXSAdmnS2QYdG8TtRgTsBnHdFdSkhoy.tKIE6A6LKlxczIZjQbpB19k7B1" - - name: "Create user curltester" - user: - name: "curltester" - password: "{{ crypt_password }}" - - name: "Copy testfile" - copy: - dest: "/home/curltester/testfile" - content: "{{ content }}" - - block: - - name: "http download" - command: "curl https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/18/Live/x86_64/Fedora-18-x86_64-Live-CHECKSUM" - args: - warn: false - register: http - become: yes - become_user: curltester - - name: "Compare http output" - fail: - msg: "{{ content }} not in {{ http.stdout }}" - when: content not in http.stdout - - name: "ftp download" - command: "curl ftp://ftp.scientificlinux.org/linux/fedora/releases/18/Live/x86_64/Fedora-18-x86_64-Live-CHECKSUM" - args: - warn: false - register: ftp - become: yes - become_user: curltester - - name: "Compare ftp output" - fail: - msg: "{{ content }} not in {{ ftp.stdout }}" - when: content not in ftp.stdout - - name: "scp download" - command: "curl -u curltester:{{ password }} --insecure scp://localhost/home/curltester/testfile" - args: - warn: false - register: scp - - name: "Compare scp output" - fail: - msg: "{{ content }} not in {{ scp.stdout }}" - when: content not in scp.stdout - - name: "sftp download" - command: "curl -u curltester:{{ password }} --insecure sftp://localhost/home/curltester/testfile" - args: - warn: false - register: sftp - - name: "Compare sftp output" - fail: - msg: "{{ content }} not in {{ sftp.stdout }}" - when: content not in sftp.stdout - always: - - name: "Remove user curltester" - user: - name: "curltester" - remove: yes - state: absent diff --git a/tests/scp-and-sftp-download-test/Makefile b/tests/scp-and-sftp-download-test/Makefile deleted file mode 100644 index b4d1c52..0000000 --- a/tests/scp-and-sftp-download-test/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Makefile of /CoreOS/curl/Sanity/scp-and-sftp-download-test -# Description: downloads test file through scp and sftp -# Author: Karel Srot -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Copyright (c) 2012 Red Hat, Inc. All rights reserved. -# -# This copyrighted material is made available to anyone wishing -# to use, modify, copy, or redistribute it subject to the terms -# and conditions of the GNU General Public License version 2. -# -# This program is distributed in the hope that it will be -# useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public -# License along with this program; if not, write to the Free -# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -export TEST=/CoreOS/curl/Sanity/scp-and-sftp-download-test -export TESTVERSION=1.0 - -BUILT_FILES= - -FILES=$(METADATA) runtest.sh Makefile PURPOSE - -.PHONY: all install download clean - -run: $(FILES) build - ./runtest.sh - -build: $(BUILT_FILES) - test -x runtest.sh || chmod a+x runtest.sh - -clean: - rm -f *~ $(BUILT_FILES) - - -include /usr/share/rhts/lib/rhts-make.include - -$(METADATA): Makefile - @echo "Owner: Karel Srot " > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "Description: downloads test file through scp and sftp" >> $(METADATA) - @echo "Type: Sanity" >> $(METADATA) - @echo "TestTime: 10m" >> $(METADATA) - @echo "RunFor: curl" >> $(METADATA) - @echo "Requires: curl openssh" >> $(METADATA) - @echo "Priority: Normal" >> $(METADATA) - @echo "License: GPLv2" >> $(METADATA) - @echo "Confidential: no" >> $(METADATA) - @echo "Destructive: no" >> $(METADATA) - - rhts-lint $(METADATA) diff --git a/tests/scp-and-sftp-download-test/PURPOSE b/tests/scp-and-sftp-download-test/PURPOSE deleted file mode 100644 index 03adc4c..0000000 --- a/tests/scp-and-sftp-download-test/PURPOSE +++ /dev/null @@ -1,12 +0,0 @@ -PURPOSE of /CoreOS/curl/Sanity/scp-and-sftp-download-test -Description: downloads test file through scp and sftp -Author: Karel Srot - -Test scenario: -- scp download -- sftp download -- scp upload -- sftp upload - -When PUBKEY_PARAM global variable is set to 'empty' or 'none', scenarios are executed -with empty --pubkey parameter (--pubkey "") or with the paramiter omitted diff --git a/tests/scp-and-sftp-download-test/main.fmf b/tests/scp-and-sftp-download-test/main.fmf new file mode 100644 index 0000000..b69aff6 --- /dev/null +++ b/tests/scp-and-sftp-download-test/main.fmf @@ -0,0 +1,20 @@ +summary: downloads test file through scp and sftp +description: | + Test scenario: + - scp download + - sftp download + - scp upload + - sftp upload + + When PUBKEY_PARAM global variable is set to 'empty' or 'none', scenarios are executed + with empty --pubkey parameter (--pubkey "") or with the paramiter omitted +contact: Daniel Rusek +require: + - findutils +component: + - curl +test: ./runtest.sh +path: /tests/scp-and-sftp-download-test +framework: beakerlib +duration: 10m +enabled: true diff --git a/tests/scp-and-sftp-download-test/runtest.sh b/tests/scp-and-sftp-download-test/runtest.sh old mode 100644 new mode 100755 index 6e5d748..9cf9a2c --- a/tests/scp-and-sftp-download-test/runtest.sh +++ b/tests/scp-and-sftp-download-test/runtest.sh @@ -27,8 +27,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Include Beaker environment -. /usr/bin/rhts-environment.sh -. /usr/lib/beakerlib/beakerlib.sh +. /usr/share/beakerlib/beakerlib.sh || exit 1 PACKAGE="curl" diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 819d636..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -# Tests for Classic -- hosts: localhost - roles: - - role: standard-test-beakerlib - tags: - - classic - tests: - - scp-and-sftp-download-test - - non-root-user-download - required_packages: - - findutils # non-root-user-download needs find command - # scp-and-sftp-download-test needs find command - - passwd # non-root-user-download needs passwd command - - openssh-clients # non-root-user-download needs ssh-keyscan command - -# Tests for Atomic -- hosts: localhost - roles: - - role: standard-test-beakerlib - tags: - - atomic - tests: - - scp-and-sftp-download-test - - non-root-user-download -