MINOR: ssl: Rename ssl_bc_hsk_err to ssl_bc_err

The ssl_bc_hsk_err sample fetch will need to raise more errors than only
handshake related ones hence its renaming to a more generic ssl_bc_err.
This patch is required because some handshake failures that should have
been caught by this fetch (verify error on the server side for instance)
were missed. This is caused by a change in TLS1.3 in which the
'Finished' state on the client is reached before its certificate is sent
(and verified) on the server side (see the "Protocol Overview" part of
RFC 8446).
This means that the SSL_do_handshake call is finished long before the
server can verify and potentially reject the client certificate.

The ssl_bc_hsk_err will then need to be expanded to catch other types of
errors.

This change is also applied to the frontend fetches (ssl_fc_hsk_err
becomes ssl_fc_err) and to their string counterparts.
This commit is contained in:
Remi Tricot-Le Breton 2021-09-29 18:56:52 +02:00 committed by William Lallemand
parent 61944f7a73
commit 1fe0fad88b
6 changed files with 64 additions and 57 deletions

View File

@ -18790,19 +18790,21 @@ ssl_bc_client_random : binary
sent using ephemeral ciphers. This requires OpenSSL >= 1.1.0, or BoringSSL.
It can be used in a tcp-check or an http-check ruleset.
ssl_bc_hsk_err : integer
ssl_bc_err : integer
When the outgoing connection was made over an SSL/TLS transport layer,
returns the ID of the latest error that happened during the handshake on the
backend side, or 0 if no error was encountered. In order to get a text
description of this error code, you can either use the "ssl_bc_hsk_err_str"
returns the ID of the last error of the first error stack raised on the
backend side. It can raise handshake errors as well as other read or write
errors occurring during the connection's lifetime. In order to get a text
description of this error code, you can either use the "ssl_bc_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_bc_hsk_err_str : string
ssl_bc_err_str : string
When the outgoing connection was made over an SSL/TLS transport layer,
returns a string representation of the latest error that happened during the
handshake on the backend side. See also "ssl_fc_hsk_err".
returns a string representation of the last error of the first error stack
that was raised on the connection from the backend's perspective. See also
"ssl_fc_err".
ssl_bc_is_resumed : boolean
Returns true when the back connection was made over an SSL/TLS transport
@ -19213,6 +19215,28 @@ ssl_fc_early_exporter_secret : string
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_err : integer
When the incoming connection was made over an SSL/TLS transport layer,
returns the ID of the last error of the first error stack raised on the
frontend side, or 0 if no error was encountered. It can be used to identify
handshake related errors other than verify ones (such as cipher mismatch), as
well as other read or write errors occurring during the connection's
lifetime. 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_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_err_str : string
When the incoming connection was made over an SSL/TLS transport layer,
returns a string representation of the last error of the first error stack
that was raised 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_err".
ssl_fc_has_crt : boolean
Returns true if a client certificate is present in an incoming connection over
SSL/TLS transport layer. Useful if 'verify' statement is set to 'optional'.
@ -19233,25 +19257,6 @@ 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
@ -21114,7 +21119,7 @@ HTTP ones, refer to the HTTP section.
14 '{' captured_request_headers* '}' {haproxy.1wt.eu}
15 '{' captured_response_headers* '}' {}
16 '"' http_request '"' "GET /index.html HTTP/1.1"
17 fc_conn_err '/' ssl_fc_hsk_err '/' ssl_c_err '/' ssl_c_ca_err 0/0/0/0
17 fc_conn_err '/' ssl_fc_err '/' ssl_c_err '/' ssl_c_ca_err 0/0/0/0
18 ssl_version '/' ssl_ciphers TLSv1.3/TLS_AES_256_GCM_SHA384
Detailed fields description :
@ -21122,9 +21127,11 @@ Detailed fields description :
corresponds to the "fc_conn_err" sample fetch. See the "fc_conn_err" and
"fc_conn_err_str" fetches for more information.
- "ssl_fc_hsk_err" is the status of the SSL handshake from the frontend's
point of view. It will be 0 if everything went well. See the
"ssl_fc_hsk_err" sample fetch's description for more information.
- "ssl_fc_err" is the last error of the first SSL error stack that was
raised on the connection from the frontend's perspective. It might be used
to detect SSL handshake errors for instance. It will be 0 if everything
went well. See the "ssl_fc_err" sample fetch's decription for more
information.
- "ssl_c_err" is the status of the client's certificate verification process.
The handshake might be successful while having a non-null verification
@ -21199,7 +21206,7 @@ the default HTTPS format is defined this way :
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC \
%CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r \
%[fc_conn_err]/%[ssl_fc_hsk_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err] \
%[fc_conn_err]/%[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err] \
%sslv/%sslc"
and the default TCP format is defined this way :

View File

