]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
openssl: improve retries on shutdown
authorStefan Eissing <stefan@eissing.org>
Thu, 17 Oct 2024 11:53:06 +0000 (13:53 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 17 Oct 2024 14:11:06 +0000 (16:11 +0200)
Once SSL_shutdown() has been called, OpenSSL does not really seem to
like it when it is called again and the other side has some finally data
to deliver.

Instead SSL_read() needs to be used solely, once the close notify has
been sent from curl's side.

Closes #15321

lib/vtls/openssl.c
tests/http/test_19_shutdown.py

index 43c478eca25842d27ea559be199ad8db0495063f..43dcce06b245e2eb20cec2e814bc759d34fd2aba 100644 (file)
@@ -1935,8 +1935,9 @@ static CURLcode ossl_shutdown(struct Curl_cfilter *cf,
 
   /* SSL should now have started the shutdown from our side. Since it
    * was not complete, we are lacking the close notify from the server. */
-  if(send_shutdown) {
+  if(send_shutdown && !(SSL_get_shutdown(octx->ssl) & SSL_SENT_SHUTDOWN)) {
     ERR_clear_error();
+    CURL_TRC_CF(data, cf, "send SSL close notify");
     if(SSL_shutdown(octx->ssl) == 1) {
       CURL_TRC_CF(data, cf, "SSL shutdown finished");
       *done = TRUE;
@@ -1961,7 +1962,10 @@ static CURLcode ossl_shutdown(struct Curl_cfilter *cf,
   err = SSL_get_error(octx->ssl, nread);
   switch(err) {
   case SSL_ERROR_ZERO_RETURN: /* no more data */
-    CURL_TRC_CF(data, cf, "SSL shutdown not received, but closed");
+    if(SSL_shutdown(octx->ssl) == 1)
+      CURL_TRC_CF(data, cf, "SSL shutdown finished");
+    else
+      CURL_TRC_CF(data, cf, "SSL shutdown not received, but closed");
     *done = TRUE;
     break;
   case SSL_ERROR_NONE: /* just did not get anything */
index 5e82121ee288489377700df3952cab1bf6bc3a08..bbb67d360e1016139a50c068bdb9de4810b8140b 100644 (file)
@@ -73,7 +73,7 @@ class TestShutdown:
             pytest.skip('only works for curl debug builds')
         curl = CurlClient(env=env, run_env={
             'CURL_GRACEFUL_SHUTDOWN': '2000',
-            'CURL_DEBUG': 'ssl'
+            'CURL_DEBUG': 'ssl,tcp'
         })
         url = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-1]'
         r = curl.http_download(urls=[url], alpn_proto=proto, with_tcpdump=True, extra_args=[