From: Stefan Eissing Date: Fri, 15 Sep 2023 07:12:52 +0000 (+0200) Subject: openssl: improve ssl shutdown handling X-Git-Tag: curl-8_4_0~125 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34cdcb9b96a9aa3995323b74c3dd5ab19013a707;p=thirdparty%2Fcurl.git openssl: improve ssl shutdown handling - If SSL shutdown is not finished then make an additional call to SSL_read to gather additional tracing. - Fix http2 and h2-proxy filters to forward do_close() calls to the next filter. For example h2 and SSL shutdown before and after this change: Before: Curl_conn_close -> cf_hc_close -> Curl_conn_cf_discard_chain -> ssl_cf_destroy After: Curl_conn_close -> cf_hc_close -> cf_h2_close -> cf_setup_close -> ssl_cf_close Note that currently the tracing does not show output on the connection closure handle. Refer to discussion in #11878. Ref: https://github.com/curl/curl/discussions/11878 Closes https://github.com/curl/curl/pull/11858 --- diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c index 9cb804d047..922212082d 100644 --- a/lib/cf-h2-proxy.c +++ b/lib/cf-h2-proxy.c @@ -1160,6 +1160,8 @@ static void cf_h2_proxy_close(struct Curl_cfilter *cf, struct Curl_easy *data) cf_h2_proxy_ctx_clear(ctx); CF_DATA_RESTORE(cf, save); } + if(cf->next) + cf->next->cft->do_close(cf->next, data); } static void cf_h2_proxy_destroy(struct Curl_cfilter *cf, diff --git a/lib/http2.c b/lib/http2.c index 4732cf7025..1857c23b52 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -2425,6 +2425,8 @@ static void cf_h2_close(struct Curl_cfilter *cf, struct Curl_easy *data) cf_h2_ctx_clear(ctx); CF_DATA_RESTORE(cf, save); } + if(cf->next) + cf->next->cft->do_close(cf->next, data); } static void cf_h2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 3388e8b976..bbc9f594e0 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -1876,15 +1876,45 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data) if(backend->handle) { if(cf->next && cf->next->connected) { - char buf[32]; + char buf[1024]; + int nread, err; + long sslerr; + /* Maybe the server has already sent a close notify alert. Read it to avoid an RST on the TCP connection. */ (void)SSL_read(backend->handle, buf, (int)sizeof(buf)); - - (void)SSL_shutdown(backend->handle); - ERR_clear_error(); + if(SSL_shutdown(backend->handle) == 1) { + CURL_TRC_CF(data, cf, "SSL shutdown finished"); + } + else { + nread = SSL_read(backend->handle, buf, (int)sizeof(buf)); + err = SSL_get_error(backend->handle, nread); + switch(err) { + case SSL_ERROR_NONE: /* this is not an error */ + case SSL_ERROR_ZERO_RETURN: /* no more data */ + CURL_TRC_CF(data, cf, "SSL shutdown, EOF from server"); + break; + case SSL_ERROR_WANT_READ: + /* SSL has send its notify and now wants to read the reply + * from the server. We are not really interested in that. */ + CURL_TRC_CF(data, cf, "SSL shutdown sent"); + break; + case SSL_ERROR_WANT_WRITE: + CURL_TRC_CF(data, cf, "SSL shutdown send blocked"); + break; + default: + sslerr = ERR_get_error(); + CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s', errno %d", + (sslerr ? + ossl_strerror(sslerr, buf, sizeof(buf)) : + SSL_ERROR_to_str(err)), + SOCKERRNO); + break; + } + } + ERR_clear_error(); SSL_set_connect_state(backend->handle); } diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 38a20e8bea..494b660a98 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -1494,7 +1494,8 @@ static void ssl_cf_close(struct Curl_cfilter *cf, CF_DATA_SAVE(save, cf, data); cf_close(cf, data); - cf->next->cft->do_close(cf->next, data); + if(cf->next) + cf->next->cft->do_close(cf->next, data); CF_DATA_RESTORE(cf, save); }