diff options
author | Jay Satiro <raysatiro@yahoo.com> | 2022-11-14 03:30:30 -0500 |
---|---|---|
committer | Jay Satiro <raysatiro@yahoo.com> | 2022-11-18 03:04:13 -0500 |
commit | 12e1def51a75392df62e65490416007d7e68dab9 (patch) | |
tree | 842c59a11b447d53f3e2d810d61e77bbe5d76fa2 /lib/socks.c | |
parent | 856b133f5d62475d4cc12624c4cccb4170134712 (diff) | |
download | curl-12e1def51a75392df62e65490416007d7e68dab9.tar.gz |
sendf: change Curl_read_plain to wrap Curl_recv_plain
Prior to this change Curl_read_plain would attempt to read the
socket directly. On Windows that's a problem because recv data may be
cached by libcurl and that data is only drained using Curl_recv_plain.
Rather than rewrite Curl_read_plain to handle cached recv data, I
changed it to wrap Curl_recv_plain, in much the same way that
Curl_write_plain already wraps Curl_send_plain.
Curl_read_plain -> Curl_recv_plain
Curl_write_plain -> Curl_send_plain
This fixes a bug in the schannel backend where decryption of arbitrary
TLS records fails because cached recv data is never drained. We send
data (TLS records formed by Schannel) using Curl_write_plain, which
calls Curl_send_plain, and that may do a recv-before-send
("pre-receive") to cache received data. The code calls Curl_read_plain
to read data (TLS records from the server), which prior to this change
did not call Curl_recv_plain and therefore cached recv data wasn't
retrieved, resulting in malformed TLS records and decryption failure
(SEC_E_DECRYPT_FAILURE).
The bug has only been observed during Schannel TLS 1.3 handshakes. Refer
to the issue and PR for more information.
Ref: https://github.com/curl/curl/issues/9431#issuecomment-1312420361
Assisted-by: Joel Depooter
Reported-by: Egor Pugin
Fixes https://github.com/curl/curl/issues/9431
Closes https://github.com/curl/curl/pull/9904
Diffstat (limited to 'lib/socks.c')
-rw-r--r-- | lib/socks.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/lib/socks.c b/lib/socks.c index 40cd13e0a..e1f6dbbb2 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -112,7 +112,7 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */ result = ~CURLE_OK; break; } - result = Curl_read_plain(sockfd, buf, buffersize, &nread); + result = Curl_read_plain(data, sockfd, buf, buffersize, &nread); if(CURLE_AGAIN == result) continue; if(result) @@ -396,7 +396,7 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf, /* FALLTHROUGH */ case CONNECT_SOCKS_READ: /* Receive response */ - result = Curl_read_plain(sockfd, (char *)sx->outp, + result = Curl_read_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &actualread); if(result && (CURLE_AGAIN != result)) { failf(data, "SOCKS4: Failed receiving connect request ack: %s", @@ -599,7 +599,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, sx->outp = socksreq; /* store it here */ /* FALLTHROUGH */ case CONNECT_SOCKS_READ: - result = Curl_read_plain(sockfd, (char *)sx->outp, + result = Curl_read_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &actualread); if(result && (CURLE_AGAIN != result)) { failf(data, "Unable to receive initial SOCKS5 response."); @@ -729,7 +729,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, sxstate(sx, data, CONNECT_AUTH_READ); /* FALLTHROUGH */ case CONNECT_AUTH_READ: - result = Curl_read_plain(sockfd, (char *)sx->outp, + result = Curl_read_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &actualread); if(result && (CURLE_AGAIN != result)) { failf(data, "Unable to receive SOCKS5 sub-negotiation response."); @@ -931,7 +931,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, sxstate(sx, data, CONNECT_REQ_READ); /* FALLTHROUGH */ case CONNECT_REQ_READ: - result = Curl_read_plain(sockfd, (char *)sx->outp, + result = Curl_read_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &actualread); if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to receive SOCKS5 connect request ack."); @@ -1030,7 +1030,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf, #endif /* FALLTHROUGH */ case CONNECT_REQ_READ_MORE: - result = Curl_read_plain(sockfd, (char *)sx->outp, + result = Curl_read_plain(data, sockfd, (char *)sx->outp, sx->outstanding, &actualread); if(result && (CURLE_AGAIN != result)) { failf(data, "Failed to receive SOCKS5 connect request ack."); |