From bc006791a4d06502eb47fb676cc750f376464968 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 26 May 2021 10:22:51 +0200 Subject: [PATCH] Resolves: CVE-2021-22901 - fix TLS session caching disaster --- 0003-curl-7.76.1-CVE-2021-22901.patch | 1012 +++++++++++++++++++++++++ curl.spec | 5 + 2 files changed, 1017 insertions(+) create mode 100644 0003-curl-7.76.1-CVE-2021-22901.patch 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/curl.spec b/curl.spec index 9459f4a..5cb47cf 100644 --- a/curl.spec +++ b/curl.spec @@ -11,6 +11,9 @@ 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 + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -188,6 +191,7 @@ be installed. # upstream patches %patch1 -p1 %patch2 -p1 +%patch3 -p1 # Fedora patches %patch101 -p1 @@ -369,6 +373,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %changelog * 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