]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: Add new ssl_fc_hsk_err sample fetch
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 29 Jul 2021 07:45:51 +0000 (09:45 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Thu, 29 Jul 2021 13:40:45 +0000 (15:40 +0200)
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.

doc/configuration.txt
include/haproxy/ssl_sock-t.h
src/ssl_sample.c
src/ssl_sock.c

index b3ac72be62ec0c60e63931018f7f1b8777a80bce..cd40d1cde2c15e19bdc4833184bd749421487a7d 100644 (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
index 98390113f8f291ad364dc526234319a4e11629fd..5acedcfc5d336008d19607e82551467b47bac622 100644 (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 */
 
index d6315267f9476b271be1201c6144d56250c623f8..8bfea07f0b11fe02be933905917d047c56dbf8f5 100644 (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 },
index 997ab8de498a2d5157e79366614b78600d49334e..ba61243aca5730d777b08d6fe21e6a70e7fccbb9 100644 (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 @@ check_error:
                /* 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))