It is possible to receive application data together with socket close.
In this case, SSL_read() may return SSL_ERROR_SYSCALL with ECONNRESET,
specifically after OpenSSL sent TLSv1.3 tickets on a closed connection.
Before OpenSSL 4.0, a subsequent SSL_write() returned SSL_ERROR_SYSCALL
with EPIPE in this case. The behaviour was changed to remember the
error state and handle such a call as a protocol error, see for details
https://github.com/openssl/openssl/issues/30631. This makes SSL_write()
return SSL_ERROR_SSL with the empty error queue, which results in
"[crit] ... SSL_write() failed" errors, as caught by ssl_stapling.t.
The fix is to check the result of the last read stored in c->ssl->last,
to avoid calling SSL_write() after a failed read. For consistency, the
check is added to ngx_ssl_sendfile(): SSL_sendfile() resets the error
state the same way SSL_write() does, though it does not seem to be
reachable in http.
Based on a patch by Maxim Dounin.
Signed-off-by: Sergey Kandaurov <pluknet@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/
ff5becaf5444>
int n, sslerr;
ngx_err_t err;
+ if (c->ssl->last == NGX_ERROR) {
+ c->write->ready = 0;
+ c->write->error = 1;
+ return NGX_ERROR;
+ }
+
#ifdef SSL_READ_EARLY_DATA_SUCCESS
if (c->ssl->in_early) {
return ngx_ssl_write_early(c, data, size);
ssize_t n;
ngx_err_t err;
+ if (c->ssl->last == NGX_ERROR) {
+ c->write->ready = 0;
+ c->write->error = 1;
+ return NGX_ERROR;
+ }
+
ngx_ssl_clear_error(c->log);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,