@ -243,7 +243,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 */
unsigned long error_code; /* last 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

@ -105,33 +105,33 @@ syslog Slg_logconnerror -level info {
syslog Slg_bcknd -level info {
recv
expect ~ ".*bc_conn_err:0:\"Success\" ssl_bc_hsk_err:0:\"\""
expect ~ ".*bc_conn_err:0:\"Success\" ssl_bc_err:0:\"\""
barrier b2 sync
recv
expect ~ ".*bc_conn_err:34:\"SSL handshake failure\" ssl_bc_hsk_err:337047686:\"error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\""
expect ~ ".*bc_conn_err:34:\"SSL handshake failure\" ssl_bc_err:337047686:\"error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\""
barrier b2 sync
recv
expect ~ ".*bc_conn_err:32:\"Server presented an SSL certificate different from the configured one\" ssl_bc_hsk_err:337047686:\"error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\""
expect ~ ".*bc_conn_err:32:\"Server presented an SSL certificate different from the configured one\" ssl_bc_err:337047686:\"error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed\""
barrier b2 sync
# Verify errors on the server side cannot be caught through those backend fetches yet
recv
expect ~ ".*bc_conn_err:0:\"Success\" ssl_bc_hsk_err:0:\"\""
expect ~ ".*bc_conn_err:0:\"Success\" ssl_bc_err:0:\"\""
barrier b2 sync
recv
expect ~ ".*bc_conn_err:34:\"SSL handshake failure\" ssl_bc_hsk_err:336151568:\"error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure\""
expect ~ ".*bc_conn_err:34:\"SSL handshake failure\" ssl_bc_err:336151568:\"error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure\""
barrier b2 sync
recv
expect ~ ".*bc_conn_err:34:\"SSL handshake failure\" ssl_bc_hsk_err:336151568:\"error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure\""
expect ~ ".*bc_conn_err:34:\"SSL handshake failure\" ssl_bc_err:336151568:\"error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure\""
} -start
@ -167,12 +167,12 @@ haproxy h1 -conf {
server logconnerror "${tmpdir}/logconnerror_ssl.sock"
# This listener will be used to test backend fetches (bc_conn_err and ssl_bc_hsk_err)
# This listener will be used to test backend fetches (bc_conn_err and ssl_bc_err)
listen clear_backend_errors_lst
bind "fd@${backenderrorslst}"
log ${Slg_bcknd_addr}:${Slg_bcknd_port} local0
log-format "bc_conn_err:%[bc_conn_err]:%{+Q}[bc_conn_err_str]\ ssl_bc_hsk_err:%[ssl_bc_hsk_err]:%{+Q}[ssl_bc_hsk_err_str]"
error-log-format "ERROR bc_conn_err:%[bc_conn_err]:%{+Q}[bc_conn_err_str]\ ssl_bc_hsk_err:%[ssl_bc_hsk_err]:%{+Q}[ssl_bc_hsk_err_str]"
log-format "bc_conn_err:%[bc_conn_err]:%{+Q}[bc_conn_err_str]\ ssl_bc_err:%[ssl_bc_err]:%{+Q}[ssl_bc_err_str]"
error-log-format "ERROR bc_conn_err:%[bc_conn_err]:%{+Q}[bc_conn_err_str]\ ssl_bc_err:%[ssl_bc_err]:%{+Q}[ssl_bc_err_str]"
balance roundrobin
server no_err "${tmpdir}/no_err_ssl.sock" ssl crt ${testdir}/set_cafile_client.pem ca-file ${testdir}/set_cafile_interCA2.crt verify required
@ -188,8 +188,8 @@ haproxy h1 -conf {
listen cust_logfmt_ssl_lst
log ${Slg_cust_fmt_addr}:${Slg_cust_fmt_port} local0
mode http
log-format "conn_status:\"%[fc_conn_err]:%[fc_conn_err_str]\" hsk_err:\"%[ssl_fc_hsk_err]:%[ssl_fc_hsk_err_str]\" CN=%{+Q}[ssl_c_s_dn],serial=%[ssl_c_serial,hex],hash=%[ssl_c_sha1,hex]"
error-log-format "ERROR conn_status:\"%[fc_conn_err]:%[fc_conn_err_str]\" hsk_err:\"%[ssl_fc_hsk_err]:%[ssl_fc_hsk_err_str]\" CN=%{+Q}[ssl_c_s_dn],serial=%[ssl_c_serial,hex],hash=%[ssl_c_sha1,hex]"
log-format "conn_status:\"%[fc_conn_err]:%[fc_conn_err_str]\" hsk_err:\"%[ssl_fc_err]:%[ssl_fc_err_str]\" CN=%{+Q}[ssl_c_s_dn],serial=%[ssl_c_serial,hex],hash=%[ssl_c_sha1,hex]"
error-log-format "ERROR conn_status:\"%[fc_conn_err]:%[fc_conn_err_str]\" hsk_err:\"%[ssl_fc_err]:%[ssl_fc_err_str]\" CN=%{+Q}[ssl_c_s_dn],serial=%[ssl_c_serial,hex],hash=%[ssl_c_sha1,hex]"
bind "${tmpdir}/cust_logfmt_ssl.sock" ssl crt ${testdir}/set_cafile_server.pem ca-verify-file ${testdir}/set_cafile_rootCA.crt ca-file ${testdir}/set_cafile_interCA1.crt verify required ciphersuites "TLS_AES_256_GCM_SHA384"
server s1 ${s1_addr}:${s1_port}
@ -199,7 +199,7 @@ haproxy h1 -conf {
option log-separate-errors
mode http
option httpslog
error-log-format "ERROR %ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %[fc_conn_err]/%[ssl_fc_hsk_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err] %sslv/%sslc"
error-log-format "ERROR %ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %[fc_conn_err]/%[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err] %sslv/%sslc"
bind "${tmpdir}/https_logfmt_ssl.sock" ssl crt ${testdir}/set_cafile_server.pem ca-verify-file ${testdir}/set_cafile_rootCA.crt ca-file ${testdir}/set_cafile_interCA1.crt verify required ciphersuites "TLS_AES_256_GCM_SHA384"
server s1 ${s1_addr}:${s1_port}

View File

@ -193,7 +193,7 @@ static const struct logformat_type logformat_keywords[] = {
};
char default_http_log_format[] = "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"; // default format
char default_https_log_format[] = "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %[fc_conn_err]/%[ssl_fc_hsk_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err] %sslv/%sslc";
char default_https_log_format[] = "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %[fc_conn_err]/%[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err] %sslv/%sslc";
char clf_http_log_format[] = "%{+Q}o %{-Q}ci - - [%trg] %r %ST %B \"\" \"\" %cp %ms %ft %b %s %TR %Tw %Tc %Tr %Ta %tsc %ac %fc %bc %sc %rc %sq %bq %CC %CS %hrl %hsl";
char default_tcp_log_format[] = "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq";
char *log_format = NULL;

View File

@ -1207,7 +1207,7 @@ smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char
}
static int
smp_fetch_ssl_fc_hsk_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
smp_fetch_ssl_fc_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
struct ssl_sock_ctx *ctx;
@ -1232,7 +1232,7 @@ smp_fetch_ssl_fc_hsk_err(const struct arg *args, struct sample *smp, const char
smp->flags = SMP_F_VOL_SESS;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = ctx->hsk_error_code;
smp->data.u.sint = ctx->error_code;
return 1;
}
@ -1259,7 +1259,7 @@ smp_fetch_ssl_fc_protocol_hello_id(const struct arg *args, struct sample *smp, c
}
static int
smp_fetch_ssl_fc_hsk_err_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
smp_fetch_ssl_fc_err_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
struct ssl_sock_ctx *ctx;
@ -1280,10 +1280,10 @@ smp_fetch_ssl_fc_hsk_err_str(const struct arg *args, struct sample *smp, const c
return 0;
}
if (!ctx || !ctx->hsk_error_code)
if (!ctx || !ctx->error_code)
return 0;
err_code_str = ERR_error_string(ctx->hsk_error_code, NULL);
err_code_str = ERR_error_string(ctx->error_code, NULL);
smp->flags = SMP_F_VOL_SESS;
smp->data.type = SMP_T_STR;
@ -1679,8 +1679,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
{ "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
#endif
{ "ssl_bc_hsk_err", smp_fetch_ssl_fc_hsk_err, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
{ "ssl_bc_hsk_err_str", smp_fetch_ssl_fc_hsk_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
{ "ssl_bc_err", smp_fetch_ssl_fc_err, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
{ "ssl_bc_err_str", smp_fetch_ssl_fc_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
{ "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
@ -1751,8 +1751,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, ARG1(0,SINT), NULL, SMP_T_BIN, SMP_USE_L5CLI },
{ "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, ARG1(0,SINT), 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_fc_err", smp_fetch_ssl_fc_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_fc_err_str", smp_fetch_ssl_fc_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_protocol_hello_id",smp_fetch_ssl_fc_protocol_hello_id,0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
{ "ssl_fc_extlist_bin", smp_fetch_ssl_fc_ext_bin, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_eclist_bin", smp_fetch_ssl_fc_ecl_bin, ARG1(0,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },

View File

@ -5427,7 +5427,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;
ctx->error_code = 0;
/* Only work with sockets for now, this should be adapted when we'll
* add QUIC support.
@ -5706,8 +5706,8 @@ 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 (!ctx->error_code)
ctx->error_code = ERR_peek_error();
if (ret == SSL_ERROR_WANT_WRITE) {
/* SSL handshake needs to write, L4 connection may not be ready */