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
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)
{ "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 },
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.
/* 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))