I did this
Console 1:
openssl s_server -accept 4433 -cert [removed] -keylogfile keys -timeout -www
Console 2:
curld -k -v https://localhost:4433/
OpenSSL serves an HTTP/1.0 status page without content length so curl keeps reading until the connection is closed.
In the case of Schannel, all data is received at once (including the server's close notify) and schannel_recv processes all records at once (including the close_notify) and then returns the body content. readwrite_data does not make further calls to schannel_recv (which would return 0 if called again) because data_pending returns false.
I found this issue while investigating #12885 and the recent mailing list report which were fixed by #12848. However my report is not the same and reproduces regardless of the fix. It precedes connection filters and I was able to reproduce from master all the way back to early versions of curl such as 7.45.0.
I am not sure if other backends are affected, it depends on how they process records. I could not reproduce with OpenSSL 3.0 as a backend.
I expected the following
I expected it not to hang of course...
I can force readwrite_data to call schannel_recv again by treating connection closed and close notify messages "data pending" even though there's no data. In these cases, schannel_recv would return 0. This seems like an ok solution, unless there is some pitfall I'm not thinking of. I'd like to get some thoughts on it, or maybe there's something more elegant to be done in readwrite_data?
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 45c3373..c1edc29 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -2443,7 +2443,9 @@ static bool schannel_data_pending(struct Curl_cfilter *cf,
if(backend->ctxt) /* SSL/TLS is in use */
return (backend->decdata_offset > 0 ||
- (backend->encdata_offset > 0 && !backend->encdata_is_incomplete));
+ (backend->encdata_offset > 0 && !backend->encdata_is_incomplete) ||
+ backend->recv_connection_closed ||
+ backend->recv_sspi_close_notify);
else
return FALSE;
}
curl/libcurl version
master ef4bd8d 2024-02-07
curl 8.6.1-DEV (i386-pc-win32) libcurl/8.6.1-DEV Schannel WinIDN
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS Debug HSTS HTTPS-proxy IDN IPv6 Kerberos Largefile NTLM SPNEGO SSL SSPI Unicode UnixSockets
operating system
Windows, any
I did this
Console 1:
Console 2:
OpenSSL serves an HTTP/1.0 status page without content length so curl keeps reading until the connection is closed.
In the case of Schannel, all data is received at once (including the server's close notify) and
schannel_recvprocesses all records at once (including the close_notify) and then returns the body content.readwrite_datadoes not make further calls toschannel_recv(which would return 0 if called again) becausedata_pendingreturns false.I found this issue while investigating #12885 and the recent mailing list report which were fixed by #12848. However my report is not the same and reproduces regardless of the fix. It precedes connection filters and I was able to reproduce from master all the way back to early versions of curl such as 7.45.0.
I am not sure if other backends are affected, it depends on how they process records. I could not reproduce with OpenSSL 3.0 as a backend.
I expected the following
I expected it not to hang of course...
I can force
readwrite_datato callschannel_recvagain by treating connection closed and close notify messages "data pending" even though there's no data. In these cases,schannel_recvwould return 0. This seems like an ok solution, unless there is some pitfall I'm not thinking of. I'd like to get some thoughts on it, or maybe there's something more elegant to be done inreadwrite_data?curl/libcurl version
master ef4bd8d 2024-02-07
operating system
Windows, any