MINOR: ssl: Store the last SSL error code in case of read or write failure

In case of error while calling a SSL_read or SSL_write, the
SSL_get_error function is called in order to know more about the error
that happened. If the error code is SSL_ERROR_SSL or SSL_ERROR_SYSCALL,
the error queue might contain more information on the error. This error
code was not used until now. But we now need to store it in order for
backend error fetches to catch all handshake related errors.

The change was required because the previous backend fetch would not
have raised anything if the client's certificate was rejected by the
server (and the connection interrupted). This happens because starting
from TLS1.3, the 'Finished' state on the client is reached before its
certificate is sent to the server (see the "Protocol Overview" part of
RFC 8446). The only place where we can detect that the server rejected the
certificate is after the first SSL_read call after the SSL_do_handshake
function.

This patch then adds an extra ERR_peek_error after the SSL_read and
SSL_write calls in ssl_sock_to_buf and ssl_sock_from_buf. This means
that it could set an error code in the SSL context a long time after the
handshake is over, hence the change in the error fetches.
This commit is contained in:
Remi Tricot-Le Breton 2021-09-29 18:56:53 +02:00 committed by William Lallemand
parent 1fe0fad88b
commit 9543d5ad5b
1 changed files with 6 additions and 0 deletions

View File

@ -6186,6 +6186,9 @@ static size_t ssl_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu
} else if (ret == SSL_ERROR_ZERO_RETURN) } else if (ret == SSL_ERROR_ZERO_RETURN)
goto read0; goto read0;
else if (ret == SSL_ERROR_SSL) { else if (ret == SSL_ERROR_SSL) {
struct ssl_sock_ctx *ctx = conn->xprt_ctx;
if (!ctx->error_code)
ctx->error_code = ERR_peek_error();
conn->err_code = CO_ERR_SSL_FATAL; conn->err_code = CO_ERR_SSL_FATAL;
} }
/* For SSL_ERROR_SYSCALL, make sure to clear the error /* For SSL_ERROR_SYSCALL, make sure to clear the error
@ -6350,6 +6353,9 @@ static size_t ssl_sock_from_buf(struct connection *conn, void *xprt_ctx, const s
break; break;
} }
else if (ret == SSL_ERROR_SSL || ret == SSL_ERROR_SYSCALL) { else if (ret == SSL_ERROR_SSL || ret == SSL_ERROR_SYSCALL) {
struct ssl_sock_ctx *ctx = conn->xprt_ctx;
if (!ctx->error_code)
ctx->error_code = ERR_peek_error();
conn->err_code = CO_ERR_SSL_FATAL; conn->err_code = CO_ERR_SSL_FATAL;
} }
goto out_error; goto out_error;