MINOR: ssl: Add new ssl_fc_hsk_err sample fetch

This new sample fetch along the ssl_fc_hsk_err_str fetch contain the
last SSL error of the error stack that occurred during the SSL
handshake (from the frontend's perspective). The errors happening during
the client's certificate verification will still be given by the
ssl_c_err and ssl_c_ca_err fetches. This new fetch will only hold errors
retrieved by the OpenSSL ERR_get_error function.
This commit is contained in:
Remi Tricot-Le Breton 2021-07-29 09:45:51 +02:00 committed by William Lallemand
parent 89b65cfd52
commit 7c6898ee49
4 changed files with 81 additions and 0 deletions

View File

@ -18925,6 +18925,25 @@ ssl_fc_has_sni : boolean
that the SSL library is built with support for TLS extensions enabled (check
haproxy -vv).
ssl_fc_hsk_err : integer
When the incoming connection was made over an SSL/TLS transport layer,
returns the ID of the latest error that happened during the handshake on the
frontend side, or 0 if no error was encountered. Any error happening during
the client's certificate verification process will not be raised through this
fetch but via the existing "ssl_c_err", "ssl_c_ca_err" and
"ssl_c_ca_err_depth" fetches. In order to get a text description of this
error code, you can either use the "ssl_fc_hsk_err_str" sample fetch or use
the "openssl errstr" command (which takes an error code in hexadecimal
representation as parameter). Please refer to your SSL library's
documentation to find the exhaustive list of error codes.
ssl_fc_hsk_err_str : string
When the incoming connection was made over an SSL/TLS transport layer,
returns a string representation of the latest error that happened during the
handshake on the frontend side. Any error happening during the client's
certificate verification process will not be raised through this fetch. See
also "ssl_fc_hsk_err".
ssl_fc_is_resumed : boolean
Returns true if the SSL/TLS session has been resumed through the use of
SSL session cache or TLS tickets on an incoming connection over an SSL/TLS

View File

@ -235,6 +235,7 @@ struct ssl_sock_ctx {
struct wait_event wait_event;
struct wait_event *subs;
int xprt_st; /* transport layer state, initialized to zero */
unsigned long hsk_error_code; /* last handshake error code of the error stack */
struct buffer early_buf; /* buffer to store the early data received */
int sent_early_data; /* Amount of early data we sent so far */

View File

@ -1188,6 +1188,61 @@ smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char
return 1;
}
static int
smp_fetch_ssl_fc_hsk_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
struct ssl_sock_ctx *ctx;
conn = objt_conn(smp->sess->origin);
if (!conn || conn->xprt != &ssl_sock)
return 0;
ctx = conn->xprt_ctx;
if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
if (!ctx)
return 0;
smp->flags = SMP_F_VOL_SESS;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = ctx->hsk_error_code;
return 1;
}
static int
smp_fetch_ssl_fc_hsk_err_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
struct ssl_sock_ctx *ctx;
const char *err_code_str;
conn = objt_conn(smp->sess->origin);
if (!conn || conn->xprt != &ssl_sock)
return 0;
ctx = conn->xprt_ctx;
if (conn->flags & CO_FL_WAIT_XPRT && !conn->err_code) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
if (!ctx || !ctx->hsk_error_code)
return 0;
err_code_str = ERR_error_string(ctx->hsk_error_code, NULL);
smp->flags = SMP_F_VOL_SESS;
smp->data.type = SMP_T_STR;
smp->data.u.str.area = (char*)err_code_str;
smp->data.u.str.data = strlen(err_code_str);
return 1;
}
/* Dump the SSL keylog, it only works with "tune.ssl.keylog 1" */
#ifdef HAVE_SSL_KEYLOG
static int smp_fetch_ssl_x_keylog(const struct arg *args, struct sample *smp, const char *kw, void *private)
@ -1546,6 +1601,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
{ "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_cipherlist_xxh", smp_fetch_ssl_fc_cl_xxh64, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_fc_hsk_err", smp_fetch_ssl_fc_hsk_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_fc_hsk_err_str", smp_fetch_ssl_fc_hsk_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
/* SSL server certificate fetches */
{ "ssl_s_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },

View File

@ -5278,6 +5278,7 @@ static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
ctx->subs = NULL;
ctx->xprt_st = 0;
ctx->xprt_ctx = NULL;
ctx->hsk_error_code = 0;
/* Only work with sockets for now, this should be adapted when we'll
* add QUIC support.
@ -5556,6 +5557,9 @@ static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
/* handshake did not complete, let's find why */
ret = SSL_get_error(ctx->ssl, ret);
if (!ctx->hsk_error_code)
ctx->hsk_error_code = ERR_peek_error();
if (ret == SSL_ERROR_WANT_WRITE) {
/* SSL handshake needs to write, L4 connection may not be ready */
if (!(ctx->wait_event.events & SUB_RETRY_SEND))