Skip to content

openssl s_server causes curl with Schannel to hang #12894

Description

@jay

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

Activity

  1. jay commented on Feb 8, 2024

    @jay
    MemberAuthor

    Possibly related: #5284 #7068 #7615 #9161

    /cc @JDepooter

  2. bagder commented on Feb 8, 2024

    @bagder
    Member

    This seems like an ok solution

    Me too. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